From 44e9dc83e96cefdf1c6eef45812cd80a3017b44e Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Dec 2021 15:38:30 +0800 Subject: [PATCH] Upgrade gperftools to 2.9 for GCP/GMC/GMP/GMD. (#2247) --- trunk/3rdparty/README.md | 6 +- trunk/3rdparty/gperftools-2-fit/AUTHORS | 2 + trunk/3rdparty/gperftools-2-fit/COPYING | 28 + trunk/3rdparty/gperftools-2-fit/ChangeLog | 14434 ++++++++++ trunk/3rdparty/gperftools-2-fit/ChangeLog.old | 646 + trunk/3rdparty/gperftools-2-fit/INSTALL | 564 + trunk/3rdparty/gperftools-2-fit/Makefile.am | 1508 + trunk/3rdparty/gperftools-2-fit/Makefile.in | 8288 ++++++ trunk/3rdparty/gperftools-2-fit/NEWS | 1193 + trunk/3rdparty/gperftools-2-fit/README | 279 + .../gperftools-2-fit/README_windows.txt | 120 + trunk/3rdparty/gperftools-2-fit/TODO | 47 + trunk/3rdparty/gperftools-2-fit/aclocal.m4 | 1181 + .../benchmark/binary_trees.cc | 108 + .../benchmark/malloc_bench.cc | 293 + .../benchmark/run_benchmark.c | 112 + .../benchmark/run_benchmark.h | 43 + trunk/3rdparty/gperftools-2-fit/compile | 348 + trunk/3rdparty/gperftools-2-fit/config.guess | 1480 + trunk/3rdparty/gperftools-2-fit/config.sub | 1801 ++ trunk/3rdparty/gperftools-2-fit/configure | 22674 ++++++++++++++++ trunk/3rdparty/gperftools-2-fit/configure.ac | 657 + trunk/3rdparty/gperftools-2-fit/depcomp | 791 + .../docs/cpuprofile-fileformat.html | 264 + .../gperftools-2-fit/docs/cpuprofile.html | 536 + .../gperftools-2-fit/docs/designstyle.css | 109 + .../gperftools-2-fit/docs/heap-example1.png | Bin 0 -> 37619 bytes .../gperftools-2-fit/docs/heap_checker.html | 534 + .../gperftools-2-fit/docs/heapprofile.html | 391 + .../3rdparty/gperftools-2-fit/docs/index.html | 20 + .../gperftools-2-fit/docs/overview.dot | 15 + .../gperftools-2-fit/docs/overview.gif | Bin 0 -> 6472 bytes .../gperftools-2-fit/docs/pageheap.dot | 25 + .../gperftools-2-fit/docs/pageheap.gif | Bin 0 -> 5942 bytes .../gperftools-2-fit/docs/pprof-test-big.gif | Bin 0 -> 111566 bytes .../gperftools-2-fit/docs/pprof-test.gif | Bin 0 -> 56995 bytes .../docs/pprof-vsnprintf-big.gif | Bin 0 -> 100721 bytes .../gperftools-2-fit/docs/pprof-vsnprintf.gif | Bin 0 -> 31054 bytes trunk/3rdparty/gperftools-2-fit/docs/pprof.1 | 131 + .../gperftools-2-fit/docs/pprof.see_also | 11 + .../docs/pprof_remote_servers.html | 260 + .../gperftools-2-fit/docs/spanmap.dot | 22 + .../gperftools-2-fit/docs/spanmap.gif | Bin 0 -> 8482 bytes .../gperftools-2-fit/docs/t-test1.times.txt | 480 + ...loc-opspercpusec.vs.threads.1024.bytes.png | Bin 0 -> 1882 bytes ...lloc-opspercpusec.vs.threads.128.bytes.png | Bin 0 -> 1731 bytes ...c-opspercpusec.vs.threads.131072.bytes.png | Bin 0 -> 1314 bytes ...oc-opspercpusec.vs.threads.16384.bytes.png | Bin 0 -> 1815 bytes ...loc-opspercpusec.vs.threads.2048.bytes.png | Bin 0 -> 1877 bytes ...lloc-opspercpusec.vs.threads.256.bytes.png | Bin 0 -> 1838 bytes ...oc-opspercpusec.vs.threads.32768.bytes.png | Bin 0 -> 1516 bytes ...loc-opspercpusec.vs.threads.4096.bytes.png | Bin 0 -> 2005 bytes ...lloc-opspercpusec.vs.threads.512.bytes.png | Bin 0 -> 1683 bytes ...alloc-opspercpusec.vs.threads.64.bytes.png | Bin 0 -> 1656 bytes ...oc-opspercpusec.vs.threads.65536.bytes.png | Bin 0 -> 1498 bytes ...loc-opspercpusec.vs.threads.8192.bytes.png | Bin 0 -> 1912 bytes .../tcmalloc-opspersec.vs.size.1.threads.png | Bin 0 -> 1689 bytes .../tcmalloc-opspersec.vs.size.12.threads.png | Bin 0 -> 2216 bytes .../tcmalloc-opspersec.vs.size.16.threads.png | Bin 0 -> 2010 bytes .../tcmalloc-opspersec.vs.size.2.threads.png | Bin 0 -> 2163 bytes .../tcmalloc-opspersec.vs.size.20.threads.png | Bin 0 -> 2147 bytes .../tcmalloc-opspersec.vs.size.3.threads.png | Bin 0 -> 2270 bytes .../tcmalloc-opspersec.vs.size.4.threads.png | Bin 0 -> 2174 bytes .../tcmalloc-opspersec.vs.size.5.threads.png | Bin 0 -> 1995 bytes .../tcmalloc-opspersec.vs.size.8.threads.png | Bin 0 -> 2156 bytes .../gperftools-2-fit/docs/tcmalloc.html | 778 + .../gperftools-2-fit/docs/threadheap.dot | 21 + .../gperftools-2-fit/docs/threadheap.gif | Bin 0 -> 7571 bytes .../3rdparty/gperftools-2-fit/gperftools.sln | 307 + trunk/3rdparty/gperftools-2-fit/install-sh | 541 + trunk/3rdparty/gperftools-2-fit/libtool | 11911 ++++++++ trunk/3rdparty/gperftools-2-fit/ltmain.sh | 11251 ++++++++ .../gperftools-2-fit/m4/ac_have_attribute.m4 | 16 + .../gperftools-2-fit/m4/acx_nanosleep.m4 | 35 + .../gperftools-2-fit/m4/acx_pthread.m4 | 397 + .../m4/ax_cxx_compile_stdcxx.m4 | 948 + .../m4/ax_generate_changelog.m4 | 99 + .../gperftools-2-fit/m4/install_prefix.m4 | 8 + trunk/3rdparty/gperftools-2-fit/m4/libtool.m4 | 8394 ++++++ .../3rdparty/gperftools-2-fit/m4/ltoptions.m4 | 437 + trunk/3rdparty/gperftools-2-fit/m4/ltsugar.m4 | 124 + .../3rdparty/gperftools-2-fit/m4/ltversion.m4 | 23 + .../gperftools-2-fit/m4/lt~obsolete.m4 | 99 + .../gperftools-2-fit/m4/pc_from_ucontext.m4 | 112 + .../m4/program_invocation_name.m4 | 19 + trunk/3rdparty/gperftools-2-fit/missing | 215 + .../3rdparty/gperftools-2-fit/packages/deb.sh | 74 + .../gperftools-2-fit/packages/deb/README | 7 + .../gperftools-2-fit/packages/deb/changelog | 208 + .../gperftools-2-fit/packages/deb/compat | 1 + .../gperftools-2-fit/packages/deb/control | 25 + .../gperftools-2-fit/packages/deb/copyright | 38 + .../gperftools-2-fit/packages/deb/docs | 47 + .../packages/deb/libgperftools-dev.dirs | 5 + .../packages/deb/libgperftools-dev.install | 12 + .../packages/deb/libgperftools0.dirs | 2 + .../packages/deb/libgperftools0.install | 4 + .../packages/deb/libgperftools0.manpages | 1 + .../gperftools-2-fit/packages/deb/rules | 117 + .../3rdparty/gperftools-2-fit/packages/rpm.sh | 86 + .../gperftools-2-fit/packages/rpm/rpm.spec | 77 + .../3rdparty/gperftools-2-fit/pprof-symbolize | 5580 ++++ .../gperftools-2-fit/src/addressmap-inl.h | 422 + .../src/base/arm_instruction_set_select.h | 85 + .../base/atomicops-internals-arm-generic.h | 209 + .../src/base/atomicops-internals-arm-v6plus.h | 310 + .../src/base/atomicops-internals-gcc.h | 183 + .../src/base/atomicops-internals-linuxppc.h | 405 + .../src/base/atomicops-internals-macosx.h | 341 + .../src/base/atomicops-internals-mips.h | 299 + .../src/base/atomicops-internals-windows.h | 428 + .../src/base/atomicops-internals-x86.cc | 112 + .../src/base/atomicops-internals-x86.h | 353 + .../gperftools-2-fit/src/base/atomicops.h | 363 + .../gperftools-2-fit/src/base/basictypes.h | 440 + .../src/base/commandlineflags.h | 175 + .../src/base/dynamic_annotations.c | 64 + .../src/base/dynamic_annotations.h | 86 + .../src/base/elf_mem_image.cc | 434 + .../gperftools-2-fit/src/base/elf_mem_image.h | 135 + .../gperftools-2-fit/src/base/elfcore.h | 135 + .../gperftools-2-fit/src/base/googleinit.h | 74 + .../src/base/linux_syscall_support.h | 3017 ++ .../gperftools-2-fit/src/base/linuxthreads.cc | 707 + .../gperftools-2-fit/src/base/linuxthreads.h | 55 + .../gperftools-2-fit/src/base/logging.cc | 108 + .../gperftools-2-fit/src/base/logging.h | 259 + .../src/base/low_level_alloc.cc | 580 + .../src/base/low_level_alloc.h | 120 + .../gperftools-2-fit/src/base/simple_mutex.h | 332 + .../gperftools-2-fit/src/base/spinlock.cc | 129 + .../gperftools-2-fit/src/base/spinlock.h | 132 + .../src/base/spinlock_internal.cc | 102 + .../src/base/spinlock_internal.h | 51 + .../src/base/spinlock_linux-inl.h | 103 + .../src/base/spinlock_posix-inl.h | 63 + .../src/base/spinlock_win32-inl.h | 54 + .../gperftools-2-fit/src/base/stl_allocator.h | 98 + .../gperftools-2-fit/src/base/sysinfo.cc | 878 + .../gperftools-2-fit/src/base/sysinfo.h | 230 + .../src/base/thread_annotations.h | 133 + .../gperftools-2-fit/src/base/thread_lister.c | 84 + .../gperftools-2-fit/src/base/thread_lister.h | 83 + .../gperftools-2-fit/src/base/vdso_support.cc | 143 + .../gperftools-2-fit/src/base/vdso_support.h | 137 + .../gperftools-2-fit/src/central_freelist.cc | 384 + .../gperftools-2-fit/src/central_freelist.h | 211 + trunk/3rdparty/gperftools-2-fit/src/common.cc | 291 + trunk/3rdparty/gperftools-2-fit/src/common.h | 309 + .../3rdparty/gperftools-2-fit/src/config.h.in | 279 + .../src/config_for_unittests.h | 65 + .../gperftools-2-fit/src/debugallocation.cc | 1583 ++ .../gperftools-2-fit/src/emergency_malloc.cc | 169 + .../gperftools-2-fit/src/emergency_malloc.h | 60 + .../src/emergency_malloc_for_stacktrace.cc | 48 + .../src/fake_stacktrace_scope.cc | 39 + .../gperftools-2-fit/src/getenv_safe.h | 63 + trunk/3rdparty/gperftools-2-fit/src/getpc.h | 195 + .../src/google/heap-checker.h | 36 + .../src/google/heap-profiler.h | 37 + .../src/google/malloc_extension.h | 36 + .../src/google/malloc_extension_c.h | 37 + .../gperftools-2-fit/src/google/malloc_hook.h | 36 + .../src/google/malloc_hook_c.h | 37 + .../gperftools-2-fit/src/google/profiler.h | 37 + .../gperftools-2-fit/src/google/stacktrace.h | 36 + .../gperftools-2-fit/src/google/tcmalloc.h | 37 + .../src/gperftools/heap-checker.h | 422 + .../src/gperftools/heap-profiler.h | 105 + .../src/gperftools/malloc_extension.h | 446 + .../src/gperftools/malloc_extension_c.h | 101 + .../src/gperftools/malloc_hook.h | 359 + .../src/gperftools/malloc_hook_c.h | 173 + .../gperftools-2-fit/src/gperftools/nallocx.h | 37 + .../src/gperftools/profiler.h | 173 + .../src/gperftools/stacktrace.h | 117 + .../src/gperftools/tcmalloc.h.in | 163 + .../gperftools-2-fit/src/heap-checker-bcad.cc | 93 + .../gperftools-2-fit/src/heap-checker.cc | 2388 ++ .../gperftools-2-fit/src/heap-profile-stats.h | 78 + .../src/heap-profile-table.cc | 629 + .../gperftools-2-fit/src/heap-profile-table.h | 399 + .../gperftools-2-fit/src/heap-profiler.cc | 622 + .../gperftools-2-fit/src/internal_logging.cc | 192 + .../gperftools-2-fit/src/internal_logging.h | 144 + .../gperftools-2-fit/src/libc_override.h | 99 + .../src/libc_override_gcc_and_weak.h | 244 + .../src/libc_override_glibc.h | 92 + .../gperftools-2-fit/src/libc_override_osx.h | 308 + .../src/libc_override_redefine.h | 131 + .../gperftools-2-fit/src/linked_list.h | 115 + .../gperftools-2-fit/src/malloc_extension.cc | 388 + .../gperftools-2-fit/src/malloc_hook-inl.h | 249 + .../gperftools-2-fit/src/malloc_hook.cc | 711 + .../src/malloc_hook_mmap_freebsd.h | 135 + .../src/malloc_hook_mmap_linux.h | 250 + .../src/maybe_emergency_malloc.h | 55 + .../gperftools-2-fit/src/maybe_threads.cc | 177 + .../gperftools-2-fit/src/maybe_threads.h | 61 + .../gperftools-2-fit/src/memfs_malloc.cc | 279 + .../gperftools-2-fit/src/memory_region_map.cc | 838 + .../gperftools-2-fit/src/memory_region_map.h | 416 + .../gperftools-2-fit/src/packed-cache-inl.h | 216 + .../gperftools-2-fit/src/page_heap.cc | 718 + .../3rdparty/gperftools-2-fit/src/page_heap.h | 358 + .../src/page_heap_allocator.h | 179 + trunk/3rdparty/gperftools-2-fit/src/pagemap.h | 328 + trunk/3rdparty/gperftools-2-fit/src/pprof | 5580 ++++ .../gperftools-2-fit/src/profile-handler.cc | 599 + .../gperftools-2-fit/src/profile-handler.h | 142 + .../gperftools-2-fit/src/profiledata.cc | 332 + .../gperftools-2-fit/src/profiledata.h | 184 + .../3rdparty/gperftools-2-fit/src/profiler.cc | 434 + .../gperftools-2-fit/src/raw_printer.cc | 72 + .../gperftools-2-fit/src/raw_printer.h | 90 + .../3rdparty/gperftools-2-fit/src/sampler.cc | 134 + trunk/3rdparty/gperftools-2-fit/src/sampler.h | 232 + trunk/3rdparty/gperftools-2-fit/src/span.cc | 90 + trunk/3rdparty/gperftools-2-fit/src/span.h | 161 + .../gperftools-2-fit/src/stack_trace_table.cc | 123 + .../gperftools-2-fit/src/stack_trace_table.h | 85 + .../gperftools-2-fit/src/stacktrace.cc | 396 + .../gperftools-2-fit/src/stacktrace_arm-inl.h | 148 + .../src/stacktrace_generic-inl.h | 84 + .../src/stacktrace_generic_fp-inl.h | 222 + .../src/stacktrace_impl_setup-inl.h | 94 + .../src/stacktrace_instrument-inl.h | 155 + .../src/stacktrace_libgcc-inl.h | 111 + .../src/stacktrace_libunwind-inl.h | 152 + .../src/stacktrace_powerpc-darwin-inl.h | 163 + .../src/stacktrace_powerpc-inl.h | 176 + .../src/stacktrace_powerpc-linux-inl.h | 231 + .../src/stacktrace_win32-inl.h | 107 + .../gperftools-2-fit/src/stacktrace_x86-inl.h | 354 + .../gperftools-2-fit/src/static_vars.cc | 152 + .../gperftools-2-fit/src/static_vars.h | 126 + .../gperftools-2-fit/src/symbolize.cc | 298 + .../3rdparty/gperftools-2-fit/src/symbolize.h | 84 + .../gperftools-2-fit/src/system-alloc.cc | 555 + .../gperftools-2-fit/src/system-alloc.h | 92 + .../3rdparty/gperftools-2-fit/src/tcmalloc.cc | 2225 ++ .../3rdparty/gperftools-2-fit/src/tcmalloc.h | 70 + .../gperftools-2-fit/src/tcmalloc_guard.h | 49 + .../src/tests/addressmap_unittest.cc | 174 + .../src/tests/atomicops_unittest.cc | 152 + .../src/tests/current_allocated_bytes_test.cc | 64 + .../src/tests/debugallocation_test.cc | 333 + .../src/tests/debugallocation_test.sh | 98 + .../src/tests/frag_unittest.cc | 133 + .../gperftools-2-fit/src/tests/getpc_test.cc | 123 + .../src/tests/heap-checker-death_unittest.sh | 176 + .../src/tests/heap-checker_unittest.cc | 1538 ++ .../src/tests/heap-checker_unittest.sh | 89 + .../src/tests/heap-profiler_unittest.cc | 168 + .../src/tests/heap-profiler_unittest.sh | 147 + .../large_heap_fragmentation_unittest.cc | 62 + .../src/tests/low_level_alloc_unittest.cc | 197 + .../src/tests/malloc_extension_c_test.c | 182 + .../src/tests/malloc_extension_test.cc | 98 + .../src/tests/malloc_hook_test.cc | 367 + .../src/tests/markidle_unittest.cc | 127 + .../src/tests/maybe_threads_unittest.sh | 79 + .../src/tests/memalign_unittest.cc | 221 + .../src/tests/packed-cache_test.cc | 82 + .../src/tests/page_heap_test.cc | 202 + .../src/tests/pagemap_unittest.cc | 178 + .../src/tests/profile-handler_unittest.cc | 398 + .../src/tests/profiledata_unittest.cc | 612 + .../src/tests/profiler_unittest.cc | 147 + .../src/tests/profiler_unittest.sh | 269 + .../src/tests/raw_printer_test.cc | 64 + .../src/tests/realloc_unittest.cc | 125 + .../src/tests/sampler_test.cc | 631 + .../src/tests/sampling_test.cc | 83 + .../src/tests/sampling_test.sh | 94 + .../src/tests/simple_compat_test.cc | 71 + .../src/tests/stack_trace_table_test.cc | 93 + .../src/tests/stacktrace_unittest.cc | 298 + .../src/tests/system-alloc_unittest.cc | 161 + .../src/tests/tcmalloc_large_unittest.cc | 139 + .../src/tests/tcmalloc_unittest.cc | 1669 ++ .../src/tests/tcmalloc_unittest.sh | 84 + .../gperftools-2-fit/src/tests/testutil.cc | 224 + .../gperftools-2-fit/src/tests/testutil.h | 73 + .../src/tests/thread_dealloc_unittest.cc | 84 + .../gperftools-2-fit/src/thread_cache.cc | 529 + .../gperftools-2-fit/src/thread_cache.h | 510 + .../gperftools-2-fit/src/windows/TODO | 86 + .../src/windows/addr2line-pdb.c | 183 + .../src/windows/auto_testing_hook.h | 156 + .../gperftools-2-fit/src/windows/config.h | 306 + .../src/windows/get_mangled_names.cc | 65 + .../src/windows/gperftools/tcmalloc.h | 155 + .../src/windows/gperftools/tcmalloc.h.in | 155 + .../src/windows/ia32_modrm_map.cc | 122 + .../src/windows/ia32_opcode_map.cc | 1220 + .../gperftools-2-fit/src/windows/mingw.h | 72 + .../src/windows/mini_disassembler.cc | 432 + .../src/windows/mini_disassembler.h | 198 + .../src/windows/mini_disassembler_types.h | 237 + .../gperftools-2-fit/src/windows/nm-pdb.c | 274 + .../src/windows/override_functions.cc | 173 + .../src/windows/patch_functions.cc | 1098 + .../gperftools-2-fit/src/windows/port.cc | 249 + .../gperftools-2-fit/src/windows/port.h | 477 + .../src/windows/preamble_patcher.cc | 736 + .../src/windows/preamble_patcher.h | 620 + .../src/windows/preamble_patcher_test.cc | 368 + .../src/windows/preamble_patcher_with_stub.cc | 302 + .../src/windows/shortproc.asm | 169 + .../src/windows/system-alloc.cc | 205 + trunk/3rdparty/gperftools-2-fit/test-driver | 150 + .../addr2line-pdb/addr2line-pdb.vcxproj | 191 + .../addressmap_unittest.vcxproj | 229 + .../current_allocated_bytes_test.vcxproj | 215 + .../frag_unittest/frag_unittest.vcxproj | 213 + .../libtcmalloc_minimal.vcxproj | 297 + .../low_level_alloc_unittest.vcxproj | 238 + .../malloc_extension_test.vcxproj | 216 + .../malloc_hook_test/malloc_hook_test.vcxproj | 217 + .../markidle_unittest.vcxproj | 215 + .../vsprojects/nm-pdb/nm-pdb.vcxproj | 191 + .../packed-cache_test.vcxproj | 229 + .../page_heap_test/page_heap_test.vcxproj | 229 + .../pagemap_unittest/pagemap_unittest.vcxproj | 215 + .../preamble_patcher_test.vcxproj | 234 + .../realloc_unittest/realloc_unittest.vcxproj | 214 + .../sampler_test/sampler_test.vcxproj | 215 + .../stack_trace_table_test.vcxproj | 214 + .../system-alloc_unittest.vcxproj | 215 + .../tcmalloc_minimal_large_unittest.vcxproj | 213 + .../tcmalloc_minimal_unittest.vcxproj | 215 + .../thread_dealloc_unittest.vcxproj | 215 + trunk/3rdparty/gperftools-2.1.zip | Bin 1624882 -> 0 bytes trunk/auto/depends.sh | 16 +- .../research/gperftools/cpu-profiler/Makefile | 2 +- .../research/gperftools/heap-checker/Makefile | 4 +- .../gperftools/heap-checker/heap_checker.cc | 6 +- .../research/gperftools/heap-defense/Makefile | 10 + .../gperftools/heap-defense/heap_defense.cc | 30 + .../gperftools/heap-profiler/Makefile | 4 +- .../gperftools/memory.error.notcmalloc.cpp | 16 - .../gperftools/memory.error.tcmalloc.cpp | 16 - trunk/src/app/srs_app_server.cpp | 2 +- trunk/src/core/srs_core_autofree.hpp | 64 +- trunk/src/protocol/srs_service_st.cpp | 2 +- 346 files changed, 169666 insertions(+), 78 deletions(-) create mode 100644 trunk/3rdparty/gperftools-2-fit/AUTHORS create mode 100644 trunk/3rdparty/gperftools-2-fit/COPYING create mode 100644 trunk/3rdparty/gperftools-2-fit/ChangeLog create mode 100644 trunk/3rdparty/gperftools-2-fit/ChangeLog.old create mode 100644 trunk/3rdparty/gperftools-2-fit/INSTALL create mode 100644 trunk/3rdparty/gperftools-2-fit/Makefile.am create mode 100644 trunk/3rdparty/gperftools-2-fit/Makefile.in create mode 100644 trunk/3rdparty/gperftools-2-fit/NEWS create mode 100644 trunk/3rdparty/gperftools-2-fit/README create mode 100644 trunk/3rdparty/gperftools-2-fit/README_windows.txt create mode 100644 trunk/3rdparty/gperftools-2-fit/TODO create mode 100644 trunk/3rdparty/gperftools-2-fit/aclocal.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/benchmark/binary_trees.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/benchmark/malloc_bench.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.c create mode 100644 trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.h create mode 100755 trunk/3rdparty/gperftools-2-fit/compile create mode 100755 trunk/3rdparty/gperftools-2-fit/config.guess create mode 100755 trunk/3rdparty/gperftools-2-fit/config.sub create mode 100755 trunk/3rdparty/gperftools-2-fit/configure create mode 100644 trunk/3rdparty/gperftools-2-fit/configure.ac create mode 100755 trunk/3rdparty/gperftools-2-fit/depcomp create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/cpuprofile-fileformat.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/cpuprofile.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/designstyle.css create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/heap-example1.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/heap_checker.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/heapprofile.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/index.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/overview.dot create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/overview.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pageheap.dot create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pageheap.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof-test-big.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof-test.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf-big.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof.1 create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof.see_also create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/pprof_remote_servers.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/spanmap.dot create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/spanmap.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/t-test1.times.txt create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.1.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.12.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.16.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.2.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.20.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.3.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.4.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.5.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.8.threads.png create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/tcmalloc.html create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/threadheap.dot create mode 100644 trunk/3rdparty/gperftools-2-fit/docs/threadheap.gif create mode 100644 trunk/3rdparty/gperftools-2-fit/gperftools.sln create mode 100755 trunk/3rdparty/gperftools-2-fit/install-sh create mode 100755 trunk/3rdparty/gperftools-2-fit/libtool create mode 100755 trunk/3rdparty/gperftools-2-fit/ltmain.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ac_have_attribute.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/acx_nanosleep.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/acx_pthread.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ax_cxx_compile_stdcxx.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ax_generate_changelog.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/install_prefix.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/libtool.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ltoptions.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ltsugar.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/ltversion.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/lt~obsolete.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/pc_from_ucontext.m4 create mode 100644 trunk/3rdparty/gperftools-2-fit/m4/program_invocation_name.m4 create mode 100755 trunk/3rdparty/gperftools-2-fit/missing create mode 100755 trunk/3rdparty/gperftools-2-fit/packages/deb.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/README create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/changelog create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/compat create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/control create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/copyright create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/docs create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.dirs create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.install create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.dirs create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.install create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.manpages create mode 100755 trunk/3rdparty/gperftools-2-fit/packages/deb/rules create mode 100755 trunk/3rdparty/gperftools-2-fit/packages/rpm.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/packages/rpm/rpm.spec create mode 100755 trunk/3rdparty/gperftools-2-fit/pprof-symbolize create mode 100644 trunk/3rdparty/gperftools-2-fit/src/addressmap-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/arm_instruction_set_select.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-generic.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-v6plus.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-gcc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-linuxppc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-macosx.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-mips.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-windows.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/atomicops.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/basictypes.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/commandlineflags.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.c create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/elfcore.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/googleinit.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/linux_syscall_support.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/logging.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/logging.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/simple_mutex.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock_linux-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock_posix-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/spinlock_win32-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/stl_allocator.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/thread_annotations.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.c create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/central_freelist.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/central_freelist.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/common.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/common.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/config.h.in create mode 100644 trunk/3rdparty/gperftools-2-fit/src/config_for_unittests.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/debugallocation.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/emergency_malloc_for_stacktrace.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/fake_stacktrace_scope.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/getenv_safe.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/getpc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/heap-checker.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/heap-profiler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension_c.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook_c.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/profiler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/stacktrace.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/google/tcmalloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-checker.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-profiler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension_c.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook_c.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/nallocx.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/profiler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/stacktrace.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/gperftools/tcmalloc.h.in create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-checker-bcad.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-checker.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-profile-stats.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/heap-profiler.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/internal_logging.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/internal_logging.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/libc_override.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/libc_override_gcc_and_weak.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/libc_override_glibc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/libc_override_osx.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/libc_override_redefine.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/linked_list.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/malloc_extension.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/malloc_hook-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/malloc_hook.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_freebsd.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_linux.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/maybe_emergency_malloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/maybe_threads.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/maybe_threads.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/memfs_malloc.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/memory_region_map.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/memory_region_map.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/packed-cache-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/page_heap.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/page_heap.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/page_heap_allocator.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/pagemap.h create mode 100755 trunk/3rdparty/gperftools-2-fit/src/pprof create mode 100644 trunk/3rdparty/gperftools-2-fit/src/profile-handler.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/profile-handler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/profiledata.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/profiledata.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/profiler.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/raw_printer.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/raw_printer.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/sampler.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/sampler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/span.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/span.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_arm-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic_fp-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_impl_setup-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_instrument-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_libgcc-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_libunwind-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-darwin-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-linux-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_win32-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/stacktrace_x86-inl.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/static_vars.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/static_vars.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/symbolize.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/symbolize.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/system-alloc.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/system-alloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tcmalloc.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tcmalloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tcmalloc_guard.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/addressmap_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/atomicops_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/current_allocated_bytes_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/frag_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/getpc_test.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker-death_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/large_heap_fragmentation_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/low_level_alloc_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_c_test.c create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/malloc_hook_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/markidle_unittest.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/maybe_threads_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/memalign_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/packed-cache_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/page_heap_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/pagemap_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/profile-handler_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/profiledata_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/raw_printer_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/realloc_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/sampler_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/simple_compat_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/stack_trace_table_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/stacktrace_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/system-alloc_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_large_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.sh create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/testutil.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/testutil.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/tests/thread_dealloc_unittest.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/thread_cache.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/thread_cache.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/TODO create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/addr2line-pdb.c create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/auto_testing_hook.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/config.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/get_mangled_names.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h.in create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/ia32_modrm_map.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/ia32_opcode_map.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/mingw.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler_types.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/nm-pdb.c create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/override_functions.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/patch_functions.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/port.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/port.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.h create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_test.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_with_stub.cc create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/shortproc.asm create mode 100644 trunk/3rdparty/gperftools-2-fit/src/windows/system-alloc.cc create mode 100755 trunk/3rdparty/gperftools-2-fit/test-driver create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/addr2line-pdb/addr2line-pdb.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/addressmap_unittest/addressmap_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/frag_unittest/frag_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_extension_test/malloc_extension_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_hook_test/malloc_hook_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/markidle_unittest/markidle_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/nm-pdb/nm-pdb.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/packed-cache_test/packed-cache_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/page_heap_test/page_heap_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/pagemap_unittest/pagemap_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/realloc_unittest/realloc_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/sampler_test/sampler_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj create mode 100644 trunk/3rdparty/gperftools-2-fit/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj delete mode 100644 trunk/3rdparty/gperftools-2.1.zip create mode 100644 trunk/research/gperftools/heap-defense/Makefile create mode 100644 trunk/research/gperftools/heap-defense/heap_defense.cc delete mode 100644 trunk/research/gperftools/memory.error.notcmalloc.cpp delete mode 100644 trunk/research/gperftools/memory.error.tcmalloc.cpp diff --git a/trunk/3rdparty/README.md b/trunk/3rdparty/README.md index bec290e04..355f0938d 100644 --- a/trunk/3rdparty/README.md +++ b/trunk/3rdparty/README.md @@ -41,10 +41,10 @@ opus-1.3.1.tar.gz gtest-1.6.0.zip * google test framework. * https://code.google.com/p/googletest/downloads/list - -gperftools-2.1.zip + +gperftools-2-fit * gperf tools for performance benchmark. -* https://github.com/gperftools/gperftools/releases +* https://github.com/gperftools/gperftools/releases/tag/gperftools-2.9.1 st-srs st-1.9.zip diff --git a/trunk/3rdparty/gperftools-2-fit/AUTHORS b/trunk/3rdparty/gperftools-2-fit/AUTHORS new file mode 100644 index 000000000..3995ed4cf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/AUTHORS @@ -0,0 +1,2 @@ +google-perftools@googlegroups.com + diff --git a/trunk/3rdparty/gperftools-2-fit/COPYING b/trunk/3rdparty/gperftools-2-fit/COPYING new file mode 100644 index 000000000..e4956cfd9 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/COPYING @@ -0,0 +1,28 @@ +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. diff --git a/trunk/3rdparty/gperftools-2-fit/ChangeLog b/trunk/3rdparty/gperftools-2-fit/ChangeLog new file mode 100644 index 000000000..49ad492ca --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/ChangeLog @@ -0,0 +1,14434 @@ +commit f7c6fb6c8e99d6b1b725e5994373bcd19ffdf8fd +Author: Aliaksey Kandratsenka +Date: Tue Mar 2 19:32:07 2021 -0800 + + bump version to 2.9.1 + +M CMakeLists.txt +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit c2f60400a86a5211bf009941bf1ccf9b2947a7c1 +Author: Aliaksey Kandratsenka +Date: Sun Feb 28 17:52:17 2021 -0800 + + prefer backtrace() on OSX + + It seems to work and _Unwind_Backtrace which is configured otherwise + doesn't. + +M CMakeLists.txt +M cmake/DefineTargetVariables.cmake +M configure.ac + +commit a015377a54eb09fca4b893ae530187a705164df5 +Author: Aliaksey Kandratsenka +Date: Sun Feb 28 17:47:56 2021 -0800 + + Set tcmalloc heap limit prior to testing oom + + Otherwise it can take long time to OOM on osex. + +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc + +commit c939dd5531fd95e8af2181ac60e0b6e6230226c8 +Author: Aliaksey Kandratsenka +Date: Sun Feb 28 15:42:00 2021 -0800 + + correctly check sized delete hint when asserts are on + + We previously tested wrong assumption that larger than page size size + classes have addresses aligned on page size. New code is making proper + check of size class. + + Also added is unit test coverage for this previously failing + condition. And we now also run "assert-ful" unittests for big tcmalloc + too, not only tcmalloc_minimal configuration. + + This fixes github issue #1254 + +M .gitignore +M Makefile.am +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc + +commit 47b5b59ca9b62ee42cf30273cce463aa9cbba8c7 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 15:16:06 2021 -0800 + + bump version to 2.9 + +M CMakeLists.txt +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit d7cbc8c2ff4ab8dbdc411ab1f25eca459f88502e +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 14:55:15 2021 -0800 + + unbreak cmake build + + It was trying to use third_party/valgrind.h header which I recently + removed. + +M CMakeLists.txt + +commit be0bbdb3403685798a7c1d5acf6405d2635fba4c +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 13:48:11 2021 -0800 + + amputate various unused bits from elfcore.h + +M src/base/elfcore.h + +commit 42bab59f25dee53f91c0ba45e95b73754e197c20 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 13:35:43 2021 -0800 + + liberate profile handler from linux_syscall_support + + We can get thread's tid in more portable way via libc syscall wrapper. + +M src/profile-handler.cc + +commit 4629511e99f85fa8ca40fcbe105e014a725059d2 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 13:32:08 2021 -0800 + + liberate spinlock futex waits from linux_syscall_support includes + + We've been using libc syscall wrapper some time now. + +M src/base/spinlock_linux-inl.h + +commit 2e7094a86215118f3dcd3ad6f2c9099dc409ecc5 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 13:28:48 2021 -0800 + + liberate malloc_hook_mmap_linux.h from linux_syscall_support + + It was not used some time now, as we're rightfully trusting libc + syscall wrapper instead. + +M src/malloc_hook_mmap_linux.h + +commit 35301e2e59b30b7379981e60f3046124a2dfd68e +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 12:40:45 2021 -0800 + + add missing noopt wrappings around more operator new calls + + This fixes tests passing on clang which otherwise eliminates those + new/delete calls so checking for hooks being called failed. + +M src/tests/tcmalloc_unittest.cc + +commit fa412adfe38ffd3f545a0e10139bd20b38b688e9 +Author: Venkatesh Srinivas +Date: Wed Feb 17 17:50:43 2021 -0800 + + Fix thread-safety (annotalysis) annotations + + tcmalloc contains some thread-safety annotations; however those + annotations have not been exercised for some time, as they used + macros/attributes only supported by a legacy branch of gcc. + + Pull request #1251 converted those macros to support modern + versions of clang; this CR fixes the annotations that were + enabled. For the most part, this just requires re-enabling + annotations on member functions that take/release locks. For the + tcmalloc fork (pre-fork and post-fork) handlers, we mark the + functions as exempt from this analysis, as it takes a dynamic + number of locks. + +M src/base/low_level_alloc.cc +M src/base/spinlock.h +M src/central_freelist.h +M src/static_vars.cc + +commit cc496aecb81ee5966c865f3723743ff02046c5ad +Author: Venkatesh Srinivas +Date: Wed Feb 17 16:23:17 2021 -0800 + + tcmalloc: Switch thread-safety annotations to support clang + + tcmalloc contains its own copy of thread_annotations.h, wrapper + macros for static thread-safety analysis expressions. These thread- + safety expressions allow asserting (at compile time) that certain + locks are held or excluded or certain data is protected by specific + locks; they are checked at compile-time by recent versions of clang + or a gcc branch (https://gcc.gnu.org/wiki/ThreadSafetyAnnotation). + + Convert the #if-guard and macro names from the no-longer-supported + gcc branch's defines & macros to the versions supported by recent + versions of clang. + +M src/base/thread_annotations.h + +commit 96ba58e19b7b93fcf1db6a0551c9510296ce26da +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 23:18:57 2021 -0800 + + bump version to 2.9rc + +M CMakeLists.txt +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 9ce32aefa9c66698817be50e141c5a39fe3823c8 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 23:02:28 2021 -0800 + + upgrade test bot to xenial (ubuntu 16.04 LTS) + + Older glibc seemingly doesn't have right unwind info for signal frame, + so fails recently upgraded stacktrace_unittest. But since this version + is not supported anymore, lets just test newer glibc. + +M .travis.yml + +commit 91ff3114492f368a651ee790c8311eb6fadf3e8e +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 22:36:55 2021 -0800 + + don't default to generic_fp without frame pointers + + I.e. on x86-64 and riscv. + +M src/stacktrace.cc + +commit 4cf7dd0a7502849b117e15ad5eb1eb68eab4b6dc +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 22:28:34 2021 -0800 + + enable emergency_malloc on all architectures with mmap + + It is actually needed for libgcc backtracer from time to time. And + we've seen libunwind to need it too. Plus we've not heard of any + problems with it. So lets just always enable it. + + This should fix github issue #1248. + +M configure.ac + +commit 37087ec5360e821627155d3129f9b55a321a0001 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 21:37:20 2021 -0800 + + prefer libunwind on x86-64 even with -fno-omit-frame-pointer + + Libunwind is mostly safe on x86-64 and most of OS (e.g. libc) is + compiled without frame pointers anyways. Even when libc is built with + frame pointers, various libc asm routines (e.g. memcpy) are not. And + even for code built with frame pointers we actually sometimes get + SIGPROF inside function prologues, before frame pointer is + established. Which then causes imperfect backtraces. + + Libunwind should handle this all (when it doesn't crash or deadlock). + +M src/stacktrace.cc + +commit f4aa2a435eed63fc047448635f705a9c6037bd97 +Author: Aliaksey Kandratsenka +Date: Sun Feb 7 11:59:44 2021 -0800 + + implement generic frame pointer backtracer + + This supports frame pointer backtracing on x86-64, aarch64 and + riscv-s (should work for both 32 and 64 bits). + + Also added is detection of borked libunwind on aarch64-s. In this case + frame pointer unwinder is preferred. + +M Makefile.am +M src/stacktrace.cc +A src/stacktrace_generic_fp-inl.h +M src/tests/stacktrace_unittest.cc + +commit 17bab484aea43cf1a5247c823e036dfb52f5d92b +Author: Aliaksey Kandratsenka +Date: Sat Feb 6 13:21:12 2021 -0800 + + always respect --enable-frame-pointers + + Previously it only was respected on x86_64, but this days lots + of modern + ABIs are without frame pointers by default (e.g. arm64 and riscv, and + even older mips). + +M CMakeLists.txt +M Makefile.am +D cmake/CheckNoFPByDefault.cmake +M configure.ac + +commit 22c0eceddcf986a9b3f853b36d855acb38fa678f +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 16:29:14 2021 -0800 + + add emacs mode line annotations to remaining files + +M src/base/arm_instruction_set_select.h +M src/base/dynamic_annotations.c +M src/base/dynamic_annotations.h +M src/base/linuxthreads.h +M src/base/thread_annotations.h +M src/base/thread_lister.c +M src/base/vdso_support.cc +M src/base/vdso_support.h +M src/gperftools/heap-profiler.h +M src/gperftools/profiler.h +M src/gperftools/tcmalloc.h.in +M src/stacktrace_powerpc-darwin-inl.h +M src/tests/stacktrace_unittest.cc +M src/windows/addr2line-pdb.c +M src/windows/config.h +M src/windows/ia32_modrm_map.cc +M src/windows/ia32_opcode_map.cc +M src/windows/nm-pdb.c +M src/windows/patch_functions.cc +M src/windows/system-alloc.cc + +commit b12139ddbaa3e16ba491a24ce6fec51009e70cce +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 16:13:15 2021 -0800 + + delete-trailing-whitespace on all files + +M src/addressmap-inl.h +M src/base/atomicops-internals-gcc.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-windows.h +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/commandlineflags.h +M src/base/googleinit.h +M src/base/linuxthreads.cc +M src/base/logging.cc +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +M src/base/simple_mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/spinlock_linux-inl.h +M src/base/spinlock_posix-inl.h +M src/base/spinlock_win32-inl.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/thread_annotations.h +M src/base/vdso_support.cc +M src/common.cc +M src/config_for_unittests.h +M src/getenv_safe.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/google/tcmalloc.h +M src/gperftools/heap-profiler.h +M src/gperftools/malloc_extension.h +M src/gperftools/malloc_extension_c.h +M src/gperftools/malloc_hook.h +M src/gperftools/malloc_hook_c.h +M src/gperftools/profiler.h +M src/gperftools/stacktrace.h +M src/heap-checker-bcad.cc +M src/heap-profile-stats.h +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/maybe_threads.cc +M src/maybe_threads.h +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/pagemap.h +M src/profile-handler.cc +M src/profile-handler.h +M src/raw_printer.cc +M src/raw_printer.h +M src/sampler.cc +M src/sampler.h +M src/stacktrace_powerpc-inl.h +M src/symbolize.cc +M src/symbolize.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tests/addressmap_unittest.cc +M src/tests/atomicops_unittest.cc +M src/tests/frag_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/malloc_extension_c_test.c +M src/tests/malloc_extension_test.cc +M src/tests/markidle_unittest.cc +M src/tests/memalign_unittest.cc +M src/tests/pagemap_unittest.cc +M src/tests/profiler_unittest.cc +M src/tests/realloc_unittest.cc +M src/tests/sampler_test.cc +M src/tests/stacktrace_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_large_unittest.cc +M src/tests/testutil.cc +M src/tests/testutil.h +M src/tests/thread_dealloc_unittest.cc +M src/windows/get_mangled_names.cc +M src/windows/google/tcmalloc.h +M src/windows/ia32_modrm_map.cc +M src/windows/ia32_opcode_map.cc +M src/windows/mingw.h +M src/windows/mini_disassembler.cc +M src/windows/mini_disassembler.h +M src/windows/mini_disassembler_types.h +M src/windows/nm-pdb.c +M src/windows/override_functions.cc +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/preamble_patcher.cc +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_test.cc +M src/windows/preamble_patcher_with_stub.cc +M src/windows/system-alloc.cc + +commit 419c85814de497d6dfaf6f9a19d153138a7dec08 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 16:02:56 2021 -0800 + + amputate unused dynamic annotations support + +M CMakeLists.txt +M Makefile.am +M cmake/config.h.in +M configure.ac +M src/base/dynamic_annotations.c +M src/base/dynamic_annotations.h +M src/base/low_level_alloc.cc +M src/base/spinlock.h +M src/profile-handler.cc +D src/third_party/valgrind.h +M src/windows/config.h + +commit 73a72cdb6154ab7bdd49b1dde91349a30e8d7973 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 15:11:12 2021 -0800 + + don't check for snprintf + +M CMakeLists.txt +M cmake/config.h.in +M src/windows/config.h +M src/windows/mingw.h +M src/windows/port.h + +commit 95b52b0504a7cb2bce36d72b8bb0825833500b4c +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 15:02:57 2021 -0800 + + don't check for unused uname symbol + +M CMakeLists.txt +M cmake/config.h.in +M configure.ac +M src/windows/config.h + +commit 01c2697fac41a5d6175ad0da21d9d753f0b385a1 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 14:30:29 2021 -0800 + + amputate unused SleepForMilliseconds from sysinfo.{h,cc} + +M src/base/sysinfo.cc +M src/base/sysinfo.h + +commit ac68c97187e3729668ff5048c9bd27aae14e974d +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 14:25:49 2021 -0800 + + don't check for useless __builtin_stack_pointer + + It doesn't seem to be supported anyways, and we're not using it too. + +M CMakeLists.txt +M cmake/config.h.in +M configure.ac +M src/windows/config.h + +commit 7271bb72be08db491d3f0c60c1b0d5593cc1b5b5 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 14:22:08 2021 -0800 + + unbreak cmake check for TLS support + +M CMakeLists.txt + +commit 7c106ca241a344993f8011397de8004a224e094a +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 14:14:55 2021 -0800 + + don't bother checking for stl namespace and use std + + Because there are no compilers left that don't do std namespace. + +M CMakeLists.txt +M cmake/config.h.in +M configure.ac +D m4/namespaces.m4 +D m4/stl_namespace.m4 +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/tcmalloc.cc +M src/windows/config.h + +commit 0d6f32b9cef7ee044e55a746e7c76db62d23cd86 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 14:04:10 2021 -0800 + + use standard way to print size_t-sized ints + + I.e. just use zu/zd/zx instead of finding out right size and defining + PRI{u,x,d}S defines. Compilers have long caught up to this part of + standard. + +M cmake/config.h.in +M configure.ac +D m4/compiler_characteristics.m4 +M src/debugallocation.cc +M src/emergency_malloc.cc +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/memory_region_map.cc +M src/profiledata.cc +M src/tcmalloc.cc +M src/tests/markidle_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h + +commit 0c11d35f4a2a0f5f42ee684a3f5b27cbab8abae2 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 13:39:55 2021 -0800 + + amputate checking for __int64 + + Since everything supports stdint.h this days. + +M CMakeLists.txt +M cmake/config.h.in +M configure.ac +M src/windows/config.h +M src/windows/port.h + +commit 92718aaaeb08d139b346633333235bf2260d0848 +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 13:34:58 2021 -0800 + + amputate checking for conflict-signal.h + + It was never found or used. + +M CMakeLists.txt +M cmake/config.h.in +M src/profiler.cc +M src/windows/config.h + +commit 9bb2937261bca6c0257a8cfd62ff97f69c450acb +Author: Aliaksey Kandratsenka +Date: Sun Feb 14 13:33:10 2021 -0800 + + amputate checking for inline keyword support + + It is supported everywhere now. + +M CMakeLists.txt +M cmake/config.h.in +M configure.ac +M src/windows/config.h + +commit d9c4c3b481e641b719d3d790987ed7d094157bf2 +Author: Đoàn Trần Công Danh +Date: Fri Feb 12 19:21:18 2021 +0700 + + profile-handler: use documented sigev_notify_thread_id in sigevent + + sigevent(7) is documented to have sigev_notify_thread_id as its + member. + In glibc system, it's a macro expanded to the legacy _sigev_un._tid, + _sigev_un._tid is obviously an internal implementation detail as + signaled by its underscore prefix. And this macro was hidden inside + linux/signal.h in older version of glibc. + + On Linux that use musl libc, sigev_notify_thread_id is also a + macro, but + it's expanded to __sev_fields.sigev_notify_thread_id + + [alkondratenko@gmail.com: amputated broken linux/signal.h dependency] + [alkondratenko@gmail.com: see + https://github.com/gperftools/gperftools/pull/1250] + Signed-off-by: Aliaksey Kandratsenka + +M src/profile-handler.cc + +commit 43459feb33b87d3300e3b8b4917e5226678e4a0f +Author: Đoàn Trần Công Danh +Date: Sat Feb 13 17:35:20 2021 +0700 + + configure.ac: check for features.h once + +M configure.ac + +commit 290b123c01f6578391b20bb31849f26b02401112 +Author: Venkatesh Srinivas +Date: Mon Feb 8 12:32:23 2021 -0800 + + atomicops: Remove Acquire_Store / Release_Load + + gperftools' internal atomicops library included atomic + Release Load and Acquire Store operations; those operations + were unused and expressed ordering constraints that aren't + expressible in the C++ standard memory model. + + Remove them, to make a transition to C++11 atomics easier + and to avoid confusing use of them. + +M src/base/atomicops-internals-arm-generic.h +M src/base/atomicops-internals-arm-v6plus.h +M src/base/atomicops-internals-gcc.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-mips.h +M src/base/atomicops-internals-windows.h +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/tests/atomicops_unittest.cc + +commit 3b1c60cc4ea737ff151977dbcd164c5e2eb859fb +Author: SSE4 +Date: Wed Jan 27 11:15:56 2021 +0300 + + Add support for Elbrus 2000 (e2k) + +M cmake/PCFromUContext.cmake +M m4/pc_from_ucontext.m4 +M src/base/basictypes.h +M src/malloc_hook_mmap_linux.h + +commit c5747615da78f7c2d91112f2a6b6b4da4f18540a +Author: Jarno Rajahalme +Date: Fri Jan 29 09:54:18 2021 -0800 + + syscall: Mark x8 as clobbered + + Mark arm64 register x8 as clobbered by syscall body inline assembly as + it is being used to store the syscall number. Otherwise the compiler + may try to use it for some other purpose. + + This fix is derived from a resolution to clang Bugzilla report + https://bugs.llvm.org/show_bug.cgi?id=48798. See this report for a + minimal reproducer derived from the code fixed here as well as the + resolution. + + This should fix SEGFAULTs as reported in + https://github.com/envoyproxy/envoy/issues/14756. + + Fixes: #1241 + Signed-off-by: Jarno Rajahalme + +M src/base/linux_syscall_support.h + +commit d8eb315fb18f6fb0d6efa923401f166343727bc6 +Author: Aliaksey Kandratsenka +Date: Sun Dec 20 23:35:08 2020 -0800 + + bump version to 2.8.1 + +M CMakeLists.txt +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 6ed61f8e91ffc00310b253ad2c777c0e862bd742 +Author: Aliaksey Kandratsenka +Date: Sat Dec 19 19:14:50 2020 -0800 + + add note that cmake build is preliminary + +M CMakeLists.txt + +commit 6bbf2ed1501e27e215bb412b9b0b930921598bca +Author: okhowang(王沛文) +Date: Sat Sep 12 02:43:56 2020 +0800 + + Update cmake + +M CMakeLists.txt +M cmake/FindObjcopyWithWeaken.cmake +D cmake/GPerftoolsAddTarget.cmake +M cmake/config.h.in +A cmake/pkgconfig.pc +M cmake/tcmalloc.h.in +M src/tests/addressmap_unittest.cc +A src/windows/CMakeLists.txt + +commit 913d3eb7d7fc1c5cc025920d5699b528c268f0fa +Author: Isaac Hier +Date: Wed Nov 8 11:20:25 2017 -0500 + + Fix a few macros for Apple + +M CMakeLists.txt +M cmake/config.h.in + +commit 64a73b1cb87a6661e4c3092b07bfd5032fe9a1fa +Author: Isaac Hier +Date: Wed Nov 8 07:24:08 2017 -0500 + + Work on fixing linking errors in stacktrace + +M CMakeLists.txt +M cmake/config.h.in + +commit b788d51eb4cf80adc7d782fa8df7175ee96d41d9 +Author: Isaac Hier +Date: Tue Nov 7 21:25:34 2017 -0500 + + Fix conditional definitions + +M CMakeLists.txt + +commit 495229b625d65b19f3fc98fed5b626d31a89ee03 +Author: Isaac Hier +Date: Tue Nov 7 13:26:10 2017 -0500 + + Make internal tcmalloc libs + +M CMakeLists.txt + +commit cca7f6f669657218a15ef5a176706660ad2c1d67 +Author: Isaac Hier +Date: Sun Nov 5 16:53:28 2017 -0500 + + More unit tests and libraries + +M CMakeLists.txt + +commit 11dc65c3c40618065ae48ccdb1e1548e339bff32 +Author: Isaac Hier +Date: Sun Nov 5 12:53:07 2017 -0500 + + Fix config headers, add more unit tests + +M CMakeLists.txt +M cmake/config.h.in +M cmake/tcmalloc.h.in + +commit 6078fe40d9a5b829cbbadc6ec824163d6d9eda5b +Author: Isaac Hier +Date: Sun Nov 5 12:23:42 2017 -0500 + + Finish configure.ac conversion to CMake, start on Makefile.am + +M CMakeLists.txt +A cmake/CheckNoFPByDefault.cmake +M cmake/DefineTargetVariables.cmake +A cmake/FindObjcopyWithWeaken.cmake +A cmake/GPerftoolsAddTarget.cmake +M cmake/PCFromUContext.cmake +M cmake/config.h.in + +commit 515fb221966a2413d00184186da97719b90e3915 +Author: Isaac Hier +Date: Fri Nov 3 09:10:27 2017 -0400 + + Generate config header + +M CMakeLists.txt +D cmake/DefineArchVariables.cmake +A cmake/DefineTargetVariables.cmake +M cmake/PCFromUContext.cmake +A cmake/config.h.in +A cmake/tcmalloc.h.in + +commit 4adb5ff74d35900dd8d0ed07959eef68f85c8886 +Author: Isaac Hier +Date: Thu Nov 2 20:07:29 2017 -0400 + + Add architecture checks + +M CMakeLists.txt +A cmake/DefineArchVariables.cmake +M src/tcmalloc.h + +commit fa9bedc82cbbc289875a07b6e431e553b1a15b77 +Author: Isaac Hier +Date: Wed Nov 1 09:52:02 2017 -0400 + + Add most of CMake build + +M CMakeLists.txt +A cmake/PCFromUContext.cmake + +commit 9e4f72fd1faa3f406f468796b4b6908391c8019c +Author: Isaac Hier +Date: Mon Oct 30 22:26:13 2017 -0400 + + Define options, start system checks + +M CMakeLists.txt + +commit a6ce98174b47213f11c84d57cfbc1e3cdd609bfb +Author: Isaac Hier +Date: Mon Oct 30 09:35:34 2017 -0400 + + Add CMakeLists.txt + +A CMakeLists.txt + +commit 313495587598fb1a69b94c44a83735f6056f6049 +Author: Steve Langasek +Date: Thu Oct 8 16:49:21 2020 -0700 + + Additional porting for riscv64. + + Adds handling for the PC register, malloc_hook_mmap, and syscalls. + + Successfully built in Ubuntu with these changes. + +M m4/pc_from_ucontext.m4 +M src/base/linux_syscall_support.h +M src/malloc_hook_mmap_linux.h + +commit f0e289bdbb2fbbb7fa71496d846988c1bac0e310 +Author: Steve Langasek +Date: Thu Oct 8 07:54:03 2020 -0700 + + Enable build on riscv64. + + Cacheline length may be implementation-specific, but this is known + to be + correct on the U54. + +M src/base/basictypes.h + +commit 6c715b4fa183e221a29c5d7a4ea87aeba4ee02cf +Author: Tim Gates +Date: Sat Oct 10 17:26:00 2020 +1100 + + docs: fix simple typo, defininitions -> definitions + + There is a small typo in src/base/linux_syscall_support.h. + + Should read `definitions` rather than `defininitions`. + +M src/base/linux_syscall_support.h + +commit 02d5264018cc76a36713f97329870dbf85969519 +Author: Aliaksey Kandratsenka +Date: Sat Dec 19 17:15:31 2020 -0800 + + Revert "drop page heap lock when returning memory back to kernel" + + This reverts commit be3da70298bf3d25c7d64655922ab82dd819ec98. + + There are reports of crashes and false-positive OOMs from this + patch. Crashes under aggressive decommit mode are understood, but I + have yet to get confirmations whether false-positive OOMs were seen + under aggressive decommit or not. Thus lets revert for now. + + Updates issue #1227 and issue #1204. + +M src/page_heap.cc +M src/page_heap.h +M src/tests/page_heap_test.cc + +commit 151cbf5146cd5b359a4470860d1f7d8f6a843d62 +Author: Grant Henke +Date: Thu Nov 26 20:56:46 2020 -0600 + + Add OS X arm64 program counter + + [alkondratenko@gmail.com: updated comment that it is tested] + + Signed-off-by: Aliaksey Kandratsenka + +M m4/pc_from_ucontext.m4 + +commit 140e3481d0541044cdc27f45129b47f92d5940b7 +Merge: bda3c82 0fc5cab +Author: Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) + +Date: Tue Nov 17 14:30:59 2020 -0800 + + Merge pull request #1231 from PatriosTheGreat/master + + Fix implicit-int-float-conversion warning. + +commit 0fc5cabdfc966affb6f336848d9587ec5d904d0c +Author: Levon Ter-Grigoryan +Date: Tue Nov 17 12:29:22 2020 +0100 + + Fix implicit-int-float-conversion warning. + +M src/sampler.cc + +commit bda3c82e11615ca9e7751d1f3cfb161026ee742a +Author: Kerrick Staley +Date: Wed Jul 8 16:42:12 2020 -0700 + + Increase kMaxStackDepth to 254 + + [alkondratenko@gmail.com: reduced value from 256 to 254] + +M src/profiledata.h + +commit 1d9b8bb59d5610f2c3e9faad6bbd91ceca17fb93 +Author: Aliaksey Kandratsenka +Date: Sat Jul 11 20:33:40 2020 -0700 + + don't test sbrk hook if we're on linux and don't have __sbrk + + "mmap" hooks code for linux only hooks sbrk when __sbrk is + defined. But musl doesn't offer this function (reasonably so), so + sbrk hooking doesn't work there. Not big loss, but lets make sure + tests don't fail. + + Lets reference this to issue #1198 + +M src/tests/tcmalloc_unittest.cc + +commit 180bfa10d7cb38e8b3784d60943d50e8fcef0dcb +Author: Aliaksey Kandratsenka +Date: Mon Jul 6 02:51:43 2020 -0700 + + bumped version to 2.8 + +M Makefile.am +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit c1bcc412ba4a94deaf8c3230519ecb4dda60557d +Author: Ryan Macnak +Date: Fri May 1 11:50:16 2020 -0700 + + Don't try to mark esp as clobbered in linux syscall support. + + Compare 9e5b1628737c67b4587f937164572774592978c4, issue #1076 + +M src/base/linux_syscall_support.h + +commit 50f89afaed3d07d384fa8d86c98460ccff1e870e +Author: Aliaksey Kandratsenka +Date: Sun Apr 19 22:21:07 2020 -0700 + + liberate gperftools tests from relying on -fno-builtin-XXX flags + + Clang mostly ignores those anyways, so our tests needed better way to + disable optimizations (clang is quite aggressive replacing new/delete + pair with stack allocation). + +M Makefile.am +M README +M src/tests/debugallocation_test.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_large_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.h + +commit 98ccd0f1029c11a3df0a51e4a14b543e430a96f8 +Author: Aliaksey Kandratsenka +Date: Sun Apr 19 22:50:16 2020 -0700 + + prevent inlining in heap-checker unittest + + The test relies on stuff "mmaper" function not being inlined, but + compilers are getting smarter and latest clang actually does inline it + now. Adding volatile to pointer declaration fixes it. + +M src/tests/heap-checker_unittest.cc + +commit e521472f1ac1ecf028e8c922ca4f8741473afd66 +Author: Aliaksey Kandratsenka +Date: Sun Jul 5 22:49:41 2020 -0700 + + fix linking of page_heap_test on windows + + After change to release page heap lock around returning memory back to + kernel, page heap test got dependency on page heap lock. Which was not + available on windows since relevant symbols are not exported. + + Proposed fix is to simply duplicate all needed .cc files in + page_heap_test project instead of linking to dll. This is not perfect + but gets job done, until we figure out better solution (GNU/Linux will + eventually get hidden visibility and will need it). + + This fixes github issue 1189. + +M vsprojects/page_heap_test/page_heap_test.vcxproj +M vsprojects/page_heap_test/page_heap_test.vcxproj.filters + +commit e5f77d6485bd2f6ce43862e3e57118b1bb97d30a +Author: Aliaksey Kandratsenka +Date: Mon Mar 23 01:21:27 2020 -0700 + + chmod -x Makefile.am gperftools.sln + +M Makefile.am +M gperftools.sln + +commit 6b92e00cecb82e7fae6e019583865faced29c6f7 +Author: Aliaksey Kandratsenka +Date: Mon Mar 23 01:15:40 2020 -0700 + + don't assume HAVE_MMAP on mingw builds + + Fixes github issue #1108. + +M configure.ac + +commit 4cddede3990a96969aac9ff13ce3c8195ec91ce7 +Author: Kirill Müller +Date: Tue Feb 25 09:09:22 2020 +0100 + + New ProfilerGetStackTrace() + +M Makefile.am +M src/gperftools/profiler.h +M src/profiler.cc + +commit db7aa547abb5abdd558587a15502584cbc825438 +Author: Aliaksey Kandratsenka +Date: Sun Mar 8 20:57:01 2020 -0700 + + bumped version to 2.8rc + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit be3da70298bf3d25c7d64655922ab82dd819ec98 +Author: Aliaksey Kandratsenka +Date: Sun Mar 8 19:32:02 2020 -0700 + + drop page heap lock when returning memory back to kernel + + Fixes issue #754. + +M src/page_heap.cc +M src/page_heap.h +M src/tests/page_heap_test.cc + +commit 87acc2782fe49a8b57d19783f61ff8bc667db68d +Author: Aliaksey Kandratsenka +Date: Sun Mar 8 18:22:17 2020 -0700 + + amputate span events history + + Nobody used it in years. Abseil tcmalloc had it amputated years ago. + +M src/central_freelist.cc +M src/page_heap.cc +M src/span.cc +M src/span.h + +commit e40c7f231ad89e1ee8bf37a1d6680880c519c901 +Author: Ilya Leoshkevich +Date: Thu Feb 27 13:10:29 2020 +0100 + + Fix mmap syscall on s390 + + mmap arguments must be passed in an array on s390. + + Signed-off-by: Ilya Leoshkevich + +M src/malloc_hook_mmap_linux.h + +commit b7607ee7d4ab35504a54588e5912a8e850686db2 +Author: Jon Kohler +Date: Sun Jan 19 22:09:08 2020 -0500 + + tcmalloc: ability to disable fallback allocator in memfs + + Whenever tcmalloc memfs allocator runs out of huge memory, it falls + back to the + default system allocator, which will start allocating from normal + anonymous + memory pool (small pages). For use cases that exclusively want + hugepage backed + memory, such as using tcmalloc in combination with Intel SPDK, this is + problematic. + + This change adds an environment variable + "TCMALLOC_MEMFS_DISABLE_FALLBACK" + which when set to true will ensure that tcmalloc doesn't fallback + to using the + system allocator when the system runs out of hugepages. This is + false by + default, such that all other tcmalloc consumers will not see any + changes. + + For those curious, you can see part of our upstream SPDK work here: + https://review.gerrithub.io/c/spdk/spdk/+/475943 + +M src/memfs_malloc.cc + +commit 1bfcb5bc3a779b6c0c63125737f035c2afcc9e95 +Author: Jon Kohler +Date: Tue Feb 18 11:14:49 2020 -0500 + + tcmalloc: fragmentation overhead instrumentation + + This patch adds visibility into the overhead due to fragmentation + for each size + class in the tcmalloc central free list, which is helpful when + debugging + fragmentation issues. + +M src/tcmalloc.cc + +commit 36bf1309de52433f0088274b347b4fc385ea056f +Author: Todd Lipcon +Date: Mon Jun 3 10:29:06 2019 -0700 + + Fix a clang-tidy readability warning for static member access + + This fixes the following warning: + + src/thread_cache.cc:281:10: warning: static member accessed through + instance [readability-static-accessed-through-instance] + return sampler_.GetSamplePeriod(); + ^~~~~~~~~~~~~~~~~~~~~~~~ + tcmalloc::Sampler:: + +M src/thread_cache.cc + +commit 2b2a962c2bdc3ecbdbd45873a07989c7ccb56560 +Author: prehistoricpenguin +Date: Fri Jul 12 16:25:55 2019 +0800 + + Remove executable flag for c++ files + +M src/heap-checker.cc +M src/heap-profiler.cc +M src/stacktrace_instrument-inl.h +M src/symbolize.cc +M src/system-alloc.cc +M src/tests/sampler_test.cc + +commit 8f308afbfedeca0991ef431e3b8e0b01bd5b8a8f +Author: Henrik Edin +Date: Tue Apr 9 15:16:55 2019 -0400 + + Increase kClassSizesMax to 128 to allow for page size of 4K + +M src/common.h + +commit d3fefdb69439292ec914cd8c65dd83ed1bcbdc65 +Author: Henrik Edin +Date: Tue Jan 29 13:25:40 2019 -0500 + + Allow configuring page size to 4K, 8K, 16K, 32K, 64K, 128K and 256K + +M INSTALL +M configure.ac +M src/common.h +M src/windows/config.h + +commit cf2df3b000c58155d3c83bd01b603894b4559c0b +Author: Laurent Stacul +Date: Fri Feb 7 09:37:34 2020 +0000 + + Fix the removed std::allocator::pointer member type removed in C++20 + +M src/tests/heap-checker_unittest.cc + +commit 31024506c543132adb315b8de89d5faa85e0ff0e +Author: shipujin +Date: Tue Aug 20 13:24:57 2019 +0800 + + Add mips64* support + +M src/base/linux_syscall_support.h + +commit fe62a0baab87ba3abca12f4a621532bf67c9a7d2 +Author: Holy Wu +Date: Tue Apr 9 18:33:26 2019 +0800 + + Update config.h in Windows + +M src/windows/config.h + +commit 8272631b5a9f9e840eb1b014f43b3ddea16ff67d +Author: 风 +Date: Wed Apr 17 10:55:06 2019 +0800 + + Fix a long time typo + + Thought this fix may not effect the behavior or performance, but it + seems indeed a bug. + +M src/pprof + +commit c1d546d7b22cc503f37e9a6efa1d249be60243a3 +Author: Aliaksey Kandratsenka +Date: Sun Apr 7 15:27:17 2019 -0700 + + never test and always default HAVE_MMAP to on + + This should alleviate vboxfs problems from issue #1008. + +M configure.ac + +commit fba6ce0e7aaa094fec09ef8763e86b19dc815624 +Author: pkubaj +Date: Mon Feb 4 16:10:06 2019 +0000 + + Fix build on FreeBSD + + On FreeBSD the following syntax is used: + mr REGA,REGB + +M src/stacktrace_powerpc-darwin-inl.h + +commit 98ac4ee9bc6ab285429fc5d97335b4c94fc0b919 +Author: Jakub Wilk +Date: Wed Apr 3 09:50:40 2019 +0200 + + Fix typos + +M README + +commit 9e5b1628737c67b4587f937164572774592978c4 +Author: Aliaksey Kandratsenka +Date: Sun Feb 10 12:46:18 2019 -0800 + + don't try to mark rsp as clobbered in linux syscall support + + rsp is not actually clobbered by that code and later gccs actually + (correctly) bark + at it. + + Fixed issue #1076. + +M src/base/linux_syscall_support.h + +commit 1e36ed705548ae2a5170bb00dfee0954b8ef76de +Author: Romain Geissler +Date: Tue Jan 29 18:31:19 2019 +0000 + + Use initial exec TLS model for all thread local variables from + thread_cache.cc + + This avoids a deadlock when a library which is being dlopen'ed creates + as part of its static constructors a thread which quickly need to call + malloc. We are still in the dlopen call (so with some internal glibc + mutex taken) when the thread executes code and later needs to call + malloc which in term calls tls_get_addr_tail, which wait for the + dlopen + mutex to be unlocked. If later the dlopen'ing thread also calls malloc + as part of its constructors, we are in a deadlock. + + Fix is similar to + https://github.com/gperftools/gperftools/commit/7852eeb75b9375cf52a7da01be044da6e915dd08 + + Stack of the dlopening thread: + #0 0x00007fd5406ca93c in __lll_lock_wait () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #1 0x00007fd5406c45a5 in pthread_mutex_lock () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + ... proprietary code in the stack + #9 0x00007fd5074f0367 in + __static_initialization_and_destruction_0 (__initialize_p=1, + __priority=65535) at src/ClientImpl.cpp:15 + #10 0x00007fd5074f06d7 in _GLOBAL__sub_I_ClientImpl.cpp(void) + () at src/ClientImpl.cpp:85 + #11 0x00007fd50757aa46 in __do_global_ctors_aux () + #12 0x00007fd5073e985f in _init () from ... + #13 0x00007fd53bf9dec8 in ?? () from ... + #14 0x00007fd54d637a5d in call_init.part () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #15 0x00007fd54d637bab in _dl_init () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #16 0x00007fd54d63c160 in dl_open_worker () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #17 0x00007fd54d637944 in _dl_catch_error () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #18 0x00007fd54d63b7d9 in _dl_open () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #19 0x00007fd54d61f2b9 in dlopen_doit () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + #20 0x00007fd54d637944 in _dl_catch_error () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #21 0x00007fd54d61f889 in _dlerror_run () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + #22 0x00007fd54d61f351 in dlopen@@GLIBC_2.2.5 () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libdl.so.2 + + Stack of the newly created thread calling tls_get_addr_tail: + #0 0x00007fd5406ca93c in __lll_lock_wait () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #1 0x00007fd5406c4622 in pthread_mutex_lock () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #2 0x00007fd54d63a2ed in tls_get_addr_tail () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/ld-linux-x86-64.so.2 + #3 0x00007fd53fee877d in + tcmalloc::ThreadCache::CreateCacheIfNecessary () at + src/thread_cache.cc:344 + #4 0x00007fd53fecb4ab in tcmalloc::ThreadCache::GetCache () + at src/thread_cache.h:437 + #5 0x00007fd53fefeccb in (anonymous namespace)::do_malloc + (size=56) at src/tcmalloc.cc:1354 + #6 tcmalloc::do_allocate_full (size=56) + at src/tcmalloc.cc:1762 + #7 tcmalloc::allocate_full_cpp_throw_oom (size=56) at + src/tcmalloc.cc:1776 + #8 0x00007fd53ff01b80 in + tcmalloc::dispatch_allocate_full + (size=56) at src/tcmalloc.cc:1785 + #9 malloc_fast_path (size=56) at + src/tcmalloc.cc:1845 + #10 tc_new (size=56) at src/tcmalloc.cc:1980 + ... proprietary code in the stack + #26 0x00007fd5406c1ef4 in start_thread () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libpthread.so.0 + #27 0x00007fd5403ba01d in clone () from + /data3/mwrep/rgeissler/core.tls/opt/1A/toolchain/x86_64-2.6.32-v2/lib64/libc.so.6 + +M src/thread_cache.cc + +commit 8f9a873fce14337e113a3837603a11ade06da533 +Author: pkubaj +Date: Mon Feb 4 16:06:32 2019 +0000 + + Fix accessing PC on FreeBSD/powerpc and powerpc64 + +M m4/pc_from_ucontext.m4 + +commit fc00474ddc21fff618fc3f009b46590e241e425e +Author: Tulio Magno Quites Machado Filho +Date: Fri Feb 8 10:33:09 2019 -0200 + + Include asm/ptrace.h when accessing ucontext_t + + In some architectures (e.g. powerpc, powerpc64 and powerpc64le), the + macro that specifies the position of the program counter is defined in + header asm/ptrace.h. + + When glibc bug 21457 got fixed in version 2.27, header sys/ucontext.h + stopped including signal.h, which indirectly removed asm/ptrace.h too. + + Signed-off-by: Tulio Magno Quites Machado Filho + +M m4/pc_from_ucontext.m4 +M src/getpc.h + +commit 5574c87e39ee592c909cb48245c1d91e90ddaf4d +Author: Laurent Stacul +Date: Mon Oct 15 16:56:18 2018 +0200 + + Compile time aggressive decommit option + + [alkondratenko@gmail.com: performed s/agressive/aggressive/g] + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac +M src/static_vars.cc + +commit e9ab4c53041ac62feefbbb076d326e9a77dd1567 +Author: Fabrice Fontaine +Date: Sun Oct 7 18:12:03 2018 +0200 + + undef mmap64 function + + mmap64 can already been defined and as a result the following error is + raised: + + In file included from src/malloc_hook.cc:686:0: + src/malloc_hook_mmap_linux.h: In function ‘void* mmap(void*, + size_t, int, int, int, off_t)’: + src/malloc_hook_mmap_linux.h:173:18: error: redefinition of ‘void* + mmap(void*, size_t, int, int, int, off_t)’ + extern "C" void* mmap(void *start, size_t length, int prot, + int flags, + ^~~~ + In file included from src/malloc_hook.cc:41:0: + src/malloc_hook_mmap_linux.h:159:18: note: ‘void* mmap(void*, + size_t, int, int, int, off_t)’ previously defined here + extern "C" void* mmap64(void *start, size_t length, int prot, + int flags, + ^ + Makefile:4874: recipe for target + 'src/libtcmalloc_minimal_internal_la-malloc_hook.lo' failed + + Signed-off-by: Fabrice Fontaine + +M src/malloc_hook_mmap_linux.h + +commit 5eec9d0ae396aa90ebcb5756dfd0f3d101667490 +Author: Aliaksey Kandratsenka +Date: Sun Oct 7 08:17:04 2018 -0700 + + Drop not very portable and not very useful unwind benchmark. + +M .gitignore +M Makefile.am +D benchmark/getcontext_light.cc +D benchmark/unwind_bench.cc + +commit 1561f0946fcc96d1384dae2a81f3ed111338a341 +Author: Fabrice Fontaine +Date: Sat Oct 6 20:43:19 2018 +0200 + + check for __sbrk + + __sbrk is not defined in musl so add a check for it in configure.ac + and + replace the check on ifndef __UCLIBC__ by a check on ifdef HAVE__SBRK + in src/malloc_hook_mmap_linux.h + + Signed-off-by: Fabrice Fontaine + +M configure.ac +M src/malloc_hook_mmap_linux.h + +commit 1de76671d478e848f0dd210e00df43bfa463ca9f +Author: Gabriel Marin +Date: Thu Oct 4 22:52:35 2018 +0000 + + Fix mmap region iteration while no regions are recorded. + + If no mmap regions are recorded, iteration failed since the RegionSet + (std::set) object is not initialized. + + Original CL https://codereview.chromium.org/14769008 + + Reviewed-on: https://chromium-review.googlesource.com/c/1130807 + +M src/memory_region_map.cc +M src/memory_region_map.h + +commit acdcacc28f17d2e8db1d1bb634025f820f912d93 +Author: Fabrice Fontaine +Date: Sun Apr 29 23:48:41 2018 +0200 + + Use off64_t instead of __off64_t + + __off64_t is a kernel internal symbol, which happens to be + user-visible + with glibc, but not necessarily with other C libraries such as musl. + + Switching from __off64_t to off64_t allows the code to build properly + with musl. + + Signed-off-by: Fabrice Fontaine + +M src/malloc_hook_mmap_linux.h + +commit 0177a2420aa68229f55bec970c59136813a50613 +Author: Gabriel Marin +Date: Fri Oct 5 21:49:50 2018 +0000 + + Return early in WriteProfile to reduce indentation + + Small code refactoring to reduce indentation. This change was + originally + part of https://codereview.chromium.org/9963095. + + Reviewed-on: https://chromium-review.googlesource.com/c/1130804 + +M src/heap-profile-table.cc + +commit b85652bf268d061a0ad0aec90f0d3c29aa80a6b5 +Author: Gabriel Marin +Date: Wed Oct 3 18:15:16 2018 +0000 + + Add generic.total_physical_bytes property to MallocExtension + + Original CL: + + - https://codereview.chromium.org/1410353005 + + Add generic.total_physical_bytes property to MallocExtension + + The actual physical memory usage of tcmalloc cannot be obtained by + GetNumericProperty. This accounts for the current_allocated_bytes, + fragmentation and malloc metadata, and excludes the unmapped memory + regions. This helps the user to understand how much memory is + actually + being used for the allocations that were made. + + Reviewed-on: https://chromium-review.googlesource.com/1130803 + +M src/gperftools/malloc_extension.h +M src/tcmalloc.cc + +commit 90df23c81fe6baf7799b5d3df37d2846ab88fc60 +Author: Gabriel Marin +Date: Fri Oct 5 22:00:33 2018 +0000 + + Make some tcmalloc constants truly const + + Reviewed-on: https://chromium-review.googlesource.com/c/1130809 + +M src/tcmalloc.cc + +commit 49dbe4362b431629111b85929d91fe9a46c42295 +Author: Aliaksey Kandratsenka +Date: Mon Sep 3 16:44:52 2018 -0700 + + Add comment about gperftools 2.8 not deduplicating heapz samples. + +M src/gperftools/malloc_extension.h + +commit 63a12a5ed3c4aca61cc46078b6cdf1d161425a69 +Author: Aliaksey Kandratsenka +Date: Mon Aug 27 20:10:09 2018 -0700 + + Drop de-duplication of heap sample (aka heapz) entries. + + pprof can aggregate them, and it can do it way better than we + can. With + proper unsampling etc. + +M src/stack_trace_table.cc +M src/stack_trace_table.h +M src/static_vars.cc +M src/static_vars.h +M src/tests/stack_trace_table_test.cc + +commit 954f9dc0e37ff46cb0cb24edfb39dc77fd2e7d0b +Author: Aliaksey Kandratsenka +Date: Sun Aug 26 11:37:59 2018 -0700 + + Add flag to disable installing unmaintained & deprecated pprof. + + Everyone should be using golang pprof from github.com/google/pprof, + but + distros still ship our perl version and not everyone is aware of + better pprof yet. + + This is another step in completely dropping perl pprof. We still + default to installing it, but hopefully we'll be able to convince + distros to disable this soon. + + We still install pprof under pprof-symbolize name because + stack traces symbolization depends on it, and because golang pprof + won't support this feature. + + This is related to issue #1038. + +M .gitignore +M Makefile.am +M configure.ac +M src/symbolize.cc + +commit 893bff51bcf220b724a812d340d878b5fb8ce911 +Author: Aliaksey Kandratsenka +Date: Sun Aug 26 11:35:44 2018 -0700 + + Avoid static initialization of pprof path for symbolization. + + This is one of the things that chrome's fork fixes, but with c++11 we + can do it even nicer. Proposed fix is to use c++11 local static + variable to ensure that pprof path is initialized once on as-needed + basis. + +M src/symbolize.cc + +commit 69867c523b334028c90f2acf22b5ae528fdc2356 +Author: Holy Wu +Date: Fri Aug 10 17:19:29 2018 +0800 + + Clean up MSVC projects + + 1.Remove superfluous per file settings for include directory and + runtime library. + 2.Remove unnecessary project tcmalloc_minimal_unittest-static. We + can simply build libtcmalloc_minimal as a static library and then + link against the single .lib file. + 3.Add separate configurations of patching and overriding facility + for release mode. + +M Makefile.am +M gperftools.sln +M vsprojects/addr2line-pdb/addr2line-pdb.vcxproj +M vsprojects/addressmap_unittest/addressmap_unittest.vcxproj +M +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj +M vsprojects/frag_unittest/frag_unittest.vcxproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj.filters +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj +M vsprojects/malloc_extension_test/malloc_extension_test.vcxproj +M vsprojects/malloc_hook_test/malloc_hook_test.vcxproj +M vsprojects/markidle_unittest/markidle_unittest.vcxproj +M vsprojects/nm-pdb/nm-pdb.vcxproj +M vsprojects/packed-cache_test/packed-cache_test.vcxproj +M vsprojects/page_heap_test/page_heap_test.vcxproj +M vsprojects/pagemap_unittest/pagemap_unittest.vcxproj +M vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj +M vsprojects/realloc_unittest/realloc_unittest.vcxproj +M vsprojects/sampler_test/sampler_test.vcxproj +M vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj +M vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj +M +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj +M +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj +M vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj +D vsprojects/tmu-static/tmu-static.vcxproj +D vsprojects/tmu-static/tmu-static.vcxproj.filters + +commit f2bca77aed83107197abadee0652c39e2c4c73d3 +Author: Brian Silverman +Date: Thu Aug 9 16:33:39 2018 -0700 + + Fix page_heap_test flakiness + + After 71fa9f87 (use 2-level page map for 48-bit addresses), there is a + potential for allocs of additional leaves in the middle of the test. + With ASLR enabled on amd64 (without TCMALLOC_SMALL_BUT_SLOW), this + results in the test failing sometimes (< 1% of the time). Instead, + make + sure all those leaves are allocated before deciding on the baseline + heap + usage in the test. + +M src/tests/page_heap_test.cc + +commit c41688bf20186723367b560ceb539b2330951ddb +Author: Aliaksey Kandratsenka +Date: Sun Aug 5 20:39:07 2018 -0700 + + Use standard-conforming alignof in debugallocation.cc + + Clang was giving warning that alignof() is extension. So + we're now doing alignof of decltype. + +M src/debugallocation.cc + +commit 71c8cedacafe700e662c008b65f5064b23426070 +Author: Aliaksey Kandratsenka +Date: Sun Aug 5 18:54:01 2018 -0700 + + Fix incompatible aliasing warnings + + We aliased functions with different signatures and gcc now correctly + gives warning for that. Originally gcc 5 same code merging feature + caused us to alias more than necessary, but I am not able to reproduce + this problem anymore. So we're now aliasing only compatible functions. + +M src/libc_override_gcc_and_weak.h +M src/tcmalloc.cc + +commit 8dd304035848e780372a5a4bb1afac2b2d20bc43 +Author: Aliaksey Kandratsenka +Date: Sun Aug 5 19:52:11 2018 -0700 + + Format and fix out of bound access in CpuProfilerSwitch + + GCC was giving warning on snprintf and it hinted at base_profile_name + and full_profile_name not being long enough. + + Fix is to ensure base_profile_name is long enough for PATH_MAX and + that full_profile_name is enough longer to fit extra chars. + +M src/profiler.cc + +commit 467502e70acb89f36b475bf29fe12333939fe5c7 +Author: Aliaksey Kandratsenka +Date: Sun Aug 5 17:42:04 2018 -0700 + + provide constexpr constructor for Sampler + + Constexpr constructor lets us use Sampler in TLS variable in cleaner + way. + +M src/sampler.h +M src/tests/sampler_test.cc + +commit 1fb543cc708f22017cb39ae874a28c0addcf5a63 +Author: HolyWu +Date: Tue May 1 18:04:57 2018 +0800 + + Patch _free_dbg to make Debug mode in MSVC works + + Like _free_base, _free_dbg is called by CRT internal functions or + operator delete in Debug mode. + + This closes #719 and closes #894. + + [alkondratenko@gmail.com: trivial formatting fixes] + [alkondratenko@gmail.com: build free_dbg even in release builds] + +M src/windows/patch_functions.cc + +commit 267f431d8071799282f9f4af10455b7b6adeee38 +Author: Gabriel Marin +Date: Thu Aug 2 17:16:25 2018 -0700 + + Use indirect system calls in the linux spinlock implementation + +M src/base/spinlock_linux-inl.h + +commit 73ee9b15440d72d5c4f93586ea1179c0a265980c +Author: Gabriel Marin +Date: Mon Jul 2 09:31:10 2018 -0700 + + Use indirect system calls in the mmap malloc hooks. + + sys_{mmap|munmap|mremap}(...) calls are replaced with + syscall(SYS_{mmap|munmap|mremap}, ...). + +M src/malloc_hook_mmap_linux.h + +commit 3af509d4f91aa1fae3f8caeb17b158f20e9b5e59 +Author: Gabriel Marin +Date: Tue Jul 17 18:28:01 2018 -0700 + + benchmark: use angle brackets to include ucontext.h + + Using quotes for a system header file fails a presubmit check in + Chromium. + +M benchmark/unwind_bench.cc + +commit 0cdda6d7cc5e082bb704a9352934148e13dc0a0d +Author: Gabriel Marin +Date: Tue Jul 17 18:36:31 2018 -0700 + + use utf-8 for special symbols + + A few files in the windows port that haven't been touched in a + long time, + use non-utf8 codes for special symbols, breaking a presubmit + checker in + Chromium. + +M src/windows/ia32_modrm_map.cc +M src/windows/ia32_opcode_map.cc +M src/windows/mini_disassembler.h + +commit c7a0cfda880a7310a030c62546f04a2987a11ec2 +Author: etienneb +Date: Thu Apr 20 12:58:02 2017 -0700 + + Fix potential missing nul character on resolved symbol names + + The symbol name returned by SymFromName may not contains a NUL + character + when the symbol name is exactly the size of the buffer. It believe + this + may also happen when the symbol name is too long and truncated. + + The original code is based on: + https://msdn.microsoft.com/en-us/library/windows/desktop/ms680580(v=vs.85).aspx + + A right implementation can be found here: + https://cs.chromium.org/chromium/src/base/debug/stack_trace_win.cc?l=145&rcl=f4ecb9e37e9e2d59e32b8b96f23ac4a1e33b9552 + + As described here: + https://msdn.microsoft.com/en-us/library/windows/desktop/ms680686(v=vs.85).aspx + + NameLen + The length of the name, in characters, not including the + null-terminating character. + MaxNameLen + The size of the Name buffer, in characters. If this member is 0, + the Name member is not used. + + This issue was causing the catapult symbolisation script to encode + incorrect (random) characters into the symbol names. + See the example in the bug. + + Original BUG=713741 + + Review-Url: https://codereview.chromium.org/2832643004 + Cr-Commit-Position: refs/heads/master@{#466098} + + BUG=724399,b:70905156 + + Change-Id: Ia6de4ddbd5c66a966b74ecec3fda5e853f36073b + +M src/windows/addr2line-pdb.c + +commit e42bfc8c06abd1ea1a7e92d1d6d72d1959ec27b6 +Author: Gabriel Marin +Date: Thu Jul 19 11:10:31 2018 -0700 + + tcmalloc: use relative addresses with the windows addr2line wrapper + + Modifies the Windows addr2line wrapper to expect addresses relative to + DllBase to better simulate how addr2line works with modules in Linux. + + Windows DLLs have a concept of "default load address" which hints + to the OS + where to load the binary image after relocation. The dbghelp.dll + symbolization library will load the module at this location in + the virtual + address space meaning the caller of these functions would need to + be aware + of the base address. This makes things unnecessarily complex in the + face of + ASLR and also diverges from the behavior of addr2line when used + with linux- + style DSOs. This CL simply adds the module base address to the + incoming + addresses, thereby making the input relative addresses for the + module which + both is easier to use and lines up better with linux's addr2line + behavior. + + These changes were made originally as part of CL + https://codereview.chromium.org/2730473002. + + BUG=724399,b:70905156 + + Change-Id: I0abe9e0c380e7e60ae29a11021bb805b31718d08 + +M src/windows/addr2line-pdb.c + +commit d8f8d1cced71c37ff86ff577c3afe03b7cd1648f +Author: Gabriel Marin +Date: Wed Jul 18 18:50:30 2018 -0700 + + tcmalloc: add long form flag '--exe' to specify the binary + + This change was originally made as part of CL + https://codereview.chromium.org/2730473002 + + BUG=724399,b:70905156 + + Change-Id: I33ee28eac4dab6077cf162358cf4c10b41c0f6a2 + +M src/windows/addr2line-pdb.c + +commit 25c53aca125b54df1d5c0e64c96f074bdb92ade2 +Author: Gabriel Marin +Date: Wed Jul 18 18:39:15 2018 -0700 + + tcmalloc: fixes for the windows addr2line wrapper + + Fixes a few small format string bugs and makes the windows library + configuration #defines more friendly for chromium builds. + + Based on original CL: https://codereview.chromium.org/2730473002 + + BUG=724399,b:70905156 + + Change-Id: If54c6cfc5c508744d2ee18f251677b2456acda72 + +M src/windows/addr2line-pdb.c + +commit f02e28f3488122f497755de59dc822f08c6449b9 +Author: Gabriel Marin +Date: Tue Jul 31 15:35:53 2018 -0700 + + Replace builtin_expect configure test with a direct GCC compiler check + +M configure.ac +M src/base/basictypes.h + +commit 62c4eca6e7ec9dc78333dc6b499f90eef9849378 +Author: obones +Date: Fri Jul 20 11:07:02 2018 +0200 + + Under x64, the PE loader looks for callbacks in constant sections + + [alkondratenko@gmail.com: deleted some trailing whitespace] + +M src/windows/port.cc + +commit 0b588e7490eac4ef37b59c9265f1f3f05f4bb27c +Author: Brian Silverman +Date: Tue Jul 31 15:53:47 2018 -0700 + + Fix uninitialized memory use in sampler_test + + Sampler's documentation states the following: + C++03 requires that types stored in TLS be POD. As a result, + you must + initialize these members to {0, 0, false} before using this class! + + However, the test code wasn't doing that. MemorySanitizer and + UndefinedBehaviorSanitizer both failed because of it. + +M src/tests/sampler_test.cc + +commit 51a5613f21a34197ed655c363c54c71cf68271ba +Author: Aliaksei Kandratsenka +Date: Sun Aug 5 15:28:27 2018 -0700 + + Upgrade MSVC projects to MSVC2015 + +M Makefile.am +M gperftools.sln +D vsprojects/addr2line-pdb/addr2line-pdb.vcproj +A vsprojects/addr2line-pdb/addr2line-pdb.vcxproj +A vsprojects/addr2line-pdb/addr2line-pdb.vcxproj.filters +D vsprojects/addressmap_unittest/addressmap_unittest.vcproj +A vsprojects/addressmap_unittest/addressmap_unittest.vcxproj +A vsprojects/addressmap_unittest/addressmap_unittest.vcxproj.filters +D +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcproj +A +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj +A +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj.filters +D vsprojects/frag_unittest/frag_unittest.vcproj +A vsprojects/frag_unittest/frag_unittest.vcxproj +A vsprojects/frag_unittest/frag_unittest.vcxproj.filters +D vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +A vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj +A vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj.filters +D +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +A +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj +A +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj.filters +D vsprojects/malloc_extension_test/malloc_extension_test.vcproj +A vsprojects/malloc_extension_test/malloc_extension_test.vcxproj +A +vsprojects/malloc_extension_test/malloc_extension_test.vcxproj.filters +D vsprojects/malloc_hook_test/malloc_hook_test.vcproj +A vsprojects/malloc_hook_test/malloc_hook_test.vcxproj +A vsprojects/malloc_hook_test/malloc_hook_test.vcxproj.filters +D vsprojects/markidle_unittest/markidle_unittest.vcproj +A vsprojects/markidle_unittest/markidle_unittest.vcxproj +A vsprojects/markidle_unittest/markidle_unittest.vcxproj.filters +D vsprojects/nm-pdb/nm-pdb.vcproj +A vsprojects/nm-pdb/nm-pdb.vcxproj +A vsprojects/nm-pdb/nm-pdb.vcxproj.filters +D vsprojects/packed-cache_test/packed-cache_test.vcproj +A vsprojects/packed-cache_test/packed-cache_test.vcxproj +A vsprojects/packed-cache_test/packed-cache_test.vcxproj.filters +D vsprojects/page_heap_test/page_heap_test.vcproj +A vsprojects/page_heap_test/page_heap_test.vcxproj +A vsprojects/page_heap_test/page_heap_test.vcxproj.filters +D vsprojects/pagemap_unittest/pagemap_unittest.vcproj +A vsprojects/pagemap_unittest/pagemap_unittest.vcxproj +A vsprojects/pagemap_unittest/pagemap_unittest.vcxproj.filters +D vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj +A vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj +A +vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj.filters +D vsprojects/realloc_unittest/realloc_unittest.vcproj +A vsprojects/realloc_unittest/realloc_unittest.vcxproj +A vsprojects/realloc_unittest/realloc_unittest.vcxproj.filters +D vsprojects/sampler_test/sampler_test.vcproj +A vsprojects/sampler_test/sampler_test.vcxproj +A vsprojects/sampler_test/sampler_test.vcxproj.filters +D vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj +A vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj +A +vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj.filters +D vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj +A vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj +A +vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj.filters +D +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj +A +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj +A +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj.filters +D +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj +A +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj +A +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj.filters +D vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj +A vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj +A +vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj.filters +D vsprojects/tmu-static/tmu-static.vcproj +A vsprojects/tmu-static/tmu-static.vcxproj +A vsprojects/tmu-static/tmu-static.vcxproj.filters + +commit 44da4ce5397344342e71ea3cc2c246c2ca4aedb6 +Author: Aliaksey Kandratsenka +Date: Sun Aug 5 15:09:20 2018 -0700 + + build with c++11 or later + +M configure.ac +A m4/ax_cxx_compile_stdcxx.m4 + +commit f47a52ce85c3d8d559aaae7b7a426c359fbca225 +Author: HolyWu +Date: Mon Apr 30 15:41:50 2018 +0800 + + Make _recalloc adhere to MS's definition + +M src/tcmalloc.cc +M src/windows/override_functions.cc + +commit fe87ffb7ea5a7c6ce4dea45222331716907ddbf4 +Author: Junhao Li +Date: Sun May 20 13:45:32 2018 -0400 + + Disable large allocation report by default + + Fixes issue #360. + + [alkondratenko@gmail.com: adjusted commit message a bit] + [alkondratenko@gmail.com: adjusted configure help message] + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac +M src/tcmalloc.cc + +commit 9608fa3bcf8020d35f59fbf70cd3cbe4b015b972 +Author: Aliaksey Kandratsenka +Date: Sun Apr 29 16:55:59 2018 -0700 + + bumped version to 2.7 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit db890ccfade3cf054ec330dfb4a9ddfab971367e +Author: HolyWu +Date: Mon Apr 30 12:08:51 2018 +0800 + + Clean up src/windows/config.h + +M src/windows/config.h + +commit 497ea331654f7ea9e4e6405f5beaea8ebcc9d10b +Author: HolyWu +Date: Sun Apr 15 22:47:17 2018 +0800 + + Fix WIN32_OVERRIDE_ALLOCATORS for VS2017 + + At first I try to add some functions as what Chrome does at their + https://chromium.googlesource.com/chromium/src/+/master/base/allocator/allocator_shim_override_ucrt_symbols_win.h, + but it still fails. So I decide to remove all heap-related objects + from libucrt.lib to see what happens. At the end I find that a lot of + functions in the CRT directly invoke _malloc_base instead of + malloc (and the others alike), hence we need to override them as well. + + This should close issue #716. + + [alkondratenko@gmail.com: added reference to ticket] + Signed-off-by: Aliaksey Kandratsenka + +M src/libc_override.h +M src/tcmalloc.cc +M src/windows/override_functions.cc +M src/windows/port.h + +commit ebc85cca9083241ae360e0c68e2f1d7538001fa3 +Author: HolyWu +Date: Tue Apr 17 11:40:49 2018 +0800 + + Enable aligned new/delete declarations on Windows when applicable + +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit a3badd6d2127c161f6fbad853fccd6e8064fcde7 +Author: Aliaksey Kandratsenka +Date: Sun Apr 29 16:34:54 2018 -0700 + + Really fix CheckAddressBits compilation warning + + It looks like previous fix introduced another warning on gcc for + i386. Somehow it barked on kAddressBits shift even that shift was dead + code. + + Anyways, we now avoid possibility of undefined shift even + stronger. And it actually removes compile warning on all compilers I + tested. + +M src/system-alloc.cc + +commit 7c718fe1768273f94acf2bd43cfa1f44a4b9bdcc +Author: HolyWu +Date: Thu Apr 19 13:49:28 2018 +0800 + + Add tests for sized deallocation + +M src/tests/tcmalloc_unittest.cc + +commit 30e5e614a846d5f046454341f108bc4cb2b70189 +Author: Fabrice Fontaine +Date: Sun Apr 22 19:17:12 2018 +0200 + + Fix build without static libraries + + Only add -static to malloc_bench_LDFLAGS and binary_trees_LDFLAGS if + ENABLE_STATC is set otherwise build with some compilers will fail if + user has decided to build only the shared version of gperftools + libraries + + Signed-off-by: Fabrice Fontaine + +M Makefile.am + +commit 836c4f29a585e4b176738f64cf8d312171be5fe0 +Author: Ben Dang +Date: Fri Apr 13 10:54:05 2018 -0700 + + Update documentation for heap_checker.html + + Make it clear that the static methods used require the "namespace", + `HeapLeakChecker::`. + +M docs/heap_checker.html + +commit e47d0d1c5142a4ad1203e58db31af2f58bafcda9 +Author: Tulio Magno Quites Machado Filho +Date: Tue Apr 10 15:56:52 2018 -0300 + + powerpc: Re-enable VDSO support + + Powerpc requires VDSO support in order to produce a stack trace. + Without this, it isn't possible to complete a build. + Tested on powerpc, powerpc64 and powerpc64le. + +M src/base/vdso_support.h + +commit 0a66dd3a6ac60e57d9c01f17309a40e2ebe06837 +Author: Christoph Müllner +Date: Sat Apr 7 09:00:09 2018 +0200 + + linux: add aarch64_ilp32 support. + + This patch adds aarch64 (arm64) ILP32 support by using + the proper syscalls for sys_fcntl(), sys_fstat(), sys_lseek() + and sys_mmap(). + + Signed-off-by: Christoph Müllner + +M src/base/linux_syscall_support.h + +commit 05dff0966362932631a2120eaeb8eebb50dd9300 +Author: Christoph Müllner +Date: Sat Apr 7 08:30:32 2018 +0200 + + Fix signature of sbrk. + + The manpage of sbrk says that its argument is of type intptr_t. + This patch fixes a compiler warning on gcc 7.3.0. + + Signed-off-by: Christoph Müllner + +M src/malloc_hook_mmap_linux.h + +commit 33ae0ed2ae7ce143276658be029c28ec6f2a73c9 +Author: Aliaksey Kandratsenka +Date: Mon Apr 9 20:57:29 2018 -0700 + + unbreak compilation on GNU/Linux i386 + + Recent commit to fix int overflow for implausibly huge allocation + added call to std::min. Notably, first arg was old size divided by + unsigned long 4. And on GNU/Linux i386 size_t is not long. So such + division was promoting first arg to unsigned long while second arg was + still size_t, so just unsigned. And that caused compilation to fail. + + Fix is droping 'ul'. + +M src/tcmalloc.cc + +commit 977e0d45003514d088e4bb83474c985094acee47 +Author: Christoph Müllner +Date: Sat Apr 7 08:35:42 2018 +0200 + + Remove not needed header in vdso_support.cc. + + Signed-off-by: Christoph Müllner + +M src/base/vdso_support.cc + +commit 36bfa9a4046109efa40ccc0806c72331de9c915b +Author: Mao +Date: Mon Mar 26 17:22:19 2018 +0800 + + Enable tcmalloc VDSO support only on x86 to reduce static initializers + + Background context + ------------------ + crrev.com/1466173002 switched the GN tcmalloc target from source_set + -> static_library. There are good reasons for keeping tcmalloc a + source_set (see "Note on static libraries" in [1]). However, in the + current state source_set was exposing extra static initializers in the + GN build which, are not present in the gyp build due to the linker gc + sections. + + Resolution of this CL + --------------------- + The fact that vdso_support.cc is GC-ed by the linker is the symptom + that such code is unreachable. A search in the codebase shows that the + only client is stacktrace_x86-inl.h, which depends on VDSO only when + defined(__linux__) && defined(__i386__) This CL is therefore matching + this condition in vdso_support.h and conditioning the #define + HAVE_VDSO_SUPPORT with the same conditions. + + [1] + https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/cookbook.md + + References: + https://bugs.chromium.org/p/chromium/issues/detail?id=559766 + https://bugs.chromium.org/p/chromium/issues/detail?id=564618 + +M src/base/vdso_support.h + +commit 1cb5de6db9f30daa56a0b54652a7ff6da288c1bd +Author: Mao +Date: Mon Mar 26 17:28:28 2018 +0800 + + Explicitly prevent int overflow + +M src/tcmalloc.cc + +commit 8f63f2bb983e93b57e24a05964104f1d833c575b +Author: Aliaksey Kandratsenka +Date: Sat Mar 24 21:15:01 2018 -0700 + + Correctly detect presence of various functions in tcmalloc.h + + This fixes test miscompilations on some clang 6.0 + installations. Particularly issue #946. + + Defines tested by tcmalloc.h where totally wrong defines. configure + actually puts defines of HAVE_DECL_FOOBAR kind in config.h. Which is + what we're using now. + +M src/tcmalloc.h + +commit 736648887b0b27ec70a50f0954a614dd65c1eb12 +Author: Aliaksey Kandratsenka +Date: Sat Mar 24 15:54:48 2018 -0700 + + Don't test OOM handling of debugallocator + + This may fix issue #969. + + When testing OOM handling we set up sys allocator that fails memory + allocation. But debugallocator itself allocates some internal metadata + memory via malloc and crashes if those allocations fail. So + occasionally this test failed when debugallocator's internal malloc + ended up causing sys allocator. + + So instead of failing tests from time to time, we drop it for debug + allocator. It's OOM handling is already crashy anyways. + +M src/tests/tcmalloc_unittest.cc + +commit c4a8e00da41c43da7e78858e06f3153f09f6967d +Author: Aliaksey Kandratsenka +Date: Sat Mar 24 19:09:15 2018 -0700 + + Fix warning about one of CheckAddressBits functions unused + +M src/system-alloc.cc + +commit 47c99cf492fa340671fa89afec263b8d6e859755 +Author: Aliaksey Kandratsenka +Date: Sat Mar 24 18:29:06 2018 -0700 + + unbreak printing large span stats + + One of recent commits started passing kMaxPages to printf but not used + it. Thankfully compilers gave us warning. Apparently intention was to + print real value of kMaxPages, so this is what we're doing now. + +M src/tcmalloc.cc + +commit 34f78a2dcd8160b483d86474702785337bbeb7ac +Author: Aliaksey Kandratsenka +Date: Sun Mar 18 16:39:06 2018 -0700 + + bumped version to 2.7rc + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit db98aac55a90d45e9abe188c8a928c3561d3f223 +Author: Todd Lipcon +Date: Sat Mar 17 09:43:34 2018 -0700 + + Add a central free list for kMaxPages-sized spans + + Previously, the central free list with index '0' was always unused, + since freelist index 'i' tracked spans of length 'i' and there are no + spans of length 0. This meant that there was no freelist for spans of + length 'kMaxPages'. In the default configuration, this corresponds to + 1MB, which is a relatively common allocation size in a lot of + applications. + + This changes the free list indexing so that index 'i' tracks spans of + length 'i + 1', meaning that free list index 0 is now used and + freelist[kMaxPages - 1] tracks allocations of kMaxPages size (1MB by + default). + + This also fixes the stats output to indicate '>128' for the large + spans + stats rather than the incorrect '>255' which must have referred to a + historical value of kMaxPages. + + No new tests are added since this code is covered by existing tests. + +M docs/pageheap.dot +M docs/pageheap.gif +M docs/tcmalloc.html +M src/common.h +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc + +commit d7be9385609328a03c5cfe775473a7dc8e014fd3 +Author: Aliaksey Kandratsenka +Date: Sun Mar 4 23:29:46 2018 -0800 + + implement more robust detection of sized delete support + + As reported in issue #954, osx clang compiler is able to optimize our + previous detection away while not really having runtime support for + sized delete. So this time we use AC_LINK_IFELSE and more robust code + to prevent compiler from optimizing away sized delete call. This + should reliably catch "bad" compilers. + + Special thanks to Alexey Serbin for reporting the issue, suggesting a + fix and verifying it. + + Fixes issue #954. + +M configure.ac + +commit f1d3fe4a21e339a3fd6e4592ee7444484a7b92dc +Author: Aliaksey Kandratsenka +Date: Sun Feb 25 13:55:53 2018 -0800 + + refactored handling of reverse span set iterator for correctness + + I.e. no more questionable memcpy and we run iterator's destructor when + we remove span from SpanSet. + +M src/page_heap.cc +M src/span.h + +commit 59c77be0fad2a49e31d51877985e7c48f73afcea +Author: Todd Lipcon +Date: Sun Feb 11 16:21:42 2018 -0800 + + Update docs for central page heap to reflect tree + +M docs/pageheap.dot +M docs/pageheap.gif +M docs/tcmalloc.html + +commit 06c9414ec423ffe442c047b2560555f9d5847b1d +Author: Aliaksey Kandratsenka +Date: Sat Jun 3 15:31:06 2017 -0700 + + Implemented O(log n) searching among large spans + + This is implemented via std::set with custom STL allocator that + delegates to PageHeapAllocator. Free large spans are not linked + together via linked list, but inserted into std::set. Spans also store + iterators to std::set positions pointing to them. So that removing + span from set is fast too. + + Patch implemented by Aliaksey Kandratsenka and Todd Lipcon based on + earlier research and experimentation by James Golick. + + Addresses issue #535 + + [alkondratenko@gmail.com: added Todd's fix for building on OSX] + [alkondratenko@gmail.com: removed unnecessary Span constructor] + [alkondratenko@gmail.com: added const for SpanSet comparator] + [alkondratenko@gmail.com: added operator != for STLPageHeapAllocator] + +M src/page_heap.cc +M src/page_heap.h +M src/page_heap_allocator.h +M src/span.h +M src/tests/tcmalloc_unittest.cc + +commit a42e44738a330783781541411392ba27df88b8b3 +Author: Ishan Arora +Date: Tue Jan 9 01:33:13 2018 +0530 + + typo in docs/tcmalloc.html + +M docs/tcmalloc.html + +commit 71bf09aabe93dbe390ebb54c57d3c5b3d627c142 +Author: Aliaksey Kandratsenka +Date: Sat Dec 9 09:58:31 2017 -0800 + + bumped version to 2.6.3 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 0bccb5e658762f30e6e3abbc40dc244e8f8911c1 +Author: Aliaksey Kandratsenka +Date: Sat Dec 9 08:51:19 2017 -0800 + + fix malloc fast path for patched windows functions + + malloc_fast_path now receives oom function instead of full allocation + function and windows/patch_function.cc wasn't updated until now. It + caused assertion failures as reported in issue #944. + +M src/windows/patch_functions.cc + +commit 8b1d13c631024ce7e80508c284c7bc5b1327e131 +Author: Stephan Zuercher +Date: Tue Dec 5 09:49:36 2017 -0800 + + configure.ac: use link check for std::align_val_t + +M configure.ac + +commit 36ab068baa3b07c083bd79029622aa382aeff84a +Author: Stephan Zuercher +Date: Tue Dec 5 09:31:38 2017 -0800 + + configure.ac: better test for -faligned-new + + XCode 9 provides only partial support for aligned new/delete when + -faligned-new + is specified. Require successful linking to enable aligned new/delete. + +M configure.ac + +commit 6a4b0799975576c2722daa75b35f6f65220d22b6 +Author: Aliaksey Kandratsenka +Date: Thu Nov 30 18:19:17 2017 +0000 + + bumped version to 2.6.2 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 22917145186bc8bbb6d98090d788ed7c87b282b1 +Author: Aliaksey Kandratsenka +Date: Thu Nov 30 16:36:33 2017 +0000 + + implement fast-path for memalign/aligned_alloc/tc_new_aligned + + We're taking advantage of "natural" alignedness of our size classes + and instead of previous loop over size classes looking for suitably + aligned size, we now directly compute right size. See align_size_up + function. And that gives us ability to use our existing malloc + fast-path to make memalign neat and fast in most common + cases. I.e. memalign/aligned_alloc now only tail calls and thus avoids + expensive prologue/epilogue and is almost as fast as regular malloc. + +M src/common.cc +M src/tcmalloc.cc + +commit 8b9728b02325a9bee9afd3957e506c111ed40d40 +Author: Aliaksey Kandratsenka +Date: Thu Nov 30 18:12:32 2017 +0000 + + add memalign benchmark to malloc_bench + +M benchmark/malloc_bench.cc + +commit 79c91a9810c928d7f6d0cb168c10ce470a714aa8 +Author: Aliaksey Kandratsenka +Date: Wed Nov 29 21:15:04 2017 +0000 + + always define empty PERFTOOLS_NOTHROW + + Because somehow clang still builds "this function will not throw" code + even with noexcept. Which breaks performance of + tc_malloc/tc_new_nothrow. The difference with throw() seems to be just + which function is called when unexpected exception happens. + + So we work around this sillyness by simply dropping any exception + specification when compiling tcmalloc. + +M src/tcmalloc.cc + +commit 03da6afff57c12845260997213b6ad89e420bab3 +Author: Aliaksey Kandratsenka +Date: Wed Nov 29 20:19:07 2017 +0000 + + unbreak throw declarations on operators new/delete + + We now clearly separate PERFTOOLS_NOTHROW (used for tc_XXX functions) + and throw()/noexcept (used for operators we define). + + The former is basically "nothrow() for our callers, nothing for + us". It is roughly equivalent of what glibc declares for malloc and + friends. If some exception-full C++ code calls such function it + doesn't have to bother setting up exception handling around such + call. Notably, it is still important for those functions to _not have + throw() declarations when we're building tcmalloc. Because C++ throw() + requires setting up handling of unexpected exceptions thrown from + under such functions which we don't want. + + The later is necessary to have operators new/delete definitions have + "correct" exception specifications to calm down compiler + warnings. Particularly older clang versions warn if new/delete aren't + defined with correct exception specifications. Also this commit fixes + annoying gcc 7+ warning (and gnu++14 mode) that complains about + throw() being deprecated. + +M src/base/basictypes.h +M src/libc_override.h +M src/libc_override_gcc_and_weak.h +M src/libc_override_redefine.h +M src/tests/tcmalloc_unittest.cc +M src/windows/get_mangled_names.cc + +commit 89fe59c8318b2f8cec8ce00182dd24c357252c96 +Author: Aliaksey Kandratsenka +Date: Wed Nov 29 13:37:50 2017 +0000 + + Fix OOM handling in fast-path + + Previous fast-path malloc implementation failed to arrange proper oom + handling for operator new. I.e. operator new is supposed to call new + handler and throw exception, which was not arranged in fast-path case. + + Fixed code now passes pointer for oom function to + ThreadCache::FetchFromCentralCache which will call it in oom + condition. Test is added to verify correct behavior. + + I've also updated some fast-path-related comments for more accuracy. + +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit a29a0cf348e131d5b8ec26c39dabeac89cf13fcd +Author: Aliaksey Kandratsenka +Date: Tue Nov 28 14:43:11 2017 +0000 + + delete-trailing-whitespace on thread_cache.* + +M src/thread_cache.cc +M src/thread_cache.h + +commit e6cd69bdecde074c3c7a52ccb099eafcecf668dc +Author: Aliaksey Kandratsenka +Date: Wed Nov 29 19:49:18 2017 +0000 + + reintroduce aliasing for aligned delete + + Without aliasing performance is likely to be at least partially + affected. There is still concern that aliasing between functions of + different signatures is not 100% safe. We now explicitly list of + architectures where aliasing is known to be safe. + +M src/tcmalloc.cc + +commit fb30c3d435c4712785a50f8a422c76ad490a12b2 +Author: Aliaksey Kandratsenka +Date: Wed Nov 29 19:10:23 2017 +0000 + + fully disable aligned new on windows for now + +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 7efb3ecf37d88edf9cf9a43efb89b425eaf81d5e +Author: Andrey Semashev +Date: Sat Sep 30 17:47:35 2017 +0300 + + Add support for C++17 operator new/delete for overaligned types. + + - Add auto-detection of std::align_val_t presence to configure + scripts. This + indicates that the compiler supports C++17 operator new/delete + overloads + for overaligned types. + + - Add auto-detection of -faligned-new compiler option that appeared + in gcc 7. + The option allows the compiler to generate calls to the new + operators. It is + needed for tests. + + - Added overrides for the new operators. The overrides are enabled + if the + support for std::align_val_t has been detected. The implementation + is mostly + based on the infrastructure used by memalign, which had to be + extended to + support being used by C++ operators in addition to C functions. In + particular, + the debug version of the library has to distinguish memory + allocated by + memalign from that by operator new. The current implementation + of sized + overaligned delete operators do not make use of the supplied + size argument + except for the debug allocator because it is difficult to calculate + the exact + allocation size that was used to allocate memory with + alignment. This can be + done in the future. + + - Removed forward declaration of std::nothrow_t. This was not + portable as + the standard library is not required to provide nothrow_t + directly in + namespace std (it could use e.g. an inline namespace within + std). The + header needs to be included for std::align_val_t anyway. + + - Fixed operator delete[] implementation in libc_override_redefine.h. + + - Moved TC_ALIAS definition to the beginning of the file in + tcmalloc.cc so that + the macro is defined before its first use in nallocx. + + - Added tests to verify the added operators. + + [alkondratenko@gmail.com: fixed couple minor warnings, and some + whitespace change] + [alkondratenko@gmail.com: removed addition of TC_ALIAS in debug + allocator] + Signed-off-by: Aliaksey Kandratsenka + +M Makefile.am +M configure.ac +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/libc_override_gcc_and_weak.h +M src/libc_override_redefine.h +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 7a6e25f3b143c35ed6fff8bb2c0f8de1ab348a39 +Author: Andrew Morrow +Date: Tue Nov 7 15:57:17 2017 -0500 + + Add new statistics for the PageHeap + + [alkondratenko@gmail.com: addressed init order mismatch warning] + Signed-off-by: Aliaksey Kandratsenka + +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc + +commit 6e3a702fb9c86eb450f22b326ecbceef4b0d6604 +Author: Jianbo Yang +Date: Tue Oct 17 01:09:18 2017 +0800 + + Fix data race setting size_left_ in ThreadCache::SetMaxSize + + This commit is to fix the data race in ThreadCache::SetMaxSize. + ThreadCache::size_left_ is removed and ThreadCache::size_ is + added. ThreadCache::size_left_ was introduced for optimization. + It is updated in several functions of ThreadCache, including the + ThreadCache::SetMaxSize. But thread A can update size_left_ of + thread B via SetMaxSize without protection or synchronization. + + There should not be data race around ThreadCache::size_, for it + isn't accessed by multi threads. + + The optimization of tail-call in tc_{malloc, new, free} is kept + and no other logics are affected. + +M src/thread_cache.cc +M src/thread_cache.h + +commit 235471f96564aa95354839bb135661e561966001 +Author: cs-lee +Date: Sun Aug 6 04:57:42 2017 -0700 + + fix memory leak in Symbolize function + + [alkondratenko@gmail.com: reworded commit message] + Signed-off-by: Aliaksey Kandratsenka + +M src/symbolize.cc + +commit 47efdd60f596f7180689337cbba2dab35539ba98 +Author: cs-lee +Date: Sun Aug 6 04:51:52 2017 -0700 + + Added mising va_end() in TracePrintf function + + Normally the va_end function does not do anything, + but it should be called because some platforms need it. + + [alkondratenko@gmail.com: reworded commit message] + Signed-off-by: Aliaksey Kandratsenka + +M src/debugallocation.cc + +commit 497b60ef0fa93ed41ccacf6ffd0d536789401d29 +Author: Vladimir +Date: Fri Jul 14 15:13:32 2017 +0300 + + Implemented GetProgramInvocationName on FreeBSD + + Few lines of code was taken from + /usr/src/contrib/libexecinfo/backtrace.c + + [alkondratenko@gmail.com: updated commit message + Signed-off-by: Aliaksey Kandratsenka + +M src/symbolize.cc + +commit ac072a3fc768b9699b1e809a379f576aa3e48983 +Author: Aliaksey Kandratsenka +Date: Sat Sep 23 14:55:33 2017 -0700 + + Revert "Ignore current_instance heap allocation when leak sanitizer + is enabled" + + This reverts commit 70a35422b5509a456584b132ad8ce4466af323ea. + +M Makefile.am +M src/malloc_extension.cc + +commit fb5987d57913867e3b0f20490461ea55bfabe9ee +Author: Aliaksey Kandratsenka +Date: Sat Sep 23 14:55:20 2017 -0700 + + Revert "Ensure that lsan flags are appended on all necessary targets" + + This reverts commit a3bf61ca81b68e7792739c451aceef00cf7d7d03. + +M Makefile.am + +commit 5815f02105acd5d7fd0e6ec038a9e96ccc36911f +Author: Aliaksey Kandratsenka +Date: Sat Sep 16 21:14:23 2017 -0700 + + Use safe getenv for setting up backtrace capturing method + + This code runs very early, so using special "early" version of getenv + is reasonable. It should fix issue #912. + +M src/stacktrace.cc + +commit aab4277311759b32ae8c442b49edf002230ea165 +Author: Dorin Lazăr +Date: Thu Sep 21 22:11:49 2017 +0300 + + Fixed LTO warning about the mismatch between return values for + ProfilingIsEnabledForAllThreads() + +M src/heap-checker.cc + +commit d406f2285390c402e824dd28e6992f7f890dcdf9 +Author: Aliaksey Kandratsenka +Date: Sat Aug 5 22:05:10 2017 -0700 + + implement support for C11 aligned_alloc + + Just like glibc does, we simply alias it to memalign. + +M Makefile.am +M src/libc_override_gcc_and_weak.h +M src/libc_override_redefine.h + +commit 92a27e41a137704772479277786d035763938921 +Author: Piotr Sikora +Date: Mon Aug 21 15:06:23 2017 -0700 + + Fix build on macOS. + + Fixes #910. + + Signed-off-by: Piotr Sikora + +M Makefile.am + +commit e033431e5a9e02e4d1882bb6fcd212c4fab56173 +Author: Khem Raj +Date: Sun Jul 16 19:28:17 2017 -0700 + + include fcntl.h for loff_t definition + + Fixes + linux_syscall_support.h:2641:26: error: 'loff_t' has not been declared + + Signed-off-by: Khem Raj + +M src/base/linux_syscall_support.h + +commit e41bc414048eb4a37743e294bed3f1c63a1fa559 +Author: Khem Raj +Date: Sat Jul 1 13:21:21 2017 -0700 + + Use ucontext_t instead of struct ucontext + + Newer glibc has dropped the ucontext tag from exposing + + Signed-off-by: Khem Raj + +M src/stacktrace_powerpc-linux-inl.h + +commit bf840dec0495e17f5c8403e68e10b9d6bf05c559 +Author: Aliaksey Kandratsenka +Date: Sun Jul 9 14:55:33 2017 -0700 + + bumped version to 2.6.1 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 2d220c7e26bd279ec87f9d1fc694ca5114b20bee +Author: Romain Geissler +Date: Sun Jun 18 15:21:19 2017 +0200 + + Replace "throw()" by "PERFTOOLS_NOTHROW" + + Automatically done with: + sed -e 's/\ +Date: Sun Jun 18 15:16:16 2017 +0200 + + Add PERFTOOLS_THROW where necessary (as detected by GCC). + +M src/base/basictypes.h +M src/libc_override_gcc_and_weak.h +M src/tests/tcmalloc_unittest.cc + +commit e5fbd0e24e19bf3c9a8777cfc78e6188c5557025 +Author: Romain Geissler +Date: Sun Jun 18 15:05:46 2017 +0200 + + Rename PERFTOOLS_THROW into PERFTOOLS_NOTHROW. + + Automatically done with: + sed -e 's/\/PERFTOOLS_NOTHROW/g' -i $(git grep + -l PERFTOOLS_THROW) + +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/tcmalloc.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit eeb7b84c20146c0e2e039ce72a2ea083a94ba80d +Author: Aliaksey Kandratsenka +Date: Sat Jul 8 15:23:37 2017 -0700 + + Register tcmalloc atfork handler as early as possible + + This is what other mallocs do (glibc malloc and jemalloc). The idea is + malloc is usually initialized very eary. So if we register atfork + handler at that time, we're likely to be first. And that makes our + atfork handler a bit safer, since there is much less chance of some + other library installing their "take all locks" handler first and + having fork take malloc lock before library's lock and deadlocking. + + This should address issue #904. + +M src/static_vars.cc +M src/static_vars.h +M src/thread_cache.cc + +commit 208c26caeff24fd8c1defea80cb723ec1ab4bf06 +Author: Aliaksey Kandratsenka +Date: Tue Jul 4 19:50:04 2017 -0700 + + Add initial syscall support for mips64 32-bit ABI + + This applies patch by Adhemerval Zanella from + https://github.com/gperftools/gperftools/issues/845. + + Only malloc (i.e. tcmalloc_minimal) was tested to work so far. + +M src/base/linux_syscall_support.h +M src/malloc_hook_mmap_linux.h + +commit a3bf61ca81b68e7792739c451aceef00cf7d7d03 +Author: Francis Ricci +Date: Wed Jul 5 12:39:41 2017 -0400 + + Ensure that lsan flags are appended on all necessary targets + +M Makefile.am + +commit 97646a193237af0f941e5bd3078eb72edbc2d548 +Author: Aliaksey Kandratsenka +Date: Tue Jul 4 21:02:34 2017 -0700 + + Add missing NEWS entry for recent 2.6 release + + Somehow I managed to miss this last commit in 2.6 release. So lets add + it now even if it is too late. + +M NEWS + +commit 4be05e43a1adab9ceea9bdaaae546fb938f0a86c +Author: Aliaksey Kandratsenka +Date: Tue Jul 4 20:35:25 2017 -0700 + + bumped version up to 2.6 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 70a35422b5509a456584b132ad8ce4466af323ea +Author: Francis Ricci +Date: Thu Jun 15 11:04:33 2017 -0400 + + Ignore current_instance heap allocation when leak sanitizer is enabled + + Without this patch, any user program that enables LeakSanitizer will + see a leak from tcmalloc. Add a weak hook to __lsan_ignore_object, + so that if LeakSanitizer is enabled, the allocation can be ignored. + +M Makefile.am +M src/malloc_extension.cc + +commit 6eca6c64fabbff55c43a78537e466312524b3acd +Author: Aliaksey Kandratsenka +Date: Sat Jul 1 18:48:58 2017 -0700 + + Revert "issue-654: [pprof] handle split text segments" + + This reverts commit 8c3dc52fcfe02412a529769a22cbc75388a5d368. + + People have reported issues with this so lets stay safe and use older + even if less powerful code. + +M src/pprof + +commit a495969cb6157cc361fc03228ae12ff7c0ecac4b +Author: KernelMaker +Date: Wed May 24 16:46:49 2017 +0800 + + update the prev_class_size in each loop, or the min_object_size of + tcmalloc.thread will always be 1 when calling GetFreeListSizes + +M src/tcmalloc.cc + +commit 163224d8af5abdbbd8208ad6d37f13fb450af46f +Author: Kim Gräsman +Date: Fri May 26 13:09:03 2017 +0200 + + Document HEAPPROFILESIGNAL environment variable + +M docs/heapprofile.html + +commit 5ac82ec5b96d24219efd4c8aec47a45466eabd00 +Author: Aliaksey Kandratsenka +Date: Mon May 29 13:07:39 2017 -0700 + + added stacktrace capturing benchmark + +M .gitignore +M Makefile.am +A benchmark/getcontext_light.cc +A benchmark/unwind_bench.cc + +commit c571ae2fc9433e958f29b3c3525d34c22a9cb884 +Author: Aliaksey Kandratsenka +Date: Mon May 22 19:04:20 2017 -0700 + + 2.6rc4 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit f2bae51e7e609855c26095f14ffbb84082694acb +Author: Aliaksey Kandratsenka +Date: Mon May 22 18:58:15 2017 -0700 + + Revert "Revert "disable dynamic sized delete support by default"" + + This reverts commit b82d89cb7c8781a6028f6f5959cabdc5a273aec3. + + Dynamic sized delete support relies on ifunc handler being able to + look up environment variable. The issue is, when stuff is linked with + -z now linker flags, all relocations are performed early. And sadly + ifunc relocations are not treated specially. So when ifunc handler + runs, it cannot rely on any dynamic relocations at all, otherwise + crash is real possibility. So we cannot afford doing it until (and if) + ifunc is fixed. + + This was brought to my attention by Fedora people at + https://bugzilla.redhat.com/show_bug.cgi?id=1452813 + +M configure.ac + +commit 6426c0cc8049dd50a681dc337ac9962577d5fa14 +Author: Aliaksey Kandratsenka +Date: Sun May 21 22:55:29 2017 -0700 + + 2.6rc3 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 0c0e2fe43b5095d19470abdc3b4d83613fe37c6d +Author: Aliaksey Kandratsenka +Date: Mon May 22 02:39:29 2017 -0700 + + enable 48-bit page map on msvc as well + +M src/common.h + +commit 83d6818295cb337b6201fe307e15755df9dcd47f +Author: Aliaksey Kandratsenka +Date: Mon May 22 02:38:13 2017 -0700 + + speed up 3-level page map access + + There is no need to have pointer indirection for root node. This also + helps the case of early free of garbage pointer because we didn't + check root_ pointer for NULL. + +M src/pagemap.h + +commit f7ff175b92df5577aef9caf3fb02f9ff37b822ca +Author: Aliaksey Kandratsenka +Date: Sun May 21 23:28:48 2017 -0700 + + add configure-time warning on unsupported backtrace capturing + + Both libgcc and libc's backtrace() are not really options for stack + trace capturing from inside profiling signal handler. So lets warn + people. + +M configure.ac + +commit cef582350c952bad761476d01ea64bb4087371ce +Author: Aliaksey Kandratsenka +Date: Sun May 21 23:15:59 2017 -0700 + + align fast-path functions only if compiler supports that + + Apparently gcc only supports __attribute__((aligned(N))) on functions + only since version 4.3. So lets test it in configure script and only + use when possible. We now use CACHELINE_ALIGNED_FN macro for aligning + functions. + +M configure.ac +M src/base/basictypes.h +M src/tcmalloc.cc + +commit bddf862b189c4508d5212f6e0e8ea81c4dd18811 +Author: Aliaksey Kandratsenka +Date: Sun May 21 22:24:19 2017 -0700 + + actually support very early freeing of NULL + + This was caught by unit tests on centos 5. Apparently some early + thingy is trying to do vprintf which calls free(0). Which used to + crash since before size class cache is initialized it'll report + hit (with size class 0) for NULL pointer, so we'd miss the case of + checking NULL pointer free and crash. + + The fix is to check for IsInited in the case when thread cache is + null, and if so then we escalte to free_null_or_invalid. + +M src/tcmalloc.cc +M src/thread_cache.cc + +commit 07a124d8c16bc7d52524ceb9f50d7a65b868e129 +Author: Aliaksey Kandratsenka +Date: Sun May 21 22:22:21 2017 -0700 + + don't use arg-ful constructor attribute for early nallocx test + + 101 is not very early anyways and arg-ful constructor attribute is + only supported since gcc 4.3 (and e.g. rhel 5's compiler fails to + compile it). So there seems to be very little value trying to ask for + priority of 101. + +M src/tests/tcmalloc_unittest.cc + +commit 5346b8a4def33915e6f877e308fb948f570a6120 +Author: Aliaksey Kandratsenka +Date: Sun May 21 22:18:01 2017 -0700 + + don't depend on SIZE_MAX definition in sampler.cc + + It was reported that SIZE_MAX isn't getting defined in C++ mode when + C++ standard is less than c++11. Because we still want to support + non-c++11 systems (for now), lets make it simple and not depend on + SIZE_MAX (original google-internal code used + std::numeric_limits::max, but that failed to compile on + msvc). + + Fixes issue #887 and issue #889. + +M src/sampler.cc + +commit 50125d8f70007fb2aa4d1c87df6a3092a3371edf +Author: Aliaksey Kandratsenka +Date: Mon May 15 00:02:43 2017 -0700 + + 2.6rc2 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit a5e8e42a47fc0175c8044d0d77bf192b03347964 +Author: Aliaksey Kandratsenka +Date: Sun May 14 23:45:08 2017 -0700 + + don't link-in libunwind if libunwind.h is missing + + I got report that some build environments for + https://github.com/lyft/envoy are having link-time issue due to + linking libunwind. It was happening despite libunwind.h being present, + which is clear bug as without header we won't really use libunwind. + +M configure.ac + +commit e92acdf98db229e8dc84993fd8895d55e6c69129 +Author: Rajalakshmi Srinivasaraghavan +Date: Wed Apr 26 06:46:43 2017 -0300 + + Fix compilation error for powerpc32 + + Fix the following compilation error for powerpc32 platform when using + latest glibc. + error: ‘siginfo_t’ was not declared in this scope + +M src/stacktrace_powerpc-linux-inl.h + +commit b48403a4b065830129e238feffe022abd93af807 +Author: Aliaksey Kandratsenka +Date: Sun Apr 16 21:45:51 2017 -0700 + + 2.6rc + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 53f15325d93fbe0ba17bb3fac3da86ffd3f0f1ad +Author: Aliaksey Kandratsenka +Date: Sun May 14 20:24:27 2017 -0700 + + fix compilation of tcmalloc_unittest.cc on older llvm-gcc + +M src/tests/tcmalloc_unittest.cc + +commit b1d88662cb4a38ee47aa48076745898033526f9d +Author: Aliaksey Kandratsenka +Date: Sun Apr 2 19:27:00 2017 -0700 + + change size class to be represented by 32 bit int + + This moves code closer to Google-internal version and provides for + slightly tighter code encoding on amd64. + +M src/common.h +M src/packed-cache-inl.h +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc +M src/tests/packed-cache_test.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit 991f47a159f0e169883f06686f13c31688fa2bf0 +Author: Aliaksey Kandratsenka +Date: Thu Feb 2 15:58:08 2017 -0800 + + change default transfer batch back to 32 + + Some tensorflow benchmarks are seeing large regression with elevated + values. So lets stick to old safe default until we understand how + to make + larger values work for all workloads. + +M src/common.cc + +commit 7bc34ad1f60be2df6ca38f4bffdba4daa9aa9a7d +Author: Aliaksey Kandratsenka +Date: Thu Feb 2 15:38:41 2017 -0800 + + support different number of size classes at runtime + + With TCMALLOC_TRANSFER_NUM_OBJ environment variable we can change + transfer batch size. And with that comes slightly different number of + size classes depending on value of transfer batch size. + + We used to have hardcoded number of size classes, so we couldn't + really support any batch size setting. + + This commit adds support for dynamic number of size classes (runtime + value returned by Static::num_size_classes()). + +M src/central_freelist.cc +M src/common.cc +M src/common.h +M src/page_heap.cc +M src/static_vars.cc +M src/static_vars.h +M src/tcmalloc.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit 4585b78c8dae9183dbf5f124c0343a9f1244ed67 +Author: Aliaksey Kandratsenka +Date: Tue Feb 21 00:27:39 2017 -0800 + + massage allocation and deallocation fast-path for performance + + This is significant speedup of fast-path of malloc. Large part comes + from avoiding expensive function prologue/epilogue. Which is achieved + by making sure that tc_{malloc,new,free} etc are small functions that + do only tail-calls. We keep only critical path in those functions and + tail-call to slower "full" versions when we need to deal with less + common case. This helps compiler generate much tidier code. + + Fast-path readyness check is now different too. We used to have "min + size for slow path" variable, which was set to non-zero value when we + know that thread cache is present and ready. We now have use + thread-cache pointer not equal to NULL as readyness check. + + There is special ThreadCache::threadlocal_data_.fast_path_heap copy of + that pointer that can be temporarily nulled to disable malloc fast + path. This is used to enable emergency malloc. + + There is also slight change to tracking thread cache size. Instead of + tracking total size of free list, it now tracks size headroom. This + allows for slightly faster deallocation fast-path check where we're + checking headroom to stay above zero. This check is a bit faster than + comparing with max_size_. + +M src/linked_list.h +M src/tcmalloc.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/patch_functions.cc + +commit 5964a1d9c98ea3c178435ff01f9b06e03eeda58d +Author: Aliaksey Kandratsenka +Date: Tue Feb 21 00:42:29 2017 -0800 + + always inline a number of hot functions + +M src/page_heap.h +M src/pagemap.h +M src/tcmalloc.cc +M src/thread_cache.h + +commit e419b7b9a66c39b44115b01520fb25a5100cec83 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 21:11:14 2017 -0800 + + introduce ATTRIBUTE_ALWAYS_INLINE + +M src/base/basictypes.h +M src/tcmalloc.cc + +commit 7d588da7ec4f315ea2d02824d7e8813b0f95171d +Author: Aliaksey Kandratsenka +Date: Sun Dec 18 18:36:57 2016 -0800 + + synchronized Sampler implementation with Google-internal version + + This is mostly dropping FastLog2 which was never necessary for + performance, and making sampler to be called always, even if sampling + is disabled (this benefits more for always-sampling case of Google + fork). + + We're also getting TryRecordAllocationFast which is not used yet, but + will be as part of subsequent fast-path speedup commit. + +M src/sampler.cc +M src/sampler.h +M src/static_vars.cc +M src/tests/sampler_test.cc +M src/thread_cache.h + +commit 27da4ade70d45312bfdf334aa8cf0d63bf78df14 +Author: Aliaksey Kandratsenka +Date: Tue Feb 21 00:41:43 2017 -0800 + + reduce size of class_to_size_ array + + Since 32-bit int is enough and accessing smaller array will use a bit + less of cache. + +M src/common.h +M src/tcmalloc.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit 335f09d4e43a8413642e17e5ac374f925906c4e3 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 23:49:15 2017 -0800 + + use static location for pageheap + + Makes it a bit faster to access, since we're dropping pointer + indirection. + +M src/static_vars.cc +M src/static_vars.h + +commit 6ff332fb517734cf01e86272fe37521b7155c995 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 23:37:33 2017 -0800 + + move size classes map earlier in SizeMap + + Since we access them more often, having at least one of them at offset + 0 makes pi{c,e} code a bit smaller. + +M src/common.h + +commit 121b1cb32e7416ecb7b0c739588f1bd916c4913a +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 22:57:43 2017 -0800 + + slightly faster size class cache + + Lower bits of page index are still used as index into hash + table. Those lower bits are zeroed, or-ed with size class and + placed into hash table. So checking is just loading value from hash + table, xoring with higher bits of address and checking if resultant + value is lower than 128. Notably, size class 0 is not considered + "invalid" anymore. + +M src/central_freelist.cc +M src/packed-cache-inl.h +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc +M src/tests/packed-cache_test.cc + +commit b57c0bad41700238f524b28483a1c6c18c0a621f +Author: Aliaksey Kandratsenka +Date: Sun Apr 16 23:15:16 2017 -0700 + + init tcmalloc prior to replacing system alloc + + Currently on windows, we're depending on uninitialized tcmalloc + variables to detect freeing foreign malloc's chunks. This works + somewhat by chance due to 0-initialized size classes cache working as + cache with no values. But this is about to change, so lets do explicit + initialization. + +M src/tcmalloc.cc + +commit 71fa9f873065e3d7c1f4ce0581d26b6498712f00 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 21:17:48 2017 -0800 + + use 2-level page map for 48-bit addresses + + 48 bits is size of x86-64 and arm64 address spaces. So using 2 levels + map for them is slightly faster. We keep 3 levels for small-but-slow + configuration, since 2 levels consume a bit more memory. + + This is partial port of Google-internal commit by Sanjay + Ghemawat (same idea, different implementation). + +M src/page_heap.h +M src/pagemap.h + +commit bad70249dd5c829b4981aecdc25953800d6745c3 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 21:12:58 2017 -0800 + + use 48-bit addresses on 64-bit arms too + +M src/common.h + +commit 5f12147c6dbfe2cfbdc7553521fe0110073135f0 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 21:03:58 2017 -0800 + + use hidden visibility for some key global variables + + So that our -fPIC code is faster + +M src/base/basictypes.h +M src/static_vars.h + +commit dfd53da578137d5962fe8d588980870bb0ab8aa9 +Author: Aliaksey Kandratsenka +Date: Sun Jan 22 21:08:51 2017 -0800 + + set ENOMEM in handle_oom + +M src/tcmalloc.cc + +commit 14fd551072426cef317f43d587f91004d4fdae75 +Author: Aliaksey Kandratsenka +Date: Sun Jan 8 06:02:04 2017 +0300 + + avoid O(N²) in thread cache creation code + +M src/thread_cache.cc + +commit 507a105e849422d5ceff4348d38aaf72371a6161 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 14:25:10 2016 -0800 + + pass original size to DoSampledAllocation + + It makes heap profiles more accurate. Google's internal malloc + is doing + it as well. + +M src/tcmalloc.cc + +commit bb77979dea796ab743e1308af25e9259ec97f2b1 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 18:10:19 2016 -0800 + + don't declare throw() on malloc funtions since it is faster + + Apparently throw() on functions actually asks compiler to generate + code + to detect unexpected exceptions. Which prevents tail calls + optimization. + + So in order to re-enable this optimization, we simply don't tell + compiler about throw() at all. C++11 noexcept would be even better, + but + it is not universally available yet. + + So we change to no exception specifications. Which at least for gcc & + clang on Linux (and likely for all ELF platforms, if not just all) + really eliminates all overhead of exceptions. + +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/tcmalloc.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 89c74cb79ca41cd75a1f9131af4ea2ab362593ae +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 20:26:40 2016 -0800 + + handle duplicate google_malloc frames in malloc hook stack trace + + Subsequent optimization may cause multiple malloc functions in + google_malloc section to be in call stack. Particularly when fast-path + malloc function calls slow-path and compiler chooses to implement such + call as regular call instead of tail-call. + + Because we need stacktrace just until first such function, once + we find + innermost such frame, we're simply checking if next outer frame + is also + google_malloc and consider it instead. + +M src/malloc_hook.cc + +commit 0feb1109ac957144a50d964b0ff244a6a286174a +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 21:08:57 2016 -0800 + + fix stack trace capturing in debug malloc + + Particularly, hardcoded skip count was relying on certain behavior of + compiler. Namely, that tail calls inside DebugDeallocate path are not + actually implemented as tail calls. + + New implementation is using google_malloc section as a marker + of malloc + boundary. But in order for this to work, we have to prevent + tail-call in + debugallocation's tc_XXX functions. Which is achieved by doing + volatile + read of static variable at the end of such functions. + +M src/debugallocation.cc + +commit 0506e965ee5184490fbe7acea470458562128a79 +Author: Aliaksey Kandratsenka +Date: Sun Dec 18 18:36:00 2016 -0800 + + replace LIKELY/UNLIKELY with PREDICT_{TRUE,FALSE} + + Google-internal code is using PREDICT_TRUE/FALSE, so we should be + doing it too. + +M src/base/basictypes.h +M src/common.cc +M src/common.h +M src/emergency_malloc.h +M src/malloc_hook-inl.h +M src/tcmalloc.cc +M src/thread_cache.h + +commit 59a4987054021eaf24143a27cf01252fafb5052d +Author: Aliaksey Kandratsenka +Date: Sun Mar 13 16:04:43 2016 -0700 + + prevent inlining ATTRIBUTE_SECTION functions + + So that their code is always executing in prescribed section. + +M src/base/basictypes.h + +commit ebb575b8a0153a70f43fd1c3ec33fe30f94c97d0 +Author: Aliaksey Kandratsenka +Date: Thu Feb 2 15:41:13 2017 -0800 + + Revert "enabled aggressive decommit by default" + + This reverts commit 7da5bd014d77ddaf694054b1e3ae0a3ef92ab384. + + Some tensorflow benchmarks are getting slower with aggressive + decommit. + +M src/static_vars.cc +M src/tests/tcmalloc_unittest.sh + +commit b82d89cb7c8781a6028f6f5959cabdc5a273aec3 +Author: Aliaksey Kandratsenka +Date: Sun Jan 22 13:15:39 2017 -0800 + + Revert "disable dynamic sized delete support by default" + + This reverts commit 06811b3ae4c5365880898148d188ae91d20f52f2. + +M configure.ac + +commit fac0bb44d5661946d9839496ddf104942dd00abe +Author: Aliaksey Kandratsenka +Date: Sun Jan 22 13:11:05 2017 -0800 + + Do not depend on memchr in commandlineflags::StringToBool + + It lets us use it from inside ifunc handler. + +M src/base/commandlineflags.h + +commit 7d49f015a01e35155517332a2dfd95f16b568939 +Author: Aliaksey Kandratsenka +Date: Sun Jan 22 13:08:34 2017 -0800 + + Make GetenvBeforeMain work inside ifunc handler + + Depending on things such us strlen, which are ifunc-ed themselves is + not supported from inside ifunc handler. + + Thus we implement strlen, memchr and memcmp in slow naive C++ just for + that place. + +M src/base/sysinfo.cc + +commit a2550b6309153c250f67255b6271ec988cc7d0fb +Author: Aliaksey Kandratsenka +Date: Sun Feb 26 23:46:18 2017 -0800 + + turn bench_fastpath_throughput into actual throughput benchmark + + Previously we bumped size by 16 between iterations, but for many size + classess that gave is subsequent iteration into same size + class. Multiplying by prime number randomizes sizes more so speeds up + this benchmark on at least modern x86. + +M benchmark/malloc_bench.cc + +commit b762b1a4923f769487de818175655c1683d84db5 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 14:12:02 2016 -0800 + + added sized free benchmarks to malloc_bench + +M benchmark/malloc_bench.cc + +commit 71ffc1cd6b3ea99c97ed6d0e16caeb9d1b20eec7 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 14:11:40 2016 -0800 + + added free lists randomization step to malloc_bench + +M benchmark/malloc_bench.cc + +commit 732dfeb83d726de0aea47f0e6aa2abff3e0ad680 +Author: Aliaksey Kandratsenka +Date: Sun Jan 22 13:57:31 2017 -0800 + + Run StartStopNoOptionsEmpty profiledata unittest + + Somehow we had this test, but didn't arrange to actually run it. GCC + gave warning and now we do. + +M src/tests/profiledata_unittest.cc + +commit cbb312fbe8022378c4635b3075a80a7827555170 +Author: Aliaksey Kandratsenka +Date: Sun Dec 18 11:08:54 2016 -0800 + + aggressive decommit: only free necessary regions and fix O(N²) + + We used to decommit (with MADV_FREE or MADV_DONTNEED) whole combined + span when freeing span in aggressive decommit mode. The issue with + that is preceding or following span with which we combined span we're + freeing could be freed already and fairly large. By passing all of + that memory to decommit, we force kernel to scan all of those pages. + + When mass-freeing many objects old behavior led to O(N^2) behavior + since freeing single span could lead to MADV_{FREE,DONTNEED}-ing of + most of the heap. + + New implementation just does decommit of individual bits as needed. + + While there, I'm also adding locking to calls of + PageHeap::{Get,Set}AggressiveDecommit. + + This partially (or mostly) fixes issue #839. + +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc + +commit 6d98223a9035ec1c5e9a7eb0196b21021d48a41f +Author: Aliaksey Kandratsenka +Date: Sun Feb 12 17:12:44 2017 -0800 + + don't build with -fno-exceptions + + It looks like, in past it could produce better code. But since + unwinding is totally different since almost forever now, there is no + perfomance benefit of it anymore. + +M Makefile.am + +commit d6a1931cce303ea279b744c9b438686e4f5994e5 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 15:33:10 2016 -0800 + + fixed warning in casting heap of checker's main_thread_counter + + I.e. compiler didn't like int to void * casting and upcasting to + intptr_t first (which has same size as void *) makes it happier. + +M src/heap-checker.cc + +commit 5c778701d98c642ecff97d044cd1c0b8b862aba3 +Author: Aliaksey Kandratsenka +Date: Sun Feb 12 17:54:59 2017 -0800 + + added tcmalloc minimal unittest with ASSERTs checked + +M .gitignore +M Makefile.am + +commit a9167617abbcebe9d472141c53a20ce00c8c8d75 +Author: Aliaksey Kandratsenka +Date: Sat Apr 29 19:09:47 2017 -0700 + + drop unused g_load_map variable in patch_functionc.cc + +M src/windows/patch_functions.cc + +commit d52e56dcb5aad0521ccc67d7e57dfcb8d41ea568 +Author: Aliaksey Kandratsenka +Date: Sat Apr 29 19:06:55 2017 -0700 + + don't compare integer to NULL + +M src/windows/preamble_patcher.cc + +commit bae00c0341f49ade473d24c117226552a59d3e75 +Author: Aliaksey Kandratsenka +Date: Sun Apr 23 20:33:16 2017 -0700 + + add fake_stacktrace_scope to few msvc projects + + Otherwise it predictably fails at linking phase due to missing + symbols. + +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 79aab4fed40f9aac03dacb32a108861eff689beb +Author: Aliaksey Kandratsenka +Date: Sun Apr 16 22:17:56 2017 -0700 + + correctly dllexport nallocx on windows + +M src/gperftools/nallocx.h +M src/tcmalloc.cc + +commit b010895a088703f512cb0e225c838306b2904069 +Author: Aliaksey Kandratsenka +Date: Sun Apr 30 18:32:10 2017 -0700 + + don't undef PERFTOOLS_DLL_DECL + + This is not necessary and will help adding more headers with + dll-exported functions. + +M src/gperftools/tcmalloc.h.in +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 491b1aca7edbbaed9ea6f7baaa547a35cf385130 +Author: Aliaksey Kandratsenka +Date: Sat Apr 29 16:46:21 2017 -0700 + + don't try to use pthread_atfork on windows + +M src/maybe_threads.cc +M src/windows/mingw.h + +commit 691045b95761bedb9170d758be82f9b2f15c673a +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 14:41:28 2016 -0800 + + suppress warnings from legacy headers while building legacy headers + test + +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/google/tcmalloc.h +M src/tests/simple_compat_test.cc + +commit 22f7ceb97a63bcbc9d824a80916bb7a809fad1f2 +Author: Aliaksey Kandratsenka +Date: Sat Apr 29 15:25:06 2017 -0700 + + use unsigned for few flags in mini_disassembler_types.h + + We're initializing them with value that doesn't fit into signed 32-bit + int and somehow mingw version that I have not just warns, but actually + errors on that. + +M src/windows/mini_disassembler_types.h + +commit 9b17a8a5ba1c8320d12c6e6df0ab54ff218b50e6 +Author: Mostyn Bramley-Moore +Date: Thu May 11 20:40:18 2017 +0200 + + remove superfluous size_t value >= 0 check + +M src/debugallocation.cc + +commit 86ce69d77ff5f881c5701901bf7d1ef884f9e33a +Author: Eugene +Date: Sat Feb 4 17:57:34 2017 +0300 + + Update binary_trees.cc + +M benchmark/binary_trees.cc + +commit cd8586ed6c8bed550ad727ce8af83a1a6bd1ca8e +Author: Ola Olsson +Date: Tue Mar 21 14:07:16 2017 +0100 + + Fix path names in README + +M README + +commit 98753aa73772bb0fae8cee668e513d5754ab7737 +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 16:04:14 2017 -0800 + + test that sized deallocation really works before enabling it + + Weirdly, some OSX compiler does allow -fsized-deallocation, yet barks + on any attempt to actually use it at compile time (!). So lets detect + this as well in configure and opt out as necessary. + + Should fix issue #870. + +M configure.ac + +commit 5618ef78505a854bd0d2c145fd9cf7967226a20e +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 15:31:41 2017 -0800 + + Don't assume memalign exists in memalign vs nallocx test + + OSX and windows have issues with memalign. So test against tc_memalign + instead. + + This should fix _memalign linker-time part of issue #870. + +M src/tests/tcmalloc_unittest.cc + +commit bf640cd740fe38f6f10faa8683e8361fee971aba +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 14:51:27 2017 -0800 + + rename sys allocator's sys_alloc symbol to tcmalloc_sys_alloc + + Since we're not building with hidden visibility, symbols of other DSOs + can interpose our symbols. And sys_alloc is just too generic name. + + And in fact erlang runtime has sys_alloc function. Which means we're + trying to write to it's first bytes as part of initializing system + allocator and crash. + + This should fix issue #843. + +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/windows/system-alloc.cc + +commit 069e3b16551186f8da0a41c185550fdfd11af35b +Author: Aliaksey Kandratsenka +Date: Mon Feb 20 14:25:18 2017 -0800 + + build malloc_bench_shared_full only when full tcmalloc is built + + I.e. because otherwise, when --enable-minimal is given, we're building + empty libtcmalloc.la and linking it to malloc_bench_shared_full. Which + has no effect at all and actually breaks builds on OSX. + + Should fix issue #869. + +M Makefile.am + +commit b8f9d0d44f94177d34b069180618b7d002e85b69 +Author: Aliaksey Kandratsenka +Date: Sun Dec 18 09:35:02 2016 -0800 + + ported nallocx support from Google-internal tcmalloc + + nallocx is extension introduced by jemalloc. It returns effective size + of allocaiton without allocating anything. + + We also support MALLOCX_LG_ALIGN flag. But all other jemalloc + flags (which at the moment do nothing for nallocx anyways) are + silently ignored, since there is no sensible way to return errors in + this API. + + This was originally contributed by Dmitry Vyukov with input from + Andrew Hunter. But due to significant divergence of Google-internal + and free-software forks of tcmalloc, significant massaging was done by + me. So all bugs are mine. + +M Makefile.am +A src/gperftools/nallocx.h +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc + +commit b0abefd93834d9d9c7ffaae2d23bd48ed8e96477 +Author: Andrew Morrow +Date: Sat Dec 17 13:57:41 2016 -0500 + + Fix a typo in the page fence flag declaration + +M src/debugallocation.cc + +commit 855b3800064db49af823b85a54be269923eb6f4d +Author: Kirill Müller +Date: Tue Nov 15 09:58:11 2016 +0100 + + replace docs by doc + +M Makefile.am +M README +D doc +M packages/deb/docs +M packages/deb/libgperftools0.manpages +M src/gperftools/heap-checker.h +M src/gperftools/heap-profiler.h +M src/gperftools/profiler.h +M src/profiledata.h +M src/tcmalloc.cc + +commit 664210ead806d700cdbe5eeaf75d7a066fdac541 +Author: Kirill Müller +Date: Tue Nov 15 09:42:12 2016 +0100 + + doc -> docs, with symlink + +A doc +R100 doc/cpuprofile-fileformat.html docs/cpuprofile-fileformat.html +R100 doc/cpuprofile.html docs/cpuprofile.html +R100 doc/designstyle.css docs/designstyle.css +R100 doc/heap-example1.png docs/heap-example1.png +R100 doc/heap_checker.html docs/heap_checker.html +R100 doc/heapprofile.html docs/heapprofile.html +R100 doc/index.html docs/index.html +R100 doc/overview.dot docs/overview.dot +R100 doc/overview.gif docs/overview.gif +R100 doc/pageheap.dot docs/pageheap.dot +R100 doc/pageheap.gif docs/pageheap.gif +R100 doc/pprof-test-big.gif docs/pprof-test-big.gif +R100 doc/pprof-test.gif docs/pprof-test.gif +R100 doc/pprof-vsnprintf-big.gif docs/pprof-vsnprintf-big.gif +R100 doc/pprof-vsnprintf.gif docs/pprof-vsnprintf.gif +R100 doc/pprof.1 docs/pprof.1 +R100 doc/pprof.see_also docs/pprof.see_also +R100 doc/pprof_remote_servers.html docs/pprof_remote_servers.html +R100 doc/spanmap.dot docs/spanmap.dot +R100 doc/spanmap.gif docs/spanmap.gif +R100 doc/t-test1.times.txt docs/t-test1.times.txt +R100 doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png +R100 doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png +R100 doc/tcmalloc-opspersec.vs.size.1.threads.png +docs/tcmalloc-opspersec.vs.size.1.threads.png +R100 doc/tcmalloc-opspersec.vs.size.12.threads.png +docs/tcmalloc-opspersec.vs.size.12.threads.png +R100 doc/tcmalloc-opspersec.vs.size.16.threads.png +docs/tcmalloc-opspersec.vs.size.16.threads.png +R100 doc/tcmalloc-opspersec.vs.size.2.threads.png +docs/tcmalloc-opspersec.vs.size.2.threads.png +R100 doc/tcmalloc-opspersec.vs.size.20.threads.png +docs/tcmalloc-opspersec.vs.size.20.threads.png +R100 doc/tcmalloc-opspersec.vs.size.3.threads.png +docs/tcmalloc-opspersec.vs.size.3.threads.png +R100 doc/tcmalloc-opspersec.vs.size.4.threads.png +docs/tcmalloc-opspersec.vs.size.4.threads.png +R100 doc/tcmalloc-opspersec.vs.size.5.threads.png +docs/tcmalloc-opspersec.vs.size.5.threads.png +R100 doc/tcmalloc-opspersec.vs.size.8.threads.png +docs/tcmalloc-opspersec.vs.size.8.threads.png +R100 doc/tcmalloc.html docs/tcmalloc.html +R100 doc/threadheap.dot docs/threadheap.dot +R100 doc/threadheap.gif docs/threadheap.gif + +commit 75dc9a6e1470fa82b828f9687edad48f53d740b1 +Author: zmertens +Date: Fri Nov 18 15:27:32 2016 -0700 + + Fix Post(s)cript tyos + +M doc/pprof.1 +M src/pprof + +commit dde32f8bbc95312379f9f5a651799815bb6327c5 +Author: Francis Ricci +Date: Tue Oct 11 11:14:06 2016 -0700 + + Fix unaligned memory accesses in debug allocator + +M src/base/basictypes.h +M src/debugallocation.cc + +commit 02eeed29df112728564a5dde6417fa4622b57a06 +Author: Ryan Macnak +Date: Tue Sep 27 14:03:05 2016 -0700 + + Fix redefinition of mmap on aarch64. + +M src/base/linux_syscall_support.h + +commit c07a15cff4b904ac45e4019f8e36eeffd3e8186c +Author: Aliaksey Kandratsenka +Date: Sat Sep 24 18:56:22 2016 -0700 + + [windows] patch _free_base as well + + Looks like _free_base is used as generic free/delete, which is not + checked for free/delete mismatch by their debug runtime. Issue #817 + occurs because something that is allocated by regular allocation + functions (new or malloc) is freed by _free_base. Patch it as + well fixes + the problem. + + Closes #817. + +M src/windows/patch_functions.cc + +commit acac6af26b0ef052b39f61a59507b23e9703bdfa +Author: Aliaksey Kandratsenka +Date: Sat Sep 24 16:19:27 2016 -0700 + + Fix finding default zone on macOS sierra + + This is taken from jemalloc patch at + https://github.com/jemalloc/jemalloc/pull/427/commits/19c9a3e828ed46f1576521c264640e60bd0cb01f + by Mike Hommey (aka glandium). + + The issue was reported together with advise to take that jemalloc + fix by + Koichi Shiraishi and David Ribeiro Alves at gperftools issue #827. + + Closes issue #827. + +M src/libc_override_osx.h + +commit 7822b5b0b9fa7e016e1f6b46ea86f26f4691a457 +Author: Tulio Magno Quites Machado Filho +Date: Mon Aug 8 13:50:10 2016 -0300 + + Stop using glibc malloc hooks + + glibc deprecated malloc hooks in 2011 and will be removing them soon. + These hooks aren't safe and aren't necessary when the malloc API is + fully exported. + +M configure.ac +M src/libc_override_glibc.h + +commit c92f0ed0891d69888cdc7e904c82048362b2dd8d +Author: Tulio Magno Quites Machado Filho +Date: Wed Jul 27 17:15:52 2016 -0300 + + Remove references to __malloc_initialize_hook + + __malloc_initialize_hook has been deprecated in glibc since 2011 + and is + being removed on glibc 2.24. + +M src/libc_override_glibc.h + +commit 9709eef361aa8c46d6b14c08bebead7b8185e731 +Merge: eb474c9 44f276e +Author: Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) + +Date: Wed Aug 24 22:33:05 2016 -0700 + + Merge pull request #821 from jtmcdole/patch-1 + + Rename TCMALLOC_DEBUG to PERFTOOLS_VERBOSE + +commit 44f276e132eef8ba013a04b4af92ce26464e2b54 +Author: John McDole +Date: Wed Aug 24 17:47:28 2016 -0700 + + Rename TCMALLOC_DEBUG to PERFTOOLS_VERBOSE + +M README + +commit eb474c995eadef3edb47bc081f09693228832794 +Author: Aliaksey Kandratsenka +Date: Sun Jul 3 18:20:32 2016 -0700 + + Summary: support gcc atomic ops on clang too + + Clang actually does support __atomic_XXX atomic ops builtins but does + not advertise itselt as gcc 4.7 or later. So we now detect clang + separetely. + + We're enabling gcc atomic ops on clang >= 3.4 since this is the oldest + version that I can test. + + This should fix issue #797. + +M src/base/atomicops.h + +commit 7f86eab1f3e0636a79a96fd44e3bb51db0457a86 +Author: Kenton Varda +Date: Thu Jun 30 18:32:39 2016 -0700 + + Recognize .node files as shared libraries + + node.js extensions are regular shared libraries named with the `.node` + extension. With this small change I was able to get a usable heap + profile out of node to debug an extension I'm working on. + +M src/pprof + +commit bf8eacce69df877d1cecdab8c7a6cc3f218ebcc2 +Author: Bryan Chan +Date: Wed Jun 15 00:10:45 2016 -0400 + + Add support for 31-bit s390; merge linux_syscall_support.h changes + from upstream. + +M configure.ac +M m4/pc_from_ucontext.m4 +M src/base/basictypes.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.h +M src/getpc.h +M src/malloc_hook_mmap_linux.h + +commit c54218069b96e5a64e81186cd14107bf6660b61d +Author: savefromgoogle +Date: Sat May 14 17:50:34 2016 +0200 + + Update README + + typo corrected and direct link to Google Group mailinglist added + +M README + +commit 06f4ce65c226e2bed432119bd830a478012ea336 +Author: iivlev +Date: Fri Apr 15 17:46:25 2016 +0300 + + Small performance tweak: avoid calling time() if we don't need it + +M src/heap-profiler.cc + +commit db8d4836091b93100b176e8cab4e842974234e4e +Author: Aliaksey Kandratsenka +Date: Sat Jun 25 16:24:40 2016 -0700 + + Autogenerate ChangeLog from git on make dist + + This fixes build breakage introduced in preceding commit for issue + #796. + +A ChangeLog +M Makefile.am +M configure.ac +A m4/ax_generate_changelog.m4 + +commit 4a1359831938b5a71b2faf38c02003053af253d9 +Author: Aliaksey Kandratsenka +Date: Sat Jun 25 16:12:48 2016 -0700 + + renamed ChangeLog to ChangeLog.old + + I.e. to avoid confusion. This should fix issue #796. + +R100 ChangeLog ChangeLog.old + +commit 7852eeb75b9375cf52a7da01be044da6e915dd08 +Author: Aliaksey Kandratsenka +Date: Sat Apr 9 13:09:18 2016 -0700 + + Use initial-exec tls for libunwind's recursion flag + + If we don't do it, then reading variable calls to __tls_get_addr, + which + uses malloc on first call. initial-exec makes dynamic linker + reserve tls + offset for recusion flag early and thus avoid unsafe calls to malloc. + + This fixes issue #786. + +M src/base/basictypes.h +M src/stacktrace_libunwind-inl.h +M src/thread_cache.h + +commit a07f9fe75af25ce388af3d4ff4514b42513d766f +Author: Mike Gaffney +Date: Thu Mar 31 11:27:21 2016 -0700 + + gerftools -> gperftools in readme + +M README + +commit 9fd6d2687914a1f58a8ce457d6a1bd3d55ea0747 +Author: Aliaksey Kandratsenka +Date: Sun Mar 20 12:29:40 2016 -0700 + + added define to enable MADV_FREE usage on Linux + + Building with -DTCMALLOC_USE_MADV_FREE will enable usage of + MADV_FREE on + Linux if glibc copy of kernel headers has MADV_FREE defined. + + I.e. so that people can test this more easily. + + Affects ticket #780. + +M src/system-alloc.cc + +commit 6f7a14f45e2e2e16fbbd250543f5758078e2f5f0 +Author: Mathias Stearn +Date: Wed Mar 16 18:22:32 2016 -0400 + + Don't use MADV_FREE on Linux + + Addresses #780. + +M src/system-alloc.cc + +commit 55cf6e6281f2f19ed04a6b2a90e2dcaec08e16d0 +Author: Aman Gupta +Date: Mon Mar 14 12:20:40 2016 -0700 + + Fix symbol resolution on OSX + + The library mapping ranges on OSX and Linux are sorted in opposite + orders + + 7f71c3323000-7f71c3339000 r-xp 00000000 09:02 29099128 + /lib/x86_64-linux-gnu/libz.so.1.2.3.4 + 7f71c3339000-7f71c3538000 ---p 00016000 09:02 29099128 + /lib/x86_64-linux-gnu/libz.so.1.2.3.4 + 7f71c3538000-7f71c3539000 r--p 00015000 09:02 29099128 + /lib/x86_64-linux-gnu/libz.so.1.2.3.4 + 7f71c3539000-7f71c353a000 rw-p 00016000 09:02 29099128 + /lib/x86_64-linux-gnu/libz.so.1.2.3.4 + + vs + + 108f8d000-108f95000 r-xp 00025000 00:00 0 + /usr/local/opt/libmemcached/lib/libmemcached.11.dylib + 108f8c000-108f8d000 r-xp 00024000 00:00 0 + /usr/local/opt/libmemcached/lib/libmemcached.11.dylib + 108f68000-108f8c000 r-xp 00000000 00:00 0 + /usr/local/opt/libmemcached/lib/libmemcached.11.dylib + +M src/pprof + +commit 8e858436223db7729d41304ad29a29946d47382b +Author: Aliaksey Kandratsenka +Date: Sun Mar 13 15:11:50 2016 -0700 + + added simple .travis.yml config + +A .travis.yml + +commit 05e40d29c034c0d68322e589b8d6e234f562be2e +Author: Brian Silverman +Date: Tue Mar 8 15:58:02 2016 -0500 + + Recognize modern Linux ARM + + Commit e580d7888154fa7f95b3cef9e18f1ce69182212b fixed the macros + in some + of the code but not other places. + + `make check` still fails in the same places on a Debian Jessie armhf + system. + +M src/base/elfcore.h +M src/base/linuxthreads.h + +commit 632de2975e63f89613af9ab99bc1603a4a6332aa +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 11:48:20 2016 -0800 + + bumped version up to 2.5 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 6682016092c735feb29021acbb8c2067fdf1a209 +Author: Aliaksey Kandratsenka +Date: Sat Mar 12 10:54:05 2016 -0800 + + Unbreak profiling with CPUPROFILE_FREQUENCY=1 + + This closes ticket #777. + + No test sadly, since it's not trivial to unittest this case. But + fix with single-shot manual testing is better than nothing. + +M src/profile-handler.cc + +commit 6ff86ff6a783a277956e45db68c6a2b729f27000 +Author: Aliaksey Kandratsenka +Date: Sat Mar 5 16:17:28 2016 -0800 + + bumped version to 2.4.91 for 2.5rc2 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 782165fa7f2c49d6a67c2415626a1f215cc21ac2 +Author: Aliaksey Kandratsenka +Date: Sat Mar 5 15:47:25 2016 -0800 + + build sized delete aliases even when sized-delete is disabled + + In this case we alias to regular delete. This is helpful because if we + don't override sized delete, then apps will call version in libstdc++ + which delegates calls to regular delete, which is slower than calling + regular delete directly. + +M configure.ac +M src/libc_override_gcc_and_weak.h + +commit 06811b3ae4c5365880898148d188ae91d20f52f2 +Author: Aliaksey Kandratsenka +Date: Sat Mar 5 15:08:50 2016 -0800 + + disable dynamic sized delete support by default + + IFUNC relocations don't support our advanced use case (calling + application function or looking up environment variable). + + Particularly, it doesn't work on PPC and arm when tcmalloc is linked + with -Wl,-z,now. See RedHat's bugzilla ticket + https://bugzilla.redhat.com/show_bug.cgi?id=1312462 for more details. + +M configure.ac + +commit d4d99eb608f3d778fa301137a85cc4903a1dd33e +Author: Aliaksey Kandratsenka +Date: Sat Mar 5 14:53:42 2016 -0800 + + unbreak compilation with visual studio + + Specifically, this commit adds missing fake_stacktrace_scope.cc + to msvc + build and removes undef-ing of PERFTOOLS_DLL_DECL by tcmalloc.h. + +M src/gperftools/tcmalloc.h.in +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj + +commit 126d4582c18d053452d22ce12351c5429513aabe +Author: Brian Silverman +Date: Tue Mar 1 17:57:33 2016 -0500 + + Call function pointers with the right type + + I think it's undefined behavior, but it's definitely weird. ubsan + complains too. + +M src/tests/tcmalloc_unittest.cc + +commit e0fa28ef7d50158b271da90f53ab3aee5ba441d8 +Author: Brian Silverman +Date: Tue Mar 1 17:56:32 2016 -0500 + + Don't shift a type by more than its width + + It's undefined behavior, so ubsan complains. + +M src/tests/sampler_test.cc + +commit a1c764d2632cc0090f31d8d56effb94a8d049b54 +Author: Brian Silverman +Date: Tue Mar 1 17:55:59 2016 -0500 + + Initialize counters in test + +M src/tests/profile-handler_unittest.cc + +commit 22123a37c236e26535d3f3fff7f31a5b6515d7d6 +Author: Brian Silverman +Date: Tue Mar 1 17:55:53 2016 -0500 + + Don't overflow a signed integer + + It's undefined behavior and ubsan catches it. + +M src/base/low_level_alloc.cc + +commit 66e1e94f38467b5c7bbfb05e3c7267f3039a2c69 +Author: Aliaksey Kandratsenka +Date: Mon Feb 29 20:09:39 2016 -0800 + + added minimal "header section" to README + +M README + +commit 2804b7cfee8d49d5ab98340cbf3050c0a5f57b98 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 20:27:48 2016 -0800 + + bumped version to 2.5rc + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit f47fefbfc1083e7efbada3e7e7d2859d31e151e7 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 22:38:23 2016 -0800 + + updated NEWS for 2.5rc + +M NEWS + +commit cef60361741e858041f4bb4d46ce00c6db89b711 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 23:03:41 2016 -0800 + + alias same malloc/free variants to their canonical versions + + This is similar to what gcc 5 does anyways, except gcc 5 is placing + jumps which adds a bit of overhead. + + Instead of letting gcc do it, we alias using ELF symbol aliasing. All + free variants (tc_delete{,array}_{,nothrow}) are aliased to + tc_free. There are 3 malloc variants that differ by oom + handling. tc_newarray is aliased to tc_new. And tc_newarray_nothrow is + aliased to tc_new_nothrow. + + This aliasing only happens in non-debug malloc, since debug malloc + does + distinguish between different variants since it needs checking for + mismatch. + +M src/tcmalloc.cc + +commit ea8d242061460309d174d9053a224cf94e65e6fe +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 20:16:37 2016 -0800 + + Re-enable MultipleIdleNonIdlePhases test + + Which was accidentally removed as part of MarkThreadTemporarilyIdle + support. + +M src/tests/markidle_unittest.cc + +commit c9962f698b0edb37315445b33a06820f9bcf5df9 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 20:07:37 2016 -0800 + + added maybe_emergency_malloc.h to Makefile.am + + Because without this reference it isn't packaged by make dist. + +M Makefile.am + +commit 7dd4af65365d74a5d8d30d5811c26117a9192238 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 19:26:37 2016 -0800 + + don't round up sizes for large allocation when sampling + + This closes #723. + + Since rounding up prior to sampling is introducing possibility of + arithmetic overflow, we're just not doing it. + + It introduces some error (up to 4k), but since we're dealing with at + least 256k allocations, we're fine. + +M src/tcmalloc.cc + +commit 4f3410e759ec42cb307429222d690a81e3cd37b0 +Author: Aliaksey Kandratsenka +Date: Sun Feb 21 13:52:47 2016 -0800 + + enable emergency malloc by default on arm when using libunwind + + Because by default libunwind on arm does fopen which mallocs + which will + deadlock unless we enable emergency malloc. + +M configure.ac + +commit 7f12051dbe1f402771a747c1192a66e7571d94f9 +Author: Aliaksey Kandratsenka +Date: Sun Jan 31 23:17:50 2016 -0800 + + implemented emergency malloc + + Emergency malloc is enabled for cases when backtrace capturing + needs to + call malloc. In this case, we enable emergency malloc just prior to + calling such code and disable it after it is done. + +M Makefile.am +M configure.ac +M src/debugallocation.cc +A src/emergency_malloc.cc +A src/emergency_malloc.h +A src/emergency_malloc_for_stacktrace.cc +A src/fake_stacktrace_scope.cc +M src/malloc_hook.cc +A src/maybe_emergency_malloc.h +M src/stacktrace.cc +M src/tcmalloc.cc +M src/thread_cache.h + +commit 3ee2360250c639f02b354820bc50efc6e104b754 +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 21:49:58 2016 -0800 + + replaced invalid uses of __THROW + + We're now using it only when overriding glibc functions (such + as malloc + or mmap). In other cases (most importantly in public tcmalloc.h + header) + we're doing our own throw() to avoid possible breakage on future glibc + changes. + +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/libc_override_glibc.h +M src/libc_override_redefine.h +M src/tcmalloc.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 013b82abcfeaa158da2490ff86d6bff5a5434d7f +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 21:19:37 2016 -0800 + + unbreak inclusion in gperftools/tcmalloc.h + + We have shipped header which checked HAVE_XXX defines which we only + defined in project-local config.h. So it could never work correctly. + + We're now doing #include just like tc_mallinfo on constant + which we detect at configure time and write into header that we + install. + +M src/gperftools/tcmalloc.h.in + +commit 19903e6f156d0ff8063880ddc5051b5dc261c1ff +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 21:18:18 2016 -0800 + + drop detection of sys/malloc.h and malloc/malloc.h + + Which we don't really need. + +M configure.ac + +commit cdff090ebd7a3cef8de60109bef52251758181d7 +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 20:43:21 2016 -0800 + + Fix several harmless clang warnings + +M src/common.cc +M src/internal_logging.cc +M src/malloc_hook.cc +M src/tests/current_allocated_bytes_test.cc + +commit 9095ed08402620b04591c2d27ca222594f0da6db +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 20:33:27 2016 -0800 + + implemented stacktrace capturing via libgcc's C++ ABI function + + Particularly _Unwind_Backtrace which seems to be gcc extension. + + This is what glibc's backtrace is commonly is using. + + Using _Unwind_Backtrace directly is better than glibc's backtrace, + since + it doesn't call into dlopen. While glibc does dlopen when it is + built as + shared library apparently to avoid link-time dependency on libgcc_s.so + +M Makefile.am +M configure.ac +M src/stacktrace.cc +A src/stacktrace_libgcc-inl.h + +commit 728cbe102108be8296f2485e384392a4408ce9db +Author: Aliaksey Kandratsenka +Date: Sat Feb 20 13:06:08 2016 -0800 + + force profiler_unittest to do 'real' work + + 'XOR loop' in profiler unittest wasn't 100% effective because + it allowed + compiler to avoid loading and storing to memory. + + After marking result variable as volatile, we're now forcing + compiler to + read and write memory, slowing this loops down sufficiently. And + profiler_unittest is now passing more consistently. + + Closes #628 + +M src/tests/profiler_unittest.cc + +commit fff6b4fb8814b5f25d4f97889d5003537f7dcc92 +Author: Aliaksey Kandratsenka +Date: Sun Jan 31 23:14:43 2016 -0800 + + Extend low-level allocator to support custom pages allocator + +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h + +commit 32d992679589ea83e044d3f8263583ae960b0b16 +Author: Aliaksey Kandratsenka +Date: Sun Jan 31 22:42:20 2016 -0800 + + added malloc_bench_shared_full + +M .gitignore +M Makefile.am + +commit 00d8fa1ef8d6650f08e00f59baa22cd31b908432 +Author: Aliaksey Kandratsenka +Date: Sat Feb 6 19:13:07 2016 -0800 + + always use real throw() on operators new/delete + + Since non-glibc-s have no __THROW and lack of throw() on operators + gives + us warning. + +M src/libc_override_gcc_and_weak.h + +commit 08e034ad5940f24f99a24630c7b71a0de728d05b +Author: Aliaksey Kandratsenka +Date: Sat Feb 6 16:19:54 2016 -0800 + + Detect working ifunc before enabling dynamic sized delete support + + Particularly, on arm-linux and x86-64-debian-kfreebsd compilation + fails + due to lack of support for ifunc. So it is necessary to test at + configure time whether ifunc is supported. + +M configure.ac + +commit a788f354a0cd6de3d714a58ad3e6ae5baf806c3b +Author: Aliaksey Kandratsenka +Date: Sat Feb 6 16:01:25 2016 -0800 + + include unistd.h for getpid in thread_lister.c + + This fixes warning produced on arm-linux. + +M src/base/thread_lister.c + +commit 644a6bdbdb50b26a25e4428c43556467a6e8b5cc +Author: Bryan Chan +Date: Fri Jan 22 12:26:47 2016 -0500 + + Add support for Linux s390x + + This resolves gperftools/gperftools#761. + +M configure.ac +M m4/pc_from_ucontext.m4 +M src/base/basictypes.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.h +M src/malloc_hook_mmap_linux.h + +commit bab7753aad44b3395a063966f32c23f632fee174 +Author: Bryan Chan +Date: Fri Jan 29 02:38:42 2016 -0500 + + Fix typo in heap-checker-death_unittest.sh + +M src/tests/heap-checker-death_unittest.sh + +commit 17182e1d3c324e8fe9cc02ce2822caa746d7d17a +Author: Simon Que +Date: Fri Jan 29 18:17:16 2016 -0800 + + Fix include of malloc_hook_c.h in malloc_hook.h + + malloc_hook.h includes malloc_hook_c.h as + . + This requires the compiler to have designated src/gperftools as a + standard include directory (-I), which may not always be the case. + + Instead, include it as "malloc_hook_c.h", which will search in + the same + directory first. This will always work, regardless of whether it was + designated a standard include directory. + +M src/gperftools/malloc_hook.h + +commit c69721b2b2ceae426c36de191dd0a6fa443c5c7a +Author: Andrew Morrow +Date: Sun Nov 22 15:19:12 2015 -0500 + + Add support for obtaining cache size of the current thread and + softer idling + +M src/gperftools/malloc_extension.h +M src/gperftools/malloc_extension_c.h +M src/malloc_extension.cc +M src/tcmalloc.cc +M src/tests/markidle_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit 5ce42e535d6b3bf6c5e41ceb9cf876a70a7e3318 +Author: Brian Silverman +Date: Tue Jan 26 16:53:48 2016 -0500 + + Don't always arm the profiling timer. + + It causes a noticeable performance hit and can sometimes confuse GDB. + + Tested with CPUPROFILE_PER_THREAD_TIMERS=1. + + Based on an old version by mnissler@google.com. + +M src/profile-handler.cc +M src/profile-handler.h +M src/tests/profile-handler_unittest.cc + +commit 7f801ea091e03dae7b13160f76fecce15727c9c0 +Author: Duncan Sands +Date: Fri Jan 15 18:12:51 2016 +0100 + + Make sure the alias is not removed by link-time optimization when + it can prove + that it isn't used by the program, as it might still be needed to + override the + corresponding symbol in shared libraries (or inline assembler for + that matter). + For example, suppose the program uses malloc and free but not calloc + and is + statically linked against tcmalloc (built with -flto) and LTO + is done. Then + before this patch the calloc alias would be deleted by LTO due to + not being + used, but the malloc/free aliases would be kept because they are + used by the + program. Suppose the program is dynamically linked with a shared + library that + allocates memory using calloc and later frees it by calling free. + Then calloc + will use the libc memory allocator, because the calloc alias was + deleted, but + free will call into tcmalloc, resulting in a crash. + +M src/libc_override_gcc_and_weak.h + +commit 6b3e6ef5e0ab65030d116dd55dac8d64f9c72d33 +Author: Aliaksey Kandratsenka +Date: Sun Jan 24 19:45:16 2016 -0800 + + don't retain compatibility with old docdir behavior + + Since it is not really needed. And since we don't care about too + ancient + autoconfs. + +M configure.ac + +commit ccffcbd9e988a39654fe6ec5edd6d817f266ded9 +Author: Chris Mayo +Date: Sun Dec 27 18:55:05 2015 +0000 + + support use of configure --docdir argument + + Value of docdir was being overridden in Makefile. + + Retain compatibility with old Autoconf versions that do not provide + docdir. + +M Makefile.am +M configure.ac + +commit 050f2d28be8a63836bd74558b82be7983770a654 +Author: Aliaksey Kandratsenka +Date: Sat Dec 12 18:27:40 2015 -0800 + + use alias attribute only for elf platforms + + It was reported that clang on OSX doesn't support alias + attribute. Most + likely because of executable format limitations. + + New code limits use of alias to gcc-compatible compilers on elf + platforms (various gnu and *bsd systems). Elf format is known + to support + aliases. + +M src/tcmalloc.cc + +commit 07b0b21ddd168d977c04b1395677de71bb3e402e +Author: cyshi +Date: Wed Dec 2 14:47:15 2015 +0800 + + fix compilation error in spinlock + +M src/base/spinlock.cc + +commit e14450366abc51c7a25256615179daf0bae1de34 +Author: gshirishfree +Date: Mon Nov 23 11:34:13 2015 -0800 + + Added better description for GetStats API + +M src/gperftools/malloc_extension.h + +commit 64892ae730b704a7f3f23bd8eaeaf206901df201 +Author: Aliaksey Kandratsenka +Date: Sat Nov 21 19:17:36 2015 -0800 + + lower default transfer batch size down to 512 + + Some workloads get much slower with too large batch size. + + This closes bug #678. + + binary_trees benchmark benefits from larger batch size. And I + found that + 512 is not much slower than huge value that we had. + +M src/common.cc + +commit 6fdfc5a7f40ebcff3fdaada1a2994ff54be2f9c7 +Author: Aliaksey Kandratsenka +Date: Sat Oct 24 23:16:45 2015 -0700 + + implemented enabling sized-delete support at runtime + + Under gcc 4.5 or greater we're using ifunc function attribute + to resolve + sized delete operator to either plain delete implementation + (default) or + to sized delete (if enabled via environment variable + TCMALLOC_ENABLE_SIZED_DELETE). + +M configure.ac +M src/libc_override_gcc_and_weak.h +M src/tests/tcmalloc_unittest.sh + +commit c2a79d063c949584170b3e7dd2939a4548c16079 +Author: Aliaksey Kandratsenka +Date: Fri Oct 23 21:44:04 2015 -0700 + + use x86 pause in spin loop + + This saves power and improves performance, particulary on SMT. + +M src/base/spinlock.cc + +commit 0fb6dd8aa3c2fe3245c31c138ec4dfb05efd7f6d +Author: Aliaksey Kandratsenka +Date: Fri Oct 23 22:09:25 2015 -0700 + + added binary_trees benchmark + +M .gitignore +M Makefile.am +A benchmark/binary_trees.cc + +commit a8852489e54e915d22abbdad1688d1f25ccb7925 +Author: Aliaksey Kandratsenka +Date: Sun Oct 18 00:40:15 2015 -0700 + + drop unsupported allocation sampling code in tcmalloc_minimal + +M src/tcmalloc.cc +M src/thread_cache.h + +commit a9db0ae516c225543976280047b22b1e0ca08b93 +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 21:12:28 2015 -0700 + + implemented (disabled by default) sized delete support + + gcc 5 and clang++-3.7 support sized deallocation from C++14. We are + taking advantage of that by defining sized versions of operator + delete. + + This is off by default so that if some existing programs that + define own + global operator delete without sized variant are not broken by + tcmalloc's sized delete operator. + + There is also risk of breaking exiting code that deletes objects using + wrong class (i.e. base class) without having virtual destructors. + +M configure.ac +M src/gperftools/tcmalloc.h.in +M src/libc_override_gcc_and_weak.h +M src/libc_override_redefine.h +M src/tcmalloc.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit 88686972b9caf8fd132c4e30d89da78c3d324c27 +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 11:15:37 2015 -0700 + + pass -fsized-deallocation to gcc 5 + + Otherwise it gives warning for declaration of sized delete operator. + +M Makefile.am +M configure.ac + +commit 0a18fab3af2f1b59b851836d319a1eff0db5d44e +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 21:07:54 2015 -0700 + + implemented sized free support via tc_free_sized + +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/tcmalloc.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in +M src/windows/patch_functions.cc + +commit 464688ab6ddb82db22ea9b934ddea192478e4535 +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 21:27:56 2015 -0700 + + speedup free code path by dropping "fast path allowed check" + +M src/tcmalloc.cc + +commit 10f7e207166bd6652ed8803b9885917bfbbd90d0 +Author: Aliaksey Kandratsenka +Date: Sat Oct 3 18:47:14 2015 -0700 + + added SizeMap::MaybeSizeClass + + Because it allows us to first check for smaller sizes, which is most + likely. + +M src/common.h + +commit 436e1dea43dc097525e43a43e6d79810ba6921b5 +Author: Aliaksey Kandratsenka +Date: Sat Oct 3 15:40:21 2015 -0700 + + slightly faster GetCacheIfPresent + +M src/thread_cache.h + +commit 04df911915ecfcbc5e6b13fdab1b86f825ed1938 +Author: Aliaksey Kandratsenka +Date: Sat Oct 3 15:38:33 2015 -0700 + + tell compiler that non-empty hooks are unlikely + +M src/malloc_hook-inl.h + +commit 8cc75acd1f4024ca978858b1cf85b45204ed32b2 +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 11:04:12 2015 -0700 + + correctly test for -Wno-unused-result support + + gcc is only giving warning for unknown -Wno-XXX flags so test never + fails on gcc even if -Wno-XXX is not supported. By using + -Wunused-result we're able to test if gcc actually supports it. + + This fixes issue #703. + +M configure.ac + +commit 7753d8239b1e427d83729b6d5c0401e1d80308fd +Author: Aliaksey Kandratsenka +Date: Sun Oct 4 18:26:59 2015 -0700 + + fixed clang warning about shifting negative values + +M src/base/basictypes.h + +commit ae09ebb3833f3f207b7623245e360ddf122b823e +Author: Jens Rosenboom +Date: Thu Nov 19 17:45:44 2015 +0100 + + Fix tmpdir usage in heap-profiler_unittest.sh + + Using a single fixed directory would break when tests were being + run in + parallel with "make -jN". + + Also, the cleanup at the end of the test didn't work because it + referred + to the wrong variable. + +M src/tests/heap-profiler_unittest.sh + +commit df34e71b575daa6e4fa7588ae0deb9d529566f08 +Author: Aliaksey Kandratsenka +Date: Sat Nov 21 16:03:09 2015 -0800 + + use $0 when referring to pprof + + This fixed debian bug #805536. Debian ships pprof under google-pprof + name so it is handy when google-pprof --help refers to itself + correctly. + +M src/pprof + +commit 7773ea64ee254700ef0ffc5673539f0e111a4f86 +Author: Adhemerval Zanella +Date: Fri Nov 6 16:29:12 2015 -0200 + + Alignment fix to static variables for system allocators + + This patch the placement new for some system allocator to force the + static buffer to pointer value. + +M src/memfs_malloc.cc +M src/system-alloc.cc + +commit c46eb1f3d2f7a2bdc54a52ff7cf5e7392f5aa668 +Author: Boris Sazonov +Date: Thu Oct 15 17:39:08 2015 +0300 + + Fixed printf misuse in pprof - printed string was passed as + format. Better use print instead + +M src/pprof + +commit 9bbed8b1a8f1229cf0f1b4185683f309267ee1b9 +Author: Boris Sazonov +Date: Wed Sep 23 19:46:13 2015 +0300 + + Fixed assembler argument passing inside _syscall6 on MIPS - it was + causing 'Expression too complex' compilation errors in spinlock + +M src/base/linux_syscall_support.h + +commit 962aa53c55968f62f548f6f6f4849a384b505ca0 +Author: Aliaksey Kandratsenka +Date: Sat Oct 10 20:31:50 2015 -0700 + + added more fastpath microbenchmarks + + This also makes them output nicer results. I.e. every benchmark is + run 3 + times and iteration duration is printed for every run. + + While this is still very synthetic and unrepresentave of malloc + performance + as a whole, it is exercising more situations in tcmalloc fastpath. So + it a + step forward. + +M Makefile.am +M benchmark/malloc_bench.cc +A benchmark/run_benchmark.c +A benchmark/run_benchmark.h + +commit 347a830689e4dba2adc1368d00fe4723ba726b4a +Author: Aliaksey Kandratsenka +Date: Sat Oct 10 15:58:11 2015 -0700 + + Ensure that PPROF_PATH is set for debugallocation_test + + Which fixes issue #728. + +M src/tests/debugallocation_test.sh + +commit a9059b7c30308a4f4ab25f00e55b67c649614ed3 +Author: Aliaksey Kandratsenka +Date: Sat Oct 10 15:35:54 2015 -0700 + + prevent clang from inlining Mallocer in heap checker unittest + + Looks like existing "trick" to avoid inlining doesn't really prevent + sufficiently smart compiler from inlining Mallocer function. Which + breaks tests, since test relies Mallocer having it's own separate + stack + frame. + + Making mallocer_addr variable volatile is seemingly enough to + stop that. + +M src/tests/heap-checker_unittest.cc + +commit 6627f9217d8897b297c6da038cfbcff6a3086cfa +Author: Aliaksey Kandratsenka +Date: Sat Sep 26 19:52:37 2015 -0700 + + drop cycleclock + +M Makefile.am +D src/base/cycleclock.h +M src/base/sysinfo.cc +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/packed-cache_test/packed-cache_test.vcproj + +commit f985abc29607b8a5662ddac7bd1ed99c71ceeb11 +Author: Aliaksey Kandratsenka +Date: Sat Sep 26 19:50:03 2015 -0700 + + amputate unportable and unused stuff from sysinfo + + We still check number of cpus in the system (in spinlock code), + but old + code was built under assumption of "no calls malloc" which is + not needed + in tcmalloc. Which caused it to be far more complicated than + necessary (parsing procfs files, ifdefs for different OSes and + arch-es). + + Also we don't need clock cycle frequency measurement. + + So I've removed all complexity of ald code and NumCPUs function and + replaced it with GetSystemCPUsCount which is straightforward and + portable call to sysconf. + + Renaming of cpus count function was made so that any further code that + we might port from Google that depends on old semantics of NumCPUs + will + be detected at compile time. And has to be inspected for whether it + really needs that semantics. + +M src/base/spinlock.cc +M src/base/sysinfo.cc +M src/base/sysinfo.h + +commit 16408eb4d71ecbb1dd3b3c7ff22c94bd254d7b58 +Author: Aliaksey Kandratsenka +Date: Tue Sep 29 11:59:25 2015 -0700 + + amputated wait_cycles accounting in spinlocks + + This is not needed and pulls in CycleClock dependency that lowers + code portability. + +M src/base/spinlock.cc +M src/base/spinlock.h + +commit fedceef40cd217ef406bc2522e9a8f879d60b0c0 +Author: Aliaksey Kandratsenka +Date: Tue Sep 29 11:55:35 2015 -0700 + + drop cycleclock reference in ThreadCache + +M src/thread_cache.cc + +commit d7fdc3fc9ddc0937eb7961b1d8c864cc8182f0d9 +Author: Aliaksey Kandratsenka +Date: Tue Sep 29 11:43:09 2015 -0700 + + dropped unused and unsupported synchronization profiling facility + + Spinlock usage of cycle counter is due do tracking of time it's spent + waiting for lock. But this tracking is only useful we actually have + synchronization profiling working, which dont have. Thus I'm dropping + calls to this facility with eye towards further removal of cycle clock + usage. + +M Makefile.am +M src/base/spinlock.cc +D src/base/synchronization_profiling.h + +commit 3a054d37c1f5323462bd77f55be02c5b0d764611 +Author: Aliaksey Kandratsenka +Date: Mon Sep 28 15:40:15 2015 -0700 + + dropped unused SpinLockWait function + +M src/base/spinlock.cc +M src/base/spinlock_internal.cc +M src/base/spinlock_internal.h + +commit 5b62d38329f04ee30fb475a36b552c1ebc4e1e79 +Author: Aliaksey Kandratsenka +Date: Mon Sep 28 10:27:49 2015 -0700 + + avoid checking for dup. entries on empty backtrace + + This might fix issue #721. But it is right thing to do + regardless. Since + if depth is 0 we'll be reading random "garbage" on the stack. + +M src/profiler.cc + +commit 7b9ded722e4cef9a44b8d8bfa80d3e1e108cf590 +Author: Aliaksey Kandratsenka +Date: Sat Sep 12 16:26:54 2015 -0700 + + fixed compiler warning in memory_region_map.cc + +M src/memory_region_map.cc + +commit 4194e485cbb5d8c59f65aba49da63c08ecc573da +Author: Aliaksey Kandratsenka +Date: Sat Sep 12 16:20:53 2015 -0700 + + Don't link libtcmalloc_minimal.so to libpthread.so + + So that LD_PRELOAD-ing doesn't force loading libpthread.so which may + slow down some single-threaded apps. + + tcmalloc already has maybe_threads facility that can detect if + libpthread.so is loaded (via weak symbols) and provide 'simulations' + of + some pthread functions that tcmalloc needs. + +M Makefile.am +M src/maybe_threads.cc +M src/maybe_threads.h +M src/static_vars.cc + +commit 121038308d8c5b34707614c44de265816a322563 +Author: Fredrik Mellbin +Date: Sun Sep 27 01:18:31 2015 +0200 + + Check if _MSC_VER is defined to avoid warnings + +M src/windows/port.h + +commit 73673229955cf35c5b3046ee3100d94e82d33bc2 +Author: Fredrik Mellbin +Date: Sun Sep 27 01:11:14 2015 +0200 + + Make default config.h work with VS2015 + +M src/windows/config.h + +commit ae0a444db06b2327441e6160eafa33d8b7b95629 +Author: Dair Grant +Date: Thu Oct 1 13:46:22 2015 +0100 + + Ensure ThreadCache objects are CACHELINE_ALIGNED. + +M src/base/basictypes.h +M src/common.cc +M src/system-alloc.cc + +commit ea0b1d315497771d9d077c754fb9d6a92d1c01dc +Author: Aliaksey Kandratsenka +Date: Sat Sep 26 11:13:13 2015 -0700 + + unbreak TestErrno again + + Somehow in previous commit I managed to break assignment of memalign + result to variable being tested. Luckily gcc gave me warning. + +M src/tests/tcmalloc_unittest.cc + +commit e53aef24add50bdee5ab2943d96e5c5b2b3bf596 +Author: Aliaksey Kandratsenka +Date: Sat Sep 26 09:58:45 2015 -0700 + + don't try to test memalign on windows + + This unbreaks tcmalloc_unittest.cc on windows. + +M src/tests/tcmalloc_unittest.cc + +commit 7707582448d5bdf311d88726c5f77fcbb0bedd09 +Merge: 5078abd 9eb63bd +Author: Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) + +Date: Sat Sep 26 09:43:50 2015 -0700 + + Merge pull request #717 from myrsloik/master + + Use correct mangled new and delete symbols on windows x64 + +commit 9eb63bddfb7a8a7b086bb3daceeeaa2e3b1d8f67 +Author: Fredrik Mellbin +Date: Thu Sep 24 19:57:26 2015 +0200 + + Use correct mangled new and delete symbols on windows x64 + +M src/windows/patch_functions.cc + +commit 5078abdb331e63d7a216994f186eb736861f8df7 +Author: fdeweerdt +Date: Tue Aug 18 09:27:39 2015 -0700 + + Don't discard curl options if timeout is not defined. + + Editing the options passed to curl via 'my @URL_FETCHER = ("curl", + "-s");' (in particular to add a -k to ignore self signed certs) fails + for some invocations of curl. In FetchDynamicProfile, 'my @fetcher = + AddFetchTimeout($fetch_timeout, @URL_FETCHER);' ends up being just + 'curl' if timeout is not defined. + + This happens because AddFetchTimeout doesn't retrieve all the + arguments + from the caller. + + [alk@tut.by: updated commit message] + Signed-off-by: Aliaksey Kandratsenka + +M src/pprof + +commit 54505f1d50c2d1f4676f5e87090b64a117fd980e +Author: Aliaksey Kandratsenka +Date: Sun Aug 2 19:28:03 2015 -0700 + + help clang with inlining important fast-path functions + + Clang's recent focus on code size doesn't help us in malloc fast-path + because somehow clang completely ignores inline directives. + + In order to help clang generate code that was actually intended by + original authors, we're adding always_inline attribute to key + fast-path functions. + + Clang also guessed likely branch "wrong" in couple places. Which is + now addressed by UNLIKELY declarations there. + +M src/tcmalloc.cc +M src/thread_cache.h + +commit 73c0c8c61b84e268bafd961bf304b2e4d296142f +Author: Aliaksey Kandratsenka +Date: Sun Aug 2 19:09:02 2015 -0700 + + moved do_mallor_or_cpp_alloc in better place + +M src/tcmalloc.cc + +commit 41aca070e85258d9d47b0ac47f5eddece8bf45ba +Author: Aliaksey Kandratsenka +Date: Sun Aug 2 10:53:32 2015 -0700 + + always set errno to ENOMEM on OOM condition and in single place + + While standards do not require us to set errno to ENOMEM in certain + places (like posix_memalign), existing code may sometimes set it + (i.e. because mmap or sbrk couldn't get memory from kernel) + anyways. And from my reading of glibc, it's malloc is doing more or + less same by just always setting ENOMEM on OOM condition. + + This commit also eliminates some functions (XXX_no_errno) that are not + needed anymore. + +M src/debugallocation.cc +M src/page_heap.cc +M src/tcmalloc.cc + +commit c4493874cd3b662d2778f3b79a3096ae61569b67 +Author: Aliaksey Kandratsenka +Date: Sat Aug 1 22:20:15 2015 -0700 + + deal with OOM handling in one place and prior to returning result + + This commit removes 4 (four!) duplicates of C++ OOM handling. And + introduces one helper for that. + + Other change is that malloc doesn't have to check tc_new_mode anymore + until it _actually_ deals with OOM condition. Which shaves off couple + instructions from fast-path. + +M src/debugallocation.cc +M src/tcmalloc.cc + +commit 09448a8fe977eaa083340c2504caac8820832179 +Author: Aliaksey Kandratsenka +Date: Sun Aug 2 18:11:04 2015 -0700 + + added tcmalloc_unittest path with TCMALLOC_HEAP_LIMIT_MB=512 + + I.e. so that we can exercise "voluntary" OOM conditions better. + +M src/tests/tcmalloc_unittest.sh + +commit 73fb7c7eb37e488bab8298be4110e30d83af2184 +Author: Aliaksey Kandratsenka +Date: Sun Aug 2 01:47:55 2015 -0700 + + added test on errno = ENOMEM on out of memory + +M src/tests/tcmalloc_unittest.cc + +commit eb725ff26371dfb5ae2523802c6abe75833cacef +Author: Aliaksey Kandratsenka +Date: Sat Aug 1 20:54:39 2015 -0700 + + unbreak heap-profiler-unittest on gcc 5 + + gcc 5 has got nice new optimization (-fipa-icf) which merges identical + functions into one. And that causes heap-profiler_unittest to fail + since it expects to see both Allocate and Allocate2 in heap + profiles. And smart GCC detects that they are same function and makes + one function out of two and thus breaks this test. + + New code simply adds (disabled) logging calls to make those functions + non-identical. + +M src/tests/heap-profiler_unittest.cc + +commit 53833298f3822b2b8b78c9dc85160d65d78a6857 +Author: Aliaksey Kandratsenka +Date: Sat Aug 1 19:46:34 2015 -0700 + + unbreak heap_checker_unittest on gcc 5 + + GCC 5 ended up too smart and optimized out assignment of allocated + block to global variable. Which caused test to fail since it triggered + unexpected "leak". + +M src/tests/heap-checker_unittest.cc + +commit 024bae96ce8e1591993fc0da191ce0a92d609481 +Author: Aliaksey Kandratsenka +Date: Sat Aug 1 17:41:42 2015 -0700 + + dropped support for PREANSINEW define which nobody needs anymore + +M src/debugallocation.cc +M src/tcmalloc.cc + +commit 64e0133901a20f83c41adb36748fd19d21228515 +Author: Aliaksey Kandratsenka +Date: Sun May 3 12:55:47 2015 -0700 + + added trivial malloc fast-path benchmark + + While this is not good representation of real-world production malloc + behavior, it is representative of length (instruction-wise and well as + cycle-wise) of fast-path. So this is better than nothing. + +M .gitignore +M Makefile.am +A benchmark/malloc_bench.cc + +commit e1d1311cfb6312cd44e086c879f3e95cbfa0eb9d +Author: Tom Conerly +Date: Mon Jul 27 11:35:29 2015 -0700 + + issue-699: Free list on error paths + +M src/heap-profile-table.cc + +commit b5b79860fd2b8e1a9b0573e93f942695f2992b59 +Author: Aliaksey Kandratsenka +Date: Sat Aug 1 11:24:56 2015 -0700 + + issue-702: correctly declare arg-less functions in profiler.h + + This is patch by user mitchblank. + + From his words: + + The problem is pretty simple. Ancient C code allowed declarations + without argument prototypes, i.e. + + int foo(); + + For compatibility this is still accepted. If you want to declare a + function with zero prototypes the correct way to do it is: + + int foo(void); + + C++ also accepts this syntax, but it's not needed there. + + Normally compilers still accept the old-style entries, but with + sufficient warning flags gcc will complain about them. It is good for + header files to have the explicit "void" argument so all compilers are + kept happy. + + I'm attaching a simple patch to add the "void" parameter to that file. + I haven't checked if other headers have the same problem (I'm just + using the profiler at the moment) + + + + In fact "int foo()" means "foo accepts any args" and we really want + "foo has no args". For which int foo (void) is right declaration. + +M src/gperftools/profiler.h + +commit 7df7f14c949d89d9c3f5c7c339bbdda81fb8abc7 +Author: Aliaksey Kandratsenka +Date: Sat Jun 13 21:35:06 2015 -0700 + + issue-693: enable futex usage on arm + + This patch was contributed by user spotrh. + +M src/base/linux_syscall_support.h +M src/base/spinlock_linux-inl.h + +commit cb998e56d763cfe901cf30a692d4cfd4f85259ae +Author: Aliaksey Kandratsenka +Date: Sat Jun 13 21:28:28 2015 -0700 + + issue-693: convert sys_futex to it's 6-arg form + + Because sys_futex actually takes 6 args in more recent kernels (even + though last two args are unused for FUTEX_{WAKE,WAIT}. + + This is patch contributed by user spotrh. + +M src/base/linux_syscall_support.h + +commit 36066b8df4bc516ade5209a1f60bd84d6448b531 +Author: Aliaksey Kandratsenka +Date: Sat Jun 27 21:15:30 2015 -0700 + + issue-695: implementated TCMALLOC_TRACE_FILE variable + + This is contributed by Paolo Bonzini. + + This commit adds TCMALLOC_TRACE_FILE environment variable, which if + defined overrides location of malloc trace file. + +M src/debugallocation.cc + +commit c4069d2d37b67296d675c2d1de42a46dc6d43efc +Author: Brian Silverman +Date: Tue Jun 16 16:56:48 2015 -0700 + + Add empty virtual destructor to class with virtual methods. + + Clang 3.5 has a warning about deleting objects with virtual methods + through non-virtual destructors which was triggered. I'm not sure + whether this actually creates any undefined or otherwise incorrect + behavior, but it seems like a good thing to fix regardless. + + Example compiler warning: + third_party/gperftools/src/tests/profile-handler_unittest.cc:282:5: + error: + delete called on '(anonymous namespace)::BusyThread' that has + virtual + functions but non-virtual destructor [-Wdelete-non-virtual-dtor] + delete busy_worker_; + ^ + +M src/tests/profile-handler_unittest.cc + +commit 019362fefcdca39a46d1a831ed46266c24b9a273 +Author: Patrick LoPresti +Date: Mon May 25 11:56:51 2015 -0700 + + Add support for CPUPROFILE_TIMER_SIGNAL environment variable. + + Which both enables per-thread timers and allows the signal number for + the timer to be selected. + + [alk@tut.by: reformatted commit message for subject line length] + Signed-off-by: Aliaksey Kandratsenka + +M src/profile-handler.cc +M src/tests/profile-handler_unittest.cc + +commit 81d8d2a9e7f941a2051781fd0fe62c683c32f1ef +Author: Milton Chiang +Date: Wed May 13 21:53:05 2015 +0800 + + Add "ARMv8-A" to the supporting list of ARM architecture. + +M src/base/arm_instruction_set_select.h + +commit 64d1a86cb8da245c982d470a7dfdd635197e6e5e +Author: Aliaksey Kandratsenka +Date: Sat May 9 15:38:12 2015 -0700 + + include time.h for struct timespec on Visual Studio 2015 + + This patch was submitted by user wmamrak. + +M src/windows/port.h + +commit 7013b219970a329d1db58fbd7fa7c907bec8dbba +Author: Aliaksey Kandratsenka +Date: Sat May 9 12:48:11 2015 -0700 + + hook mi_force_{un,}lock on OSX instead of pthread_atfork + + This is patch by Anton Samokhvalov. + + Apparently it helps with locking around forking on OSX. + +M src/libc_override_osx.h +M src/static_vars.cc + +commit f25f8e0bf2d361f852929848d79d7ba54586c352 +Author: Angus Gratton +Date: Mon May 4 08:18:43 2015 +1000 + + Clarify that only tcmalloc_minimal is supported on Windows. + +M INSTALL +M README_windows.txt + +commit 772a686c45455893708178d3b59b1d3b571015aa +Author: Aliaksey Kandratsenka +Date: Sun May 3 13:15:16 2015 -0700 + + issue-683: fix compile error in clang with -m32 and 64-bit off_t + +M src/malloc_hook_mmap_linux.h + +commit 0a3bafd645764250732f3c0627534142568f6f1f +Author: Aliaksey Kandratsenka +Date: Sat Apr 11 10:35:53 2015 -0700 + + fix typo in PrintAvailability code + + This is patch contributed by user ssubotin. + +M src/windows/nm-pdb.c + +commit 6ce10a2a05f13803061538d5c77e89695de59be4 +Author: Matt Cross +Date: Thu Mar 26 16:13:56 2015 -0400 + + Add support for printing collapsed stacks for generating flame graphs. + +M src/pprof + +commit 2c1a165fa56a6f8dff8fa2662ceda971ad676ead +Author: Matt Cross +Date: Thu Mar 26 12:10:23 2015 -0400 + + Add support for reading debug symbols automatically on systems + where shared libraries with debug symbols are installed at + "/usr/lib/debug/.debug", such as RHEL and CentOS. + +M src/pprof + +commit 2e654956287043a30aeaec20e5c19650358af618 +Author: Jonathan Lambrechts +Date: Fri Feb 13 18:52:21 2015 +0100 + + callgrind : handle inlined functions + +M src/pprof + +commit 90d7408d381cf2ad68ce4974cbccd51ed5222ca3 +Author: Jonathan Lambrechts +Date: Fri Feb 13 18:51:33 2015 +0100 + + pprof : callgrind : fix unknown files + +M src/pprof + +commit aa963a24ae7a74b095a631ea6a86cd071c453911 +Author: Aliaksey Kandratsenka +Date: Mon Feb 9 08:35:03 2015 -0800 + + issue-672: fixed date of news entry of gperftools 2.4 release + + It is 2015 and not 2014. Spotted and reported by Armin Rigo. + +M NEWS + +commit c66aeabdbacbfd3aff7a6633f34526ca32642f67 +Author: Aliaksey Kandratsenka +Date: Sat Jan 10 14:35:54 2015 -0800 + + fixed default value of HEAP_PROFILER_TIME_INTERVAL in .html doc + +M doc/heapprofile.html + +commit 689e4a5bb4b2a8afecb85e83b8e4f294f80b6124 +Author: Aliaksey Kandratsenka +Date: Sat Jan 10 12:26:51 2015 -0800 + + bumped version to 2.4 + +M NEWS +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 3f5f1bba0c2cb4862c38b0c9050f1cede8a5c344 +Author: Aliaksey Kandratsenka +Date: Sun Dec 28 18:18:27 2014 -0800 + + bumped version to 2.4rc + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit c4dfdebc796c2e802db686a7eea483f3d31edbcf +Author: Aliaksey Kandratsenka +Date: Sun Dec 28 17:53:02 2014 -0800 + + updated NEWS for gperftools 2.4rc + +M NEWS + +commit 0096be5f6f0bb2a01438ee78b7bb6158ffa5a1fb +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 17:17:41 2014 -0800 + + pprof: allow disabling auto-removal of "constant 2nd frame" + + "constand 2nd frame" feature is supposed to detect and workaround + incorrect cpu profile stack captures where parts of or whole cpu + profiling signal handler frames are not skipped. + + I've seen programs where this feature incorrectly removes non-signal + frames. + + Plus it actually hides bugs in stacktrace capturing which we want be + able to spot. + + There is now --no-auto-signal-frm option for disabling it. + +M src/pprof + +commit 4859d8020579cd8db8b1f8bc6af382104b38f96f +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 19:56:13 2014 -0800 + + cpuprofiler: drop correct number of signal handler frames + + We actually have 3 and not 2 of them. + +M src/profiler.cc + +commit 812ab1ee7e4365e6a9568834c7e8f4aef10018fb +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 19:53:12 2014 -0800 + + pprof: eliminate duplicate top frames if dropping signal frames + + In cpu profiles that had parts of signal handler we could have + situation like that: + + * PC + * signal handler frame + * PC + + Specifically when capturing stacktraces via libunwind. + + For such stacktraces pprof used to draw self-cycle in functions + confusing everybody. Given that me might have a number of such + profiles in the wild it makes sense to treat that duplicate PC issue. + +M src/pprof + +commit e6e78315e4761ad121a5eeb4fdffe3571d81ac17 +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 19:04:43 2014 -0800 + + cpuprofiler: better explain deduplication of top stacktrace entry + +M src/profiler.cc + +commit 24b8ec28464712bc124af5655ebf877fb3f79032 +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 17:10:38 2014 -0800 + + cpuprofiler: disable capturing stacktrace from signal's ucontext + + This was reported to cause problems due to libunwind occasionally + returning top level pc that is 1 smaller than real pc which causes + problems. + +M src/stacktrace_libunwind-inl.h + +commit 83588de7204124c8d60703f169c2f3af8aa0ce5f +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 17:04:10 2014 -0800 + + pprof: added support for dumping stacks in --text mode + + Which is very useful for diagnosing stack capturing and processing + bugs. + +M src/pprof + +commit 2f29c9b06220ce6ad75d5ab2b98e9f63ade79eea +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 17:03:36 2014 -0800 + + pprof: made --show-addresses work + +M src/pprof + +commit b8b027d09a53dd6292d2f7c45aec40198628a808 +Author: Raphael Moreira Zinsly +Date: Tue Dec 23 10:55:22 2014 -0200 + + Make PPC64 use 64K of internal page size for tcmalloc by default + + This patch set the default tcmalloc internal page size to 64K when + built on PPC. + +M configure.ac + +commit 3f55d874be8812aef9f0f567048188584962b4c1 +Author: Raphael Moreira Zinsly +Date: Tue Dec 23 10:29:49 2014 -0200 + + New configure flags to set the alignment and page size of tcmalloc + + Added two new configure flags, --with-tcmalloc-pagesize and + --with-tcmalloc-alignment, in order to set the tcmalloc internal page + size and tcmalloc allocation alignment without the need of a compiler + directive and to make the choice of the page size independent of the + allocation alignment. + +M INSTALL +M configure.ac +M src/common.h + +commit 1035d5c18f64d114ac790b92a96f3b3a1a301eb9 +Author: Aliaksey Kandratsenka +Date: Sun Dec 21 19:52:34 2014 -0800 + + start building malloc_extension_c_test even with static linking + + Comment in Makefile.am stating that it doesn't work with static + linking is not accurate anymore. + +M Makefile.am + +commit d570a6391cf4c5a5570e22ada5cf0b324c7b8dfd +Author: Aliaksey Kandratsenka +Date: Sun Dec 21 19:33:25 2014 -0800 + + unbreak malloc_extension_c_test on clang + + Looks like even force_malloc trick was not enough to force clang to + actually call malloc. I'm now calling tc_malloc directly to prevent + that smartness. + +M src/tests/malloc_extension_c_test.c + +commit 4ace8dbbe2e04da1029a539c72b90dee1724c33f +Author: Aliaksey Kandratsenka +Date: Sun Dec 21 18:49:47 2014 -0800 + + added subdir-objects automake options + + This is suggested by automake itself regarding future-compat. + +M .gitignore +M Makefile.am + +commit f72e37c3f99d942dd648e392abc65f294aa94fa8 +Author: Aliaksey Kandratsenka +Date: Sun Dec 21 18:27:03 2014 -0800 + + fixed C++ comment warning in malloc_extension_c.h from C compiler + +M src/gperftools/malloc_extension_c.h + +commit f94ff0cc0943c7b7bb9390f9d83a57c9d9e11fd0 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 14:41:36 2014 -0800 + + made AtomicOps_x86CPUFeatureStruct hidden + + So that access to has_sse2 is faster under -fPIC. + +M src/base/atomicops-internals-x86.h + +commit 987a724c23df4b29eb457e96bb5c1bbab15dc90e +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 14:20:20 2014 -0800 + + dropped atopmicops workaround for irrelevant Opteron locking bug + + It's not cheap at all when done in this way (i.e. without runtime + patching) and apparently useless. + + It looks like Linux kernel never got this workaround at all. See + bugzilla ticket: https://bugzilla.kernel.org/show_bug.cgi?id=11305 + + And I see no traces of this workaround in glibc either. + + On the other hand, opensolaris folks apparently still have it (or + something similar, based on comments on linux bugzilla) in their code: + https://github.com/illumos/illumos-gate/blob/32842aabdc7c6f8f0c6140a256cf42cf5404fefb/usr/src/uts/i86pc/os/mp_startup.c#L1136 + + And affected CPUs (if any) are from year 2008 (that's 6 years now). + + Plus even if somebody still uses those cpus (which is unlikely), they + won't have working kernel and glibc anyways. + +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h + +commit 7da5bd014d77ddaf694054b1e3ae0a3ef92ab384 +Author: Aliaksey Kandratsenka +Date: Sat Dec 20 21:18:07 2014 -0800 + + enabled aggressive decommit by default + + TCMALLOC_AGGRESSIVE_DECOMMIT=f is one way to disable it and + SetNumericProperty is another. + +M src/static_vars.cc +M src/tests/tcmalloc_unittest.sh + +commit 51b0ad55b3267caff6cd2d25815bfb913179b526 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 17:36:49 2014 -0800 + + added basic unit test for singular malloc hooks + +M src/tests/malloc_extension_c_test.c + +commit bce72dda078d2cb3e9745077f9903e642a966131 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 17:12:05 2014 -0800 + + inform compiler that tcmalloc allocation sampling is unlikely + + Now compiler generates slightly better code which produces jump-less + code for common case of not sampling allocations. + +M src/tcmalloc.cc + +commit 4f051fddcd7af53e1607b6a4866ffa461a0033ef +Author: Aliaksey Kandratsenka +Date: Sat Mar 15 13:18:28 2014 -0700 + + eliminated CheckIfKernelSupportsTLS + + We don't care about pre-2.6.0 kernels anymore. So we can assume that + if compile time check worked, then at runtime it'll work. + +M src/tcmalloc.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/port.cc + +commit 81291ac3992ec7500faf2026c72feb80c9634dc3 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 16:48:45 2014 -0800 + + set elf visibility to hidden for malloc hooks + + To speed up access to them under -fPIC. + +M src/malloc_hook-inl.h + +commit 105c004d0c84137f32cc71b8d3f7899fcc8c2e72 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 14:40:30 2014 -0800 + + introduced ATTRIBUTE_VISIBILITY_HIDDEN + + So that we can disable elf symbol interposition for certain + perf-sensitive symbols. + +M src/base/basictypes.h + +commit 6a6c49e1f53df3d00a0661a86090534146ce686c +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 16:23:06 2014 -0800 + + replaced separate singular malloc hooks with faster HookList + + Specifically, we can now check in one place if hooks are set at all, + instead of two places. Which makes fast path shorter. + +M src/malloc_hook-inl.h +M src/malloc_hook.cc + +commit ba0441785bae214566008e69adcd915800d9dbb3 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 16:13:54 2014 -0800 + + removed extra barriers in malloc hooks mutation methods + + Because those are already done under spinlock and read-only and + lockless Traverse is already tolerant to slight inconsistencies. + +M src/malloc_hook.cc + +commit 890f34c77ef79dfe1e00ce36a3f91aee7fe759b7 +Author: Aliaksey Kandratsenka +Date: Sun Nov 9 16:08:59 2014 -0800 + + introduced support for deprecated singular hooks into HookList + + So that we can later drop separate singular hooks. + +M src/malloc_hook-inl.h +M src/malloc_hook.cc + +commit 81ed7dff11de915b12c4111d403e52c81c786f82 +Author: Aliaksey Kandratsenka +Date: Sun Dec 7 13:33:40 2014 -0800 + + returned date of 2.3rc in NEWS back + +M NEWS + +commit 463a619408219fff8955d47a71de1aab31ebd129 +Author: Aliaksey Kandratsenka +Date: Sun Dec 7 12:53:35 2014 -0800 + + bumped version to 2.3 + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 76e8138e12567e2ee1f638e8fcffadc2ca1de83d +Author: Aliaksey Kandratsenka +Date: Sun Dec 7 12:46:49 2014 -0800 + + updated NEWS for gperftools 2.3 + +M NEWS + +commit 8eb4ed785ae883acb6425fd980e9d3e6bdcab89d +Author: Raphael Moreira Zinsly +Date: Thu Nov 27 14:11:09 2014 -0200 + + Added option to disable libunwind linking + + This patch adds a configure option to enable or disable libunwind + linking. + The patch also disables libunwind on ppc by default. + +M configure.ac + +commit 3b94031d21fac39ce5be820f4f8bc37626ed4c08 +Author: Aliaksey Kandratsenka +Date: Thu Nov 27 11:48:08 2014 -0800 + + compile libunwind unwinder only of __thread is supported + + This fixed build on certain OSX that I have access to. + +M src/stacktrace.cc + +commit 3ace468202a8647a16134d0bb42fa497fa3ec0d4 +Author: Aliaksey Kandratsenka +Date: Thu Nov 27 10:43:11 2014 -0800 + + issue-658: correctly close socketpair fds when socketpair fails + + This applies patch by glider. + +M src/symbolize.cc + +commit e7d5e512b068fb76f5eeed7985bebd9c0d14e226 +Author: Aliaksey Kandratsenka +Date: Sun Nov 2 20:02:12 2014 -0800 + + bumped version to 2.3rc + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 1d44d378513a8782c058833118b664f38214810b +Author: Aliaksey Kandratsenka +Date: Sun Nov 2 19:38:29 2014 -0800 + + updated NEWS for gperftools 2.3rc + +M NEWS + +commit 1108d83cf4a1692fce3b736e16d3e98c33329177 +Author: Aliaksey Kandratsenka +Date: Sun Sep 7 13:09:14 2014 -0700 + + implemented cpu-profiling mode that profiles threads separately + + Default mode of operation of cpu profiler uses itimer and + SIGPROF. This timer is by definition per-process and no spec defines + which thread is going to receive SIGPROF. And it provides correct + profiles only if we assume that probability of picking threads will be + proportional to cpu time spent by threads. + + It is easy to see, that recent Linux (at least on common SMP hardware) + doesn't satisfy that assumption. Quite big skews of SIGPROF ticks + between threads is visible. I.e. I could see as big as 70%/20% + division instead of 50%/50% for pair of cpu-hog threads. (And I do see + it become 50/50 with new mode) + + Fortunately POSIX provides mechanism to track per-thread cpu time via + posix timers facility. And even more fortunately, Linux also provides + mechanism to deliver timer ticks to specific threads. + + Interestingly, it looks like FreeBSD also has very similar facility + and seems to suffer from same skew. But due to difference in a way + how threads are identified, I haven't bothered to try to support this + mode on FreeBSD. + + This commit implements new profiling mode where every thread creates + posix timer which tracks thread's cpu time. Threads also also set up + signal delivery to itself on overflows of that timer. + + This new mode requires every thread to be registered in cpu + profiler. Existing ProfilerRegisterThread function is used for that. + + Because registering threads requires application support (or suitable + LD_PRELOAD-able wrapper for thread creation API), new mode is off by + default. And it has to be manually activated by setting environment + variable CPUPROFILE_PER_THREAD_TIMERS. + + New mode also requires librt symbols to be available. Which we do not + link to due to librt's dependency on libpthread. Which we avoid due + to perf impact of bringing in libpthread to otherwise single-threaded + programs. So it has to be either already loaded by profiling program + or LD_PRELOAD-ed. + +M Makefile.am +M configure.ac +M src/maybe_threads.cc +M src/maybe_threads.h +M src/profile-handler.cc +M src/tests/profile-handler_unittest.cc + +commit 714bd93e42535e759716324a90fbb395506499d2 +Author: Aliaksey Kandratsenka +Date: Sun Aug 10 20:28:11 2014 -0700 + + drop workaround for too old redhat 7 + + Note that this is _not_ RHEL7 but original redhat 7 from early 2000s. + +M configure.ac + +commit 8de46e66fcd2577758ab297b553bb0f468d8a97a +Author: Aliaksey Kandratsenka +Date: Sun Aug 10 19:38:07 2014 -0700 + + don't add leaf function twice to profile under libunwind + +M src/profiler.cc + +commit 2e5ee0488996437aeef2028ad95d969b56abcad1 +Author: Aliaksey Kandratsenka +Date: Sun Aug 10 12:19:45 2014 -0700 + + pprof: indicate if using remote profile + + Missing profile file is common source of confusion. So a bit more + clarify is useful. + +M src/pprof + +commit 6efe96b41c9531f68f806faa0464445f884178ce +Author: Aliaksey Kandratsenka +Date: Sat Oct 11 15:09:18 2014 -0700 + + issue-493: correctly detect __ARM_ARCH_6ZK__ for MemoryBarrier + + Which should fix issue reported by user pedronavf + +M src/base/atomicops-internals-arm-v6plus.h + +commit 8e97626378d5c4151a480dea1964e25969c9311d +Author: Aliaksey Kandratsenka +Date: Sun Nov 2 11:28:30 2014 -0800 + + issue-655: use safe getenv for aggressive decommit mode flag + + Because otherwise we risk deadlock due to too early use of getenv on + windows. + +M src/base/commandlineflags.h +M src/static_vars.cc + +commit 8c3dc52fcfe02412a529769a22cbc75388a5d368 +Author: Aliaksey Kandratsenka +Date: Sat Oct 18 16:35:57 2014 -0700 + + issue-654: [pprof] handle split text segments + + This applies patch by user simonb. + + Quoting: + + Relocation packing splits a single executable load segment into two. + Before: + + LOAD 0x000000 0x00000000 0x00000000 0x2034d28 0x2034d28 + R E 0x1000 + LOAD 0x2035888 0x02036888 0x02036888 0x182d38 0x1a67d0 + RW 0x1000 + + After: + LOAD 0x000000 0x00000000 0x00000000 0x14648 0x14648 R + E 0x1000 + LOAD 0x014648 0x0020c648 0x0020c648 0x1e286e0 0x1e286e0 + R E 0x1000 + ... + LOAD 0x1e3d888 0x02036888 0x02036888 0x182d38 0x1a67d0 + RW 0x1000 + + The .text section is in the second LOAD, and this is not at + offset/address zero. The result is that this library shows up in + /proc/self/maps as multiple executable entries, for example (note: + this trace is not from the library dissected above, but rather from an + earlier version of it): + + 73b0c000-73b21000 r-xp 00000000 b3:19 786460 + /data/.../libchrome.2160.0.so + 73b21000-73d12000 ---p 00000000 00:00 0 + 73d12000-75a90000 r-xp 00014000 b3:19 786460 + /data/.../libchrome.2160.0.so + 75a90000-75c0d000 rw-p 01d91000 b3:19 786460 + /data/.../libchrome.2160.0.so + + When parsing this, pprof needs to merge the two r-xp entries above + into a single entry, otherwise the addresses it prints are incorrect. + + The following fix against 2.2.1 was sufficient to make pprof --text + print the correct output. Untested with other pprof options. + +M src/pprof + +commit 44c61ce6c4c713b194330641f400bbf64fd2abec +Author: Ricardo M. Correia +Date: Wed Oct 8 04:39:14 2014 +0200 + + Fix parsing /proc/pid/maps dump in CPU profile data file + + When trying to use pprof on my machine, the symbols of my program were + not being recognized. + + It turned out that pprof, when calculating the offset of the text list + of mapped objects (the last section of the CPU profile data file), was + assuming that the slot size was always 4 bytes, even on 64-bit + machines. + + This led to ParseLibraries() reading a lot of garbage data at the + beginning of the map, and consequently the regex was failing to + match on + the first line of the real (non-garbage) map. + +M src/pprof + +commit 2a28ef24ddf8013bff59914b10902f1fb07bf9b2 +Author: Aliaksey Kandratsenka +Date: Sat Sep 6 16:49:24 2014 -0700 + + Added remaining memory allocated info to 'Exiting' dump message + + This applies patch by user yurivict. + +M src/heap-profiler.cc + +commit bbf346a856d4a7c5c2ab0e65d7cccf3dc1f23f13 +Author: Adam McNeeney +Date: Fri Aug 22 10:01:24 2014 +0100 + + Cope with new addr2line outputs for DWARF4 + + Copes with ? for line number (converts to 0). + Copes with (discriminator ) suffixes to file/linenum (removes). + + Change-Id: I96207165e4852c71d3512157864f12d101cdf44a + +M src/pprof + +commit b08d760958dbacc8da822f7f3db76d58c95a114d +Author: Aliaksey Kandratsenka +Date: Sat Aug 23 14:45:08 2014 -0700 + + issue-641: Added --show_addresses option + + This applies patch by user yurivict. + +M src/pprof + +commit 3c326d9f200a527bba45f1d222aa6aff20d42bc3 +Author: Aliaksey Kandratsenka +Date: Tue Aug 19 08:14:08 2014 -0700 + + issue-644: fix possible out-of-bounds access in GetenvBeforeMain + + As suggested by user Ivan L. + +M src/base/sysinfo.cc + +commit f1ae3c446f34f6e8ac901caba281051ec269e4df +Author: jiakai +Date: Mon Jul 28 11:28:03 2014 -0700 + + Add an option to allow disabling stripping template argument in pprof + +M src/pprof + +commit a12890df2519d254d1c497b8e0a65bb8fc9e1ab2 +Author: Aliaksey Kandratsenka +Date: Sat Jul 26 14:12:42 2014 -0700 + + issue-635: allow whitespace in libraries paths + + This applies change suggested by user mich...@sebesbefut.com + +M src/pprof + +commit d5e36788d8bc626403dc020a86213cfc740ee73d +Author: Aliaksey Kandratsenka +Date: Sat Jul 26 13:59:22 2014 -0700 + + issue-636: fix prof/web command on Windows/MinGW + + This applies patch sent by user chaishushan. + +M src/pprof + +commit 4b788656bb9c480640d917d27d8a94a5eae436f5 +Author: Michael Pasieka +Date: Sun Jul 13 18:09:35 2014 -0700 + + added option to display stack traces in output for heap checker + + Quoting from email: + + I had the same question as William posted to stack overflow back on + Dec 9,2013: How to display symbols in stack trace of google-perftools + heap profiler (*). I dug into the source and realized the + functionality was not there but could be added. I am hoping that + someone else will find this useful/helpful. + + The patch I created will not attach so I am adding below. + + Enjoy! + + -- Michael + + * + http://stackoverflow.com/questions/20476918/how-to-display-symbols-in-stack-trace-of-google-perftools-heap-profiler + +M src/pprof + +commit 3abb5cb819bafe7004363f041c194afd827cb053 +Author: WenSheng He +Date: Mon Jun 30 14:39:13 2014 +0800 + + issue-630: The env var should be "CPUPROFILE" + + To enable cpu profile, the env var should be "CPUPROFILE", not + "PROFILE" + actually. + + Signed-off-by: Aliaksey Kandratsenka + +M src/gperftools/profiler.h + +commit fd81ec257883c6d5486e4568c955dff86dbed5c8 +Author: Aliaksey Kandratsenka +Date: Sat Jun 28 13:05:12 2014 -0700 + + issue-631: fixed miscompilation of debugallocation without mmap + + This applies patch sent by user iamxujian. + + Clearly, when I updated debugallocation to fix issue-464 I've broken + no-mmap path by forgetting closing brace. + +M src/debugallocation.cc + +commit 2e90b6fd72fec33aedf547d1977bdee6b77645b9 +Author: Aliaksey Kandratsenka +Date: Sat Jun 21 15:45:44 2014 -0700 + + bumped version to 2.2.1 + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 577b940cc0a0ef207115d071a81127f93f02c083 +Author: Aliaksey Kandratsenka +Date: Sat Jun 21 15:39:46 2014 -0700 + + updated NEWS for 2.2.1 + +M NEWS + +commit 2fe4b329ad4d3f242b0bd73295375e70be79187b +Author: Aliaksey Kandratsenka +Date: Sun May 18 10:59:06 2014 -0700 + + applied chromium patch fixing some build issue on android + + This applies patch from: https://codereview.chromium.org/284843002/ by + jungjik.lee@samsung.com + +M src/libc_override_gcc_and_weak.h + +commit c009398e3239be8ae6185ad83685caf7458c49bb +Author: Aliaksey Kandratsenka +Date: Sun Jun 15 12:53:14 2014 -0700 + + issue-628:package missing stacktrace_powerpc-{linux,darwin}-inl.h + + This headers were missing in .tar.gz because they were not mentioned + anywhere in Makefile.am. + +M Makefile.am + +commit 81d99f21ede78ab8d5fec15d0055416ac1b581f3 +Author: Adhemerval Zanella +Date: Tue Jun 3 07:50:56 2014 -0500 + + issue-626: Fix SetupAggressiveDecommit initialization + + This patch fixes the SetupAggressiveDecommit initialization to + run after + pageheap_ creation. Current code it not enforcing it, since + InitStaticVars is being called outside the static_vars module. + +M src/static_vars.cc + +commit 846b775dfadb77901202ae7ddbac30ad1de7df01 +Author: Aliaksey Kandratsenka +Date: Sat May 3 17:50:11 2014 -0700 + + bumped version to 2.2 + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit cdf8e1e932016bd5f1737e1f10bce07226228d15 +Author: Aliaksey Kandratsenka +Date: Sat May 3 17:44:38 2014 -0700 + + updated NEWS for 2.2 + +M NEWS + +commit 0807476f56b9dc024375467be0f0b07fae3ee7fb +Author: Aliaksey Kandratsenka +Date: Sat May 3 17:38:14 2014 -0700 + + issue-620: windows dll patching: fixed delete of old stub code + + After code for issue 359 was applied PreamblePatcher started using + it's own code to manage memory of stub code fragments. It's not using + new[] anymore. And it automatically frees stub code memory on + Unpatch. + + Clearly, author of that code forgot to remote that no more needed + delete call. With that delete call we end up trying to free memory + that was never allocated with any of known allocators and crash. + +M src/windows/patch_functions.cc + +commit facd7e83b341e069875b7c1cd7774cf671d932b5 +Author: Aliaksey Kandratsenka +Date: Sat Apr 19 11:08:51 2014 -0700 + + bumped version to 2.1.90 + +M configure.ac +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit e8e082af25952e9bd10c37c3f028c91fcbbd1cbd +Author: Aliaksey Kandratsenka +Date: Sat Apr 19 13:16:02 2014 -0700 + + updated NEWS for 2.2rc + +M NEWS + +commit 802fdb739e7aabcb15443030842a2137a5559338 +Author: Aliaksey Kandratsenka +Date: Sat Apr 12 18:07:11 2014 -0700 + + issue-610: use TCMallocGetenvSafe from inside malloc + + Instead of plain getenv. So that windows getenv implementation that + may call malloc does not deadlock. + +M src/common.cc +M src/thread_cache.cc + +commit 6b83516adefcf0806825f6dba2eb2232615d744b +Author: Aliaksey Kandratsenka +Date: Sat Apr 12 18:06:32 2014 -0700 + + issue-610: made dynamic_annotations.c use TCMallocGetenvSafe + +M src/base/dynamic_annotations.c + +commit aeef3b44201ba663c19ca1c97792b724346e84a9 +Author: Aliaksey Kandratsenka +Date: Sat Apr 12 18:05:59 2014 -0700 + + issue-610: introduced TCMallocGetenvSafe + + This is version of GetenvBeforeMain that's available to C code. + +M Makefile.am +M src/base/sysinfo.cc +A src/getenv_safe.h + +commit 125e5ed58b72550e6b74e0139c2c3dd5e262a6ec +Author: Aliaksey Kandratsenka +Date: Sat Apr 12 12:38:19 2014 -0700 + + don't enable backtrace() for stacktrace capturing by default + + Because we don't yet have a treatment for deadlocks that are caused by + (recursive) use of malloc from within that facility. + +M configure.ac + +commit 75b65f96b0bb44d70e0a461a03a3f8c928390283 +Author: Raphael Moreira Zinsly +Date: Tue Apr 8 17:45:13 2014 -0300 + + PowerPC: stacktrace function refactor and fixes + + This patch fixes the stacktrace creating when the function is + interrupted by a signal. For Linux, the vDSO signal trampoline + symbol is + compared against LR from stack backchain and handled different in that + case (since the signal trampoline layout a different stack frame). + + Because of this extensive change the PowerPC stacktrace code has now + been refactored to split in Linux and Darwin specific codes. + +M src/stacktrace.cc +A src/stacktrace_powerpc-darwin-inl.h +A src/stacktrace_powerpc-linux-inl.h + +commit 8deea9ff2a3e6eef8af64ea0727d6cb840c13769 +Author: Raphael Moreira Zinsly +Date: Tue Apr 8 17:44:08 2014 -0300 + + VDSOsupport cleanup + + This patch cleans up unused VDSO getcpu racking from VDSOsupport + class, + since the code is not used anywhere in gperftools and symbol name + is not + architecture independent. + +M src/base/vdso_support.cc +M src/base/vdso_support.h + +commit 9d5e1a0aa5a6ad1c7af18b65016fa5c9b7fccb47 +Author: Raphael Moreira Zinsly +Date: Tue Apr 8 17:43:11 2014 -0300 + + Fixed issues with heap checker on PPC64 LE. + + Fixed the wrapper for the syscall sys_clone and the test for heap + checker on PPC64 LE. Both use the ODP structure, which is only + used on BE architectures. + +M src/base/linux_syscall_support.h +M src/tests/heap-checker_unittest.cc + +commit 49237462c8ae7920332c1034c623e57b50a6109c +Author: Raphael Moreira Zinsly +Date: Tue Apr 8 17:42:17 2014 -0300 + + Fixed the way that pprof packed profile data in BE. + + pprof was writing profile data in a way that only works for + little-endian + files, this patch verifies if the system is big-endian and writes + packed + data correctly. + +M src/pprof + +commit a1ae66ef110bd87ff97903e86fd84c745db24646 +Author: Raphael Moreira Zinsly +Date: Tue Apr 8 17:37:29 2014 -0300 + + Fixed the use of addr2line to discover the separator symbol. + + In systems where addr2line has a version greater than 2.22 pprof fails + in discover the separator symbol (_fini). This patch identifies if + addr2line can find the symbol, otherwise pprof uses objdump to recover + a address that addr2line's newer versions can recognize as the + separator + function. + +M src/pprof + +commit 8b2e5ee831760a94bc407dc255a522eda242b04f +Author: Aliaksey Kandratsenka +Date: Tue Apr 1 22:29:11 2014 -0700 + + issue-614: use tc_memalign in ReallocAfterMemalloc test + + Because some OSes lack plain memalign. And we really need to test our + implementation which is always available via tc_malloc. + +M configure.ac +M src/tests/debugallocation_test.cc + +commit 0399af1019240e2d9127a588ddc8e31ff4656df0 +Author: Aliaksey Kandratsenka +Date: Tue Apr 1 21:30:27 2014 -0700 + + added tc_malloc_skip_new_handler + + This is port of corresponding chromium change at: + https://codereview.chromium.org/55333002/ + + Basic idea is that sometimes apps that use tc_set_new_mode in order to + have C++ out-of-memory handler catch OOMs in malloc, need to invoke + usual malloc that returns 0 on OOM. + + That new API is exactly for that. It'll always return NULL on OOM even + if tc_new_mode is set to true. + +M src/debugallocation.cc +M src/gperftools/tcmalloc.h.in +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in + +commit d77317247e1c8de1ea4e0419318b26f636e64431 +Author: Aliaksey Kandratsenka +Date: Sat Mar 1 12:13:02 2014 -0800 + + issue deprecation warning on use of google/ headers + +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/google/tcmalloc.h + +commit e7297f0c14b0c09ec52707ed7477c7aee43a1882 +Author: Aliaksey Kandratsenka +Date: Sat Mar 15 12:44:11 2014 -0700 + + speed up MallocExtension::instance() + + It was reported that pthread_once is expensive, especially on ppc. + + In new implementation in hot path instead of doing potentially + expensive atomic read with barrier, we do just plain read. + + It's slightly less robust than older implementation, but it should be + faster. + + New code is making assumption that programs do not spawn threads + before main() is called. And therefore all variables & modules are + initialized before threads are created. Which looks like pretty safe + assumption. With that assumption, doing plain read is safe, because + current_instance is initialized as part of module init and therefore + before threads are spawned. + + This patch is based on feedback of Adhemerval Zanella. + +M src/malloc_extension.cc + +commit df227794361f9725eca7420d95e65ab997c79716 +Author: Adhemerval Zanella +Date: Sun Feb 2 19:32:37 2014 -0200 + + Fix getpc_test for PPC64v2 LE + + This patch fix the PPC64 guard to get the function address for + PPC64v2. + It removes the use of an indirection (to get the ODP text address), + since the PPCv2 does not have function descriptors. + +M src/tests/getpc_test.cc + +commit e3deb42d5dcdeeb8a340d03f207f2488ef3fb2eb +Author: Aliaksey Kandratsenka +Date: Sat Mar 29 13:28:01 2014 -0700 + + issue-613: remove friend declaration from HeapLeakChecker + + This applies patch by davide.italiano@10gen.com: + + heap-checker.h contains the following friend declaration of main: + friend int main(int, char**). + + C99 allows another declaration of main, i.e. int main(int, char**, + char**), and if code uses it and includes the heap-checker header, + this might result in a conflict, e.g. + + error: declaration of C function 'int main(int, char**, char**)' + conflicts with + int main(int argc, char* argv[], char** envp) + + Actually the comment above the friend declaration of main() mentions + that this is required to get the unittest working and for other + internal usage, but I'm not completely sure if this is true as long as + I'm able to build and run the unittest removing the declaration. + +M src/gperftools/heap-checker.h + +commit 1a28754656bd6dfc1297d62a4c5811b0a5f03180 +Author: Aliaksey Kandratsenka +Date: Sat Mar 29 13:23:00 2014 -0700 + + issue-612: added missing include for std::min + + Otherwise Visual Studio 2013 rightfully complains + +M src/windows/system-alloc.cc + +commit fe566314267fc3f67c5068d0afe004b1733ff19a +Author: Aliaksey Kandratsenka +Date: Sat Mar 1 12:38:08 2014 -0800 + + unbreak building with libunwind + + Caused by premature merging of previous patch. + + When we're searching for backtrace in libexecinfo and don't find it, + we should not reset UNWIND_LIBS to empty value. + + Correct fix is to first search for backtrace in libunwind and then to + search for it in libexecinfo. + +M configure.ac + +commit 91179961490a601f2c611889b3075e995fa5437e +Author: Thomas Klausner +Date: Tue Feb 25 21:41:28 2014 +0100 + + Look for backtrace() in libexecinfo as well. + + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac + +commit fd3379a213b2a99a72a7544b6208056daf15d0d2 +Author: Thomas Klausner +Date: Tue Feb 25 21:41:07 2014 +0100 + + Fix unportable test(1) construct. + + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac + +commit a7223c2a14431ffd783117c55f84a2c84423d313 +Author: Thomas Klausner +Date: Tue Feb 25 21:40:11 2014 +0100 + + Test for memalign in configure.ac. Disable a test that uses memalign + if it is not found. + + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac +M src/tests/debugallocation_test.cc + +commit bd9665ebbe1aca5e1ba993de4214e64ee8bbe43a +Author: Aliaksey Kandratsenka +Date: Sat Feb 22 13:46:42 2014 -0800 + + issue-489: added tcmalloc test pass with chromium-style decommit + +M src/tests/tcmalloc_unittest.sh + +commit 6a000d6dd5968ac29f8fc43f7dfc736338e11781 +Author: Aliaksey Kandratsenka +Date: Sat Feb 22 13:46:11 2014 -0800 + + issue-489: added unit test for chromium-style decommitting + +M src/tests/tcmalloc_unittest.cc + +commit eb2d69014cb3e163f2ab3ed676fbedf5c3a97caa +Author: Aliaksey Kandratsenka +Date: Sat Feb 22 13:10:08 2014 -0800 + + issue-489: made tests pass on enabled chromium-style decommitting + +M src/tests/tcmalloc_unittest.cc + +commit a92fc76f72318f7a46e91d9ef6dd24f2bcf44802 +Author: Aliaksey Kandratsenka +Date: Sat Feb 22 13:09:05 2014 -0800 + + issue-489: enable chromium-style decommitting on env variable + + TCMALLOC_AGGRESSIVE_DECOMMIT=t now enables aggressive decommitting by + default. + +M src/static_vars.cc + +commit c7ce50cd04ea08bd20d4ea4b2924e6a4451d2565 +Author: Aliaksey Kandratsenka +Date: Sat Nov 9 17:35:24 2013 -0800 + + issue-489: implemented API to set chromium-style de-committing + + Chrome has code to decommit (release back to OS) every span that's + released. I don't want to make it default, but indeed some + applications may want to enable this mode. + + The code itself is taken from 2-way-merging of code from Chromium + fork. + +M src/page_heap.cc +M src/page_heap.h +M src/tcmalloc.cc + +commit 1d707cd4a3dfe6f238a530f945291acfd5995042 +Author: Aliaksey Kandratsenka +Date: Sat Nov 9 17:19:34 2013 -0800 + + issue-489: fixed warning + + Computing certain values just for ASSERT raises just warning from + compiler because if NDEBUG is set those are dead code. + +M src/page_heap.cc + +commit 91bffcbad60d84beebe8b69a1db6c85c10fc04bf +Author: Aliaksey Kandratsenka +Date: Sat Nov 9 16:22:35 2013 -0800 + + issue-489: ported chromium windows decommitting code + + I tried to do it cleanly with merges but chromium code has so many + relevant commits (with frequent reverts) that makes it near + impossible. + + Simpler 2-way emerge-files worked in the end. I've removed chromium's + aggressive 'always decommit' behavior which I want to make optional + later. + + Majority of this work is the following commits (but there are more, + particularly against port.cc): + + commit 9c92338c5f8770c440799d24387c3733fd6d826b + Author: jamesr@chromium.org + + Date: Tue Oct 6 18:33:31 2009 +0000 + + Tracks the amount of committed vs uncommitted memory in tcmalloc's + page heap's freelists + + Keeps track of the number of reserved but not committed pages in + the freelist and uses that to calculate a waste metric, which is + the ratio of committed pages vs pages used by the application. + This is exposed in the GetStats() call (which is used for + about:tcmalloc) and through GetNumericalProperty() in Malloc + + BUG=none + TEST=open about:tcmalloc and monitor 'WASTE' columns while using + the browser + + Review URL: http://codereview.chromium.org/251065 + + git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28133 + 0039d316-1c4b-4281-b951-d872f2087c98 + + commit aef4f1be3eec2059a7c6e2c106050a5f3d6ccf12 + Author: jar@chromium.org + + Date: Mon Oct 5 17:58:51 2009 +0000 + + Revert further back to MBelshe's baseline forking TCMalloc + + This changes to decommitting in all paths through the + page_heap delete method (which adds spans to the free lists). + + r=mbelshe,jamesr + Review URL: http://codereview.chromium.org/255067 + + git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28006 + 0039d316-1c4b-4281-b951-d872f2087c98 + + commit e94afbb913b95f512cb8745a2729c73f82b15ae7 + Author: jar@chromium.org + + Date: Thu Oct 1 00:25:41 2009 +0000 + + Rollback Scavenge implemetation and rely on existing functionality + to free + + This is a landing of a patch provided by antonm. See: + http://codereview.chromium.org/235022 + + Also included change to browser_about_handler.cc to fix build, + and I set + TCMALLOC_RELEASE_RATE to 1.0 on line 40 of page_heap.cc (I + think this + was an inadvertent rollback element). + + r=antonm + Review URL: http://codereview.chromium.org/257009 + + git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27692 + 0039d316-1c4b-4281-b951-d872f2087c98 + + commit c585892d2c42a47c95d06a684a6685156c545403 + Author: mbelshe@google.com + + Date: Wed Sep 2 17:33:23 2009 +0000 + + Landing for Anton Muhin's tcmalloc patch: + http://codereview.chromium.org/180021/show + + Restore decommitting in IncrementalScavenge and draft Scavenge + method to + be invoked periodically + to reduce amount of committed pages. + + BUG=none + TEST=none + + Review URL: http://codereview.chromium.org/187008 + + git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25188 + 0039d316-1c4b-4281-b951-d872f2087c98 + + commit 14239acc00731e94736ac62e80fc6b17c31ea131 + Author: mbelshe@google.com + + Date: Wed Aug 12 02:17:14 2009 +0000 + + Major changes to the Chrome allocator. + + Changes include: + * Fix tcmalloc to release memory. Implements the + TCMalloc_SystemCommit() + mechanism so that tcmalloc can implement SystemRelease() + and later + reuse that memory. + * Enable dynamic switching of allocators based on an environment + variable. + Users can now switch between tcmalloc, jemalloc, the default + windows + heap, and the windows low-fragmentation heap. + * Implements set_new_mode() across all allocators so that we + can be sure + that out-of-memory conditions are handled safely. + + BUG=18345 + TEST=none; plan to get all unit tests running through these + allocators. + + Review URL: http://codereview.chromium.org/165275 + + git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23140 + 0039d316-1c4b-4281-b951-d872f2087c98 + +M src/page_heap.cc +M src/page_heap.h +M src/system-alloc.cc +M src/system-alloc.h +M src/windows/system-alloc.cc + +commit 7be2edfe7f09e7e8c123e958742815784a718880 +Author: Aliaksey Kandratsenka +Date: Sat Feb 22 12:14:11 2014 -0800 + + issue-525: only warn if --enable-frame-pointers are not given + + This fixes issue when frame pointers warning is given even if frame + pointers are enabled + +M configure.ac + +commit 7e24b6ca2aa2c15a24504c02fad09f47e1ece8b5 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 17:04:26 2014 -0800 + + added debugallocation check for offset_ corruption + + It was previously possible (although unlikely) for damaged offset_ + field + to lead FromRawPointer implementation into different MallocBlock. + + As is usual with any damage, it's best to catch errors at earliest + possible time. + +M src/debugallocation.cc + +commit 6dcd73f1eb5ce2cc44ab918c53cd42c472f44c52 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 16:59:43 2014 -0800 + + avoid crash in DebugMallocImplementation::GetOwnership + + It was possible that if GetOwnership is passed pointer to memory not + owned by tcmalloc, it would crash. Or incorrectly return + owned. I.e. due to indirection in FromRawPointer. + + New implementation prevents that, but introduces different bug + instead. New implementation incorrectly returns "not owned" for + memalign chunks with big alignment. But in can be argued that passing + pointer returned from different memalign implementation did not work + previously too. + +M src/debugallocation.cc + +commit 33280ffb71fc0e4eb75e455d53824c344d011e35 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 16:25:14 2014 -0800 + + removed unused "using" in malloc_extension_test.cc + +M src/tests/malloc_extension_test.cc + +commit 066e524d6e33e9e3364bb6819f98a02b347c14ef +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 14:58:35 2014 -0800 + + eliminated useless BASE_XXX defines in debugallocation.cc + + And closed TODO entry for that. + +M src/debugallocation.cc + +commit a2375a1f360c0451ec2a2b852ea26a71fb731727 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 14:49:57 2014 -0800 + + issue-464: correctly handle realloc after memalign in debugalloc + + debug memalign is creating special header block to allow us to find + real allocated block. And previous implementation of data copying + wasn't taking that into account and was copying that "alignment + header" into newly allocated block. + +M src/debugallocation.cc +M src/tests/debugallocation_test.cc + +commit d31f522f0e1b0e87ee3d5941e331ba745a0f5c23 +Author: Riku Voipio +Date: Mon Feb 3 16:31:32 2014 +0200 + + Add aarch64 defines + + With atomic operations and system call support in place, enable + with __aarch64__ defines Aarch64 support in other files around + the google-perftools header files. After these, google-perftools + testsuite (make check) results: + + 8 of 46 tests failed. + + FAIL: sampling_test.sh + FAIL: heap-profiler_unittest.sh + FAIL: heap-checker_unittest.sh + FAIL: heap-checker-death_unittest.sh + FAIL: sampling_debug_test.sh + FAIL: heap-profiler_debug_unittest.sh + FAIL: heap-checker_debug_unittest.sh + FAIL: profiler_unittest.sh + + While it indicates that there is still work to do, This is still + better than the result I get on ARMv7: + + 12 of 46 tests failed. + +M src/base/basictypes.h +M src/base/cycleclock.h +M src/base/linuxthreads.h +M src/malloc_hook_mmap_linux.h + +commit 15b5e7a35c83ce5d38fa523f2c291a2ac30bb8ed +Author: Riku Voipio +Date: Tue Feb 4 11:09:47 2014 +0200 + + linux_syscall_support.h: add aarch64 support + + Aarch64 support for linux_syscall_support.h. Since Aarch64 is a brand + new architecture, none of the legacy system calls are neccesarily + available. Thus some changes were neccesary affect other architectures + as well: + + 1) use getdents64 where available and else getdents (for ppc64) + + 2) other legacy system calls, pipe, waitpid and open replaced + by pipe2, + wait4 and openat where available. + + 3) use fstatat if stat is not available. + + The aarch64 system call interface follows the Aarch64 calling + convention + (regs x0-x5 for arguments and x8 system call number - return in x0). + Clone implementation is adapted from glibc. + + v2: step back in getdents removal due to ppc64 + +M src/base/linux_syscall_support.h +M src/base/linuxthreads.cc + +commit b5e584dfdc22328f713488311707f502aa77ff5f +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 19:41:37 2014 -0800 + + issue-525: warn user on lack of libunwind but don't fail + + Because we now have access to other backtrace capturing method(s) at + runtime. + +M configure.ac + +commit 90ba15d1f2f6704af96f62ce1e8c5f214697bab1 +Author: Aliaksey Kandratsenka +Date: Sat Feb 8 15:30:36 2014 -0800 + + issue-604: implement runtime-selectable stacktrace capturing + + We're now building all supported stacktrace capturing methods. And + there's now a way to select at runtime which method is used. + +M Makefile.am +M configure.ac +M src/stacktrace.cc +M src/stacktrace_arm-inl.h +D src/stacktrace_config.h +M src/stacktrace_generic-inl.h +C055 src/stacktrace.cc src/stacktrace_impl_setup-inl.h +M src/stacktrace_instrument-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +M src/stacktrace_win32-inl.h +M src/stacktrace_x86-inl.h + +commit 33f6781d64af88ea23698a084188d8c2ab94ecb1 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 18:47:04 2014 -0800 + + issue-605: avoid compilation errors if pthread_key_t is pointer + + Which seems to be the case on later cygwin + +M src/maybe_threads.cc + +commit 100f310088aa30d347cd5d07bbe9d9f80cf2c2d0 +Author: Aliaksey Kandratsenka +Date: Sun Feb 16 18:27:14 2014 -0800 + + unbreak make dist + +M Makefile.am + +commit a0ed9ace534372fbeee9bfefd6e26b922f0a1835 +Author: Wang YanQing +Date: Tue Feb 11 23:20:31 2014 +0800 + + debugallocation: fix bus error on mipsel-linux platform when enable + use_malloc_page_fence + + Fix below "BUS ERROR" issue: + + a0 hold start address of memory block allocated by DebugAllocate + in debugallocation.cc + + gdb) info registers + zero at v0 v1 a0 a1 + a2 a3 + R0 00000000 10008700 772f62a0 00084d40 766dcfef 7fb5f420 00000000 + 004b4dd8 + t0 t1 t2 t3 t4 t5 + t6 t7 + R8 7713c1a0 7712dbc0 ffffffff 777bc000 f0000000 00000001 00000000 + 00403d10 + s0 s1 s2 s3 s4 s5 + s6 s7 + R16 7fb5ff1c 00401b9c 77050020 7fb5fb18 00000000 004cb008 004ca748 + ffffffff + t8 t9 k0 k1 gp sp + s8 ra + R24 0000002f 771adcd4 00000000 00000000 771f4140 7fb5f408 7fb5f430 + 771add6c + sr lo hi bad cause pc + 00008713 0000e9fe 00000334 766dcff7 00800010 771adcfc + fsr fir + 00000004 00000000 + + (gdb) disassemble + Dump of assembler code for function _ZNSs4_Rep10_M_disposeERKSaIcE: + 0x771adcd4 <+0>: lui gp,0x4 + 0x771adcd8 <+4>: addiu gp,gp,25708 + 0x771adcdc <+8>: addu gp,gp,t9 + 0x771adce0 <+12>: lw v0,-28696(gp) + 0x771adce4 <+16>: beq a0,v0,0x771add38 + <_ZNSs4_Rep10_M_disposeERKSaIcE+100> + 0x771adce8 <+20>: nop + 0x771adcec <+24>: lw v0,-30356(gp) + 0x771adcf0 <+28>: beqzl v0,0x771add1c + <_ZNSs4_Rep10_M_disposeERKSaIcE+72> + 0x771adcf4 <+32>: lw v0,8(a0) + 0x771adcf8 <+36>: sync + => 0x771adcfc <+40>: ll v0,8(a0) + 0x771add00 <+44>: addiu at,v0,-1 + 0x771add04 <+48>: sc at,8(a0) + 0x771add08 <+52>: beqz at,0x771adcfc + <_ZNSs4_Rep10_M_disposeERKSaIcE+40> + 0x771add0c <+56>: nop + 0x771add10 <+60>: sync + 0x771add14 <+64>: b 0x771add24 + <_ZNSs4_Rep10_M_disposeERKSaIcE+80> + 0x771add18 <+68>: nop + 0x771add1c <+72>: addiu v1,v0,-1 + 0x771add20 <+76>: sw v1,8(a0) + 0x771add24 <+80>: bgtz v0,0x771add38 + <_ZNSs4_Rep10_M_disposeERKSaIcE+100> + 0x771add28 <+84>: nop + 0x771add2c <+88>: lw t9,-27072(gp) + 0x771add30 <+92>: jr t9 + 0x771add34 <+96>: nop + 0x771add38 <+100>: jr ra + 0x771add3c <+104>: nop + End of assembler dump. + + ll instruction manual: + Load Linked: + Loads the destination register with the contents of the word + that is at the memory location. This instruction implicity performs + a SYNC operation; all loads and stores to shared memory fetched prior + to the ll must access memory before the ll, and loads and stores to + shared memory fetched subsequent to the ll must access memory + after ll. + Load Linked and Store Conditional can be use to automatically update + memory locations. *This instruction is not valid in the mips1 + architectures. + The machine signals an address exception when the effective address + is not + divisible by four. + + Signed-off-by: Wang YanQing + Signed-off-by: Aliaksey Kandratsenka + [alk@tut.by: removed addition of unused #include] + +M src/debugallocation.cc + +commit 38bfc7a1c2f9ba718bcaa9b82fdcd9c429c8f85f +Author: Aliaksey Kandratsenka +Date: Sat Feb 8 14:10:11 2014 -0800 + + removed irrelevant comment + +M src/base/atomicops.h + +commit d03c467a3446088b229f0106d9f47fab6d7c52a4 +Author: Aliaksey Kandratsenka +Date: Sat Feb 8 13:35:16 2014 -0800 + + allow asking for gcc atomics on all platforms + + I.e. by doing ./configure CPPFLAGS=-DTCMALLOC_PREFER_GCC_ATOMICS + +M src/base/atomicops.h + +commit 6de1f38b687e3974d67adad45217f35a2c376049 +Author: Aliaksey Kandratsenka +Date: Sat Feb 8 13:43:04 2014 -0800 + + chmod -x configure.ac + + Because configure.ac is not really executable. And because it + interferes with tab completion of configure. + +M configure.ac + +commit e8fe990fa06e337a07059c55adc6ed2a0888de95 +Author: Riku Voipio +Date: Wed Jan 29 10:54:29 2014 +0200 + + implement atomics with gcc intrinsics + + Gcc after 4.7 provides atomic builtins[1]. Use these instead of adding + yet-another-assembly port for Aarch64 (64-bit ARM). This patch enables + succesfully building and running atomicops unittest on Aarch64. + + This patch enables using gcc builtins only when no assembly + implementation is provided. But as a quick check, atomicops_unittest + and rest of testsuite passes with atomicops-internals-gcc also + ARMv7 and X86_64 if the ifdef in atomicops is adjusted to prefer + the generic implementation. + + [1] http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html + +A src/base/atomicops-internals-gcc.h +M src/base/atomicops.h + +commit fa4b1c401da1ac381d4d72172825231b3d5518d9 +Author: Aliaksey Kandratsenka +Date: Sun Jan 19 22:37:44 2014 -0800 + + issue-599: fixing FreeBSD issue with sbrk + + Applied patch by yurivict. + + It was wrong assembly specifically for FreeBSD in sbrk overriding + code. + +M src/malloc_hook_mmap_freebsd.h + +commit 71a239e559c9ea2300ad0511f8de7077db5369c3 +Author: Aliaksey Kandratsenka +Date: Sun Jan 19 12:30:53 2014 -0800 + + check debug_malloc_implementation_space via COMPILE_ASSERT + + Because we can and because compile-time is always better. + +M src/debugallocation.cc + +commit 54568e32fc2321e0adef15fb1eab4e3a7f8ce5b0 +Author: Aliaksey Kandratsenka +Date: Sat Sep 21 18:14:00 2013 -0700 + + issue-565: don't pollute global namespace with thread lister API + + Instead those functions that are original taken from google's "base" + code now have prefix TCMalloc_. So that they don't conflict with other + google's libraries having same functions. + +M src/base/linuxthreads.cc +M src/base/thread_lister.c +M src/base/thread_lister.h +M src/gperftools/heap-checker.h +M src/heap-checker.cc +M src/memory_region_map.h + +commit 64bc1baa1f4723d73ba40cd730b72896bd45a810 +Author: Aliaksey Kandratsenka +Date: Sat May 18 17:11:58 2013 -0700 + + issue-{66,547}: use signal's ucontext when unwinding backtrace + + In issue-66 (and readme) it is pointed out that sometimes there are + some issues grabbing backtrace across signal handler boundary. + + This code attempts to fix it by grabbing backtrace from signal's + ucontext which clearly does not include signal handler boundary. + + We're using "feature" of libunwind that for some important platforms + libunwind's context is same as libc's ucontext_t which is given to us + as part of calling signal handler. + +M src/stacktrace_libunwind-inl.h + +commit 185bf3fcc36f8cb3839abdfe652f615bfb5306d1 +Author: Aliaksey Kandratsenka +Date: Sat Jan 11 12:46:02 2014 -0800 + + issue-581: avoid destructing DebugMallocImplementation + + Because otherwise destructor might be invoked well before other places + that might touch malloc extension instance. + + We're using placement new to initialize it and pass pointer to + MallocExtension::Register. Which ensures that destructor for it is + never run. + + Based on idea suggested by Andrew C. Morrow. + +M src/debugallocation.cc + +commit 48a0d131c1aa088c6075e9c4676ee430f81d8600 +Author: Aliaksey Kandratsenka +Date: Sat Jan 18 13:27:41 2014 -0800 + + issue-548: pass -fno-builtin to compiler for unittests + + Because clang doesn't understand -fno-builtin-malloc and friends. And + otherwise new/delete pairs get optimized away causing our tests that + expect hooks to be called to fail. + +M Makefile.am + +commit e98371540d63dde53ce4b7c772d78c1da6b59ea8 +Author: Aliaksey Kandratsenka +Date: Sat Jan 11 16:28:15 2014 -0800 + + eliminated gcc warning on __thread configure snippet + + gcc complained about lack of matching ' in code that force-fails + __thread detection on mingw + +M configure.ac + +commit 60b12171bc73117c0108b847bb310af095cd2778 +Author: xiaoyur347 +Date: Sat Jan 11 11:39:53 2014 +0800 + + fix GCC version detect for platforms other than X86/X64 + + [alk@tut.by: commented why we're disabling __thread not just for x86] + + Signed-off-by: Aliaksey Kandratsenka + +M configure.ac + +commit 764d304222f0c3057ab99babd06246016cbfa505 +Author: Aliaksey Kandratsenka +Date: Sun Jan 5 12:49:23 2014 -0800 + + don't re-define strtoq for VS2013 + + Which is part of previous change that wasn't correctly applied. + +M src/windows/port.h + +commit 1fc768864d506466b45f3f38474912bcb69bb772 +Author: Aliaksey Kandratsenka +Date: Sat Jan 4 18:28:36 2014 -0800 + + fix compilation under VS 2013 + + This is essentially a copy of corresponding chromium change from: + https://codereview.chromium.org/27017003 + +M src/windows/port.cc +M src/windows/port.h + +commit 4c274b9e20132230e62117ff583ebadd83081d90 +Author: Aliaksey Kandratsenka +Date: Sat Jan 4 18:28:36 2014 -0800 + + issue-592: handle recent mingw with C++11 threads + + Somehow it's c++ headers (like string) define pthread symbols without + even us asking for. That breaks old assumption that pthread symbols + are not available on windows. + + In order to fix that we detect this condition in configure.ac and + avoid defining windows versions of pthread symbols. + +M Makefile.am +M configure.ac +M src/windows/mingw.h +M src/windows/port.h + +commit 1458ee2239e0791567e69112931dc17eb0456cf8 +Author: Aliaksey Kandratsenka +Date: Sat Jan 4 13:54:24 2014 -0800 + + issue-596: removed unused AtomicIncrement operation + + There's no need for us to attempt to maintain Google's atomic ops code + in era of C++11. + +M src/base/atomicops-internals-arm-generic.h +M src/base/atomicops-internals-arm-v6plus.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-mips.h +M src/base/atomicops-internals-windows.h +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/tests/atomicops_unittest.cc + +commit 6630b24e27c6a62727fe73aaae21dcc7364b8fee +Author: Aliaksey Kandratsenka +Date: Sat Jan 4 13:07:35 2014 -0800 + + Removed unused AtomicPtr::CompareAndSwap + +M src/malloc_hook-inl.h +M src/malloc_hook.cc + +commit a15115271cc475509b17bf7fecbe1ac4966baf2e +Author: xiaoyur347 +Date: Fri Dec 20 09:41:08 2013 +0800 + + add "-finstrument-functions" support for MIPS uclibc. + should configure with CXXFLAGS="-finstrument-functions" + +M src/stacktrace_config.h +A src/stacktrace_instrument-inl.h + +commit 7c4888515ed93347d4793fc066cd6048e519a197 +Author: xiaoyur347 +Date: Fri Dec 20 09:02:49 2013 +0800 + + add uclibc support + * some variables defined with "char *" should be modified to + "const char*" + * For uclibc, glibc's "void malloc_stats(void)" should be "void + malloc_stats(FILE *)", is commented now. + * For uclibc, __sbrk is with attribute "hidden", so we use mmap + allocator for uclibc. + +M Makefile.am +M src/heap-checker.cc +M src/heap-profiler.cc +M src/libc_override_gcc_and_weak.h +M src/malloc_hook_mmap_linux.h +M src/memory_region_map.cc +M src/symbolize.cc +M src/system-alloc.cc + +commit 7bd193bca97d93b43ff6c824bc9f39227329312f +Author: Aliaksey Kandratsenka +Date: Sat Dec 14 12:03:02 2013 -0800 + + issue-586: detect main executable even if PIE is active + + Previous logic of detecting main program addresses is to assume that + main executable is at least addressess. With PIE (active by default on + Ubuntus) it doesn't work. + + In order to deal with that, we're attempting to find main executable + mapping in /proc/[pid]/maps. And old logic is preserved too just in + case. + +M src/pprof + +commit f8a2163b5131050765ea877e2573f4930e41f630 +Author: Aliaksey Kandratsenka +Date: Fri Dec 6 12:23:48 2013 -0800 + + Added AM_MAINTAINER_MODE to disable Makefile rebuild rules + + Some people might want to check-in unpacked result on make dist into + git. But because git doesn't preserve timestamps it would cause those + automatic "auto-retool" rules to trigger. Sometimes even causing build + breakage if system's autotools version don't match autotools version + used for make dist. + + Easiest way around this problem is to simply disable those unnecessary + "maintainer" rebuild rules. Especially given that source is always + freely available via git and therefore there should be no reason to + regenerate any of autotools products in 'make dist'-produced sources. + +M configure.ac + +commit 925bbaea76b91bd307634908cfd6902f99804544 +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 14:01:38 2013 -0800 + + actually check result of CheckAddressBits + + Previously call to CheckAddressBits was made but nothing was done to + it's result. + + I've also make sure that actual size is used in checks and in bumping + up of TCMalloc_SystemTaken. + +M src/system-alloc.cc + +commit f216317a879e972ceafe77e61b2d66fd5f29922e +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 15:05:45 2013 -0800 + + use AC_PROG_LIBTOOL to summon libtool + + So that older autotools of rhel 5 can be used + +M configure.ac + +commit d4f4c5a3104e30b14b1090241fb4d0fac6a0e357 +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 14:00:19 2013 -0800 + + assert that ClassSize(0) is 0 instead >=0 + + Because it's return value being size_t cannot be negative + anyways. This fixes clang warning + +M src/common.cc + +commit 946203d60e50488a0b9e0fe003c13662873fa17d +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 13:35:59 2013 -0800 + + assert key size in way that is clearer to gcc + + Both new and old asserts are checking same condition, however new + assert helps gcc see that out of bounds access is not possible in + root_ array. + +M src/pagemap.h + +commit bf2d7bd3f8c1fb6a0843e55e652e37f4ce0fae3d +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 13:31:34 2013 -0800 + + fixed gcc warning + + We've recently changed old_signal_handler to by integer, so comparing + it with NULL is not good idea. + +M src/heap-profiler.cc + +commit dd5f979c5e6e7e3127835a659a5af89ac21597d5 +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 13:31:08 2013 -0800 + + fixed -Wreorder warning in HeapProfileTable constructor + +M src/heap-profile-table.cc + +commit e4ea98f147a7602979f70be022de068b04e68060 +Author: Aliaksey Kandratsenka +Date: Sat Nov 9 14:19:16 2013 -0800 + + issue-585: fixed use of TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES + + In order to apply that, we're now doing explicit EnvToInt64 call as + part of initializing thread cache module. + +M src/thread_cache.cc + +commit e0102230ec7e8304155798bf7f03d6abcd5991ee +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 12:03:35 2013 -0800 + + issue-588: Fix profiler_unittest.cc fork() + + As suggested by Hannes Weisbach. + + Call heap-profiler_unittest with the arguments 1 -2 (one iteration, 2 + fork()ed children). + + Instead of running the test, the program crashes with a std::bad_alloc + exception. This is caused by unconditionally passing the + number-of-threads-argument (0 or positive for threads, negative for + fork()s) in RunManyThreads(), thus allocating an array of pthread_t of + size -2. Depending on the sign of the thread number argument either + RunManyThreads or fork() should be called. + +M src/tests/profiler_unittest.cc + +commit 2bf83af65664a2badbaebdb722ad498e8b38548c +Author: Aliaksey Kandratsenka +Date: Sat Nov 16 11:35:32 2013 -0800 + + issue-587: fix typos in unit test scripts + + As proposed by Hannes Weisbach. + + The argument will be garbled because of a misplaced brace, for example + (heap-checker_unittest.sh): + + HEAP_CHECKER="${1:-$BINDIR}/heap-checker_unittest" + which should be: + HEAP_CHECKER="${1:-$BINDIR/heap-checker_unittest}" + + This unit test is used to check the binaries heap-checker_unittest and + heap-checker_debug_unittest. With the typo, the executable + heap-checker_debug_unittest is never actually run. + +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.sh +M src/tests/heap-profiler_unittest.sh +M src/tests/tcmalloc_unittest.sh + +commit b3b19269783cf1ed163bdb447cef9ca11b10851c +Author: Aliaksey Kandratsenka +Date: Sat Nov 9 12:28:55 2013 -0800 + + issue-584: added license note to files without explicit license + + As suggested at corresponding chromium issue discussion it's seemingly + sufficient to simply refer to project-wide LICENSE file. + +M src/tests/page_heap_test.cc +M src/tests/profile-handler_unittest.cc +M src/tests/raw_printer_test.cc +M src/tests/stack_trace_table_test.cc +M src/windows/config.h + +commit 7be35fb0d844c73f5c5301f62074294df5acbc5c +Author: Joonsoo Kim +Date: Thu Oct 10 14:26:47 2013 +0900 + + central_freelist: change fetch ordering + + When we fetch objects from the span for thread cache, we make + reverse-ordered list against original list on the span and suppy + this list + to thread cache. This algorithm has trouble with newly created span. + Newly created span has ascending ordered objects list. Since thread + cache + will get reverse-ordered list against it, user gets objects as + descending order. + + Following example shows what occurs in this algorithm. + + new span: object list: 1 -> 2 -> 3 -> 4 -> 5 -> ... + fetch N items: N -> N-1 -> N-2 -> ... -> 2 -> 1 -> NULL + thread cache: N -> N-1 -> N-2 -> ... -> 2 -> 1 -> NULL + + user's 1st malloc: N + user's 2nd malloc: N-1 + ... + user's Nth malloc: 1 + + In general, access memory with ascending order is better than + descending + order in terms of the performance. So this patch fix this situation. + + I run below program to measure performance effect. + + #define MALLOC_SIZE (512) + #define CACHE_SIZE (64) + #define TOUCH_SIZE (512 / CACHE_SIZE) + + array = malloc(sizeof(void *) * count); + + for (i = 0; i < 1; i++) { + for (j = 0; j < count; j++) { + x = malloc(MALLOC_SIZE); + array[j] = x; + } + } + + repeat = 10; + for (i = 0; i < repeat; i++) { + for (j = 0; j < count; j++) { + x = array[j]; + for (k = 0; k < TOUCH_SIZE; k++) { + *(x + (k * CACHE_SIZE)) = '1'; + } + } + } + + LD_PRELOAD=libtcmalloc_minimal.so perf stat -r 10 ./a.out 1000000 + + **** Before **** + Performance counter stats for './a.out 1000000' (10 runs): + + 2.715161299 seconds time elapsed + ( +- 0.07% ) + + **** After **** + Performance counter stats for './a.out 1000000' (10 runs): + + 2.259366428 seconds time elapsed + ( +- 0.08% ) + +M src/central_freelist.cc + +commit 7315b45c28564afdc2699beff934a3b45457edc6 +Author: Joonsoo Kim +Date: Thu Oct 10 11:46:12 2013 +0900 + + central_freelist: fetch objects as much as possible during each trial + + It is better to reduce function call if possible. If we try to fetch + objects from one span as much as possible during each function call, + number of function call would be reduced and this would help + performance. + +M src/central_freelist.cc +M src/central_freelist.h + +commit cc002ea19363e1ebbd7f3e809d116ab81a6862cd +Author: Joonsoo Kim +Date: Thu Oct 10 10:06:33 2013 +0900 + + skip unnecessary check during double-check SizeClass intergrity + + On initialization step, tcmalloc double-checks SizeClass integrity + with + all possible size values, 0 to kMaxSize. This causes tremendous + overhead + for short-lived applications. + + For example, consider following command. + 'find -exec grep something {} \;' + + Actual work of each grep is really small, but double-check requires + more work. To reduce this overhead, it is best to remove double-check + entirely. But we cannot be sure the integrity without double-checking, + so alternative is needed. + + This patch doesn't remove double-check, instead, try to skip + unnecessary + check based on ClassIndex() implementation. This reduce much + overhead and + the code has same coverage as previous double-check. Following is + the result of this patch. + + time LD_PRELOAD=libtcmalloc_minimal.so find ./ -exec grep "SOMETHING" + {} \; + + * Before + real 0m3.675s + user 0m1.000s + sys 0m0.640s + + * This patch + real 0m2.833s + user 0m0.056s + sys 0m0.220s + + * Remove double-check entirely + real 0m2.675s + user 0m0.072s + sys 0m0.184s + +M src/common.cc + +commit 3e9a33e8c708ccf3ec91e3a3b14e924f5f79e4a6 +Author: Aliaksey Kandratsenka +Date: Sat Oct 26 16:54:03 2013 -0700 + + issue-583: include pthread.h into static_var.cc + + Because we're doing pthread_atfork. + + Fix suggested by user named drussel. + +M src/static_vars.cc + +commit db0d5730ee059d72b895fbead5237f9cb5bbf98a +Author: Aliaksey Kandratsenka +Date: Sat Jun 22 13:48:11 2013 -0700 + + issue-579: ensure order between memory region and libunwind locks + + I.e. to prevent possible deadlock when this locks are taked by + different threads in different order. + + This particular problem was also reported as part of issue 66. + +M src/memory_region_map.cc + +commit 42ddc8d42c82ba6f5137c26b4e7f752b1a022831 +Author: Aliaksey Kandratsenka +Date: Sat Sep 21 19:03:52 2013 -0700 + + added emacs -*- mode lines for google coding style + +M src/addressmap-inl.h +M src/base/atomicops-internals-arm-generic.h +M src/base/atomicops-internals-arm-v6plus.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-mips.h +M src/base/atomicops-internals-windows.h +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/basictypes.h +M src/base/commandlineflags.h +M src/base/cycleclock.h +M src/base/elf_mem_image.cc +M src/base/elf_mem_image.h +M src/base/elfcore.h +M src/base/googleinit.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.cc +M src/base/logging.cc +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +M src/base/simple_mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/spinlock_internal.cc +M src/base/spinlock_internal.h +M src/base/spinlock_linux-inl.h +M src/base/spinlock_posix-inl.h +M src/base/spinlock_win32-inl.h +M src/base/stl_allocator.h +M src/base/synchronization_profiling.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/thread_lister.h +M src/central_freelist.cc +M src/central_freelist.h +M src/common.cc +M src/common.h +M src/config_for_unittests.h +M src/debugallocation.cc +M src/getpc.h +M src/gperftools/heap-checker.h +M src/gperftools/heap-profiler.h +M src/gperftools/malloc_extension.h +M src/gperftools/malloc_hook.h +M src/gperftools/profiler.h +M src/gperftools/stacktrace.h +M src/gperftools/tcmalloc.h.in +M src/heap-checker-bcad.cc +M src/heap-checker.cc +M src/heap-profile-stats.h +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/libc_override.h +M src/libc_override_gcc_and_weak.h +M src/libc_override_glibc.h +M src/libc_override_osx.h +M src/libc_override_redefine.h +M src/linked_list.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/malloc_hook_mmap_freebsd.h +M src/malloc_hook_mmap_linux.h +M src/maybe_threads.cc +M src/maybe_threads.h +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/packed-cache-inl.h +M src/page_heap.cc +M src/page_heap.h +M src/page_heap_allocator.h +M src/pagemap.h +M src/profile-handler.cc +M src/profile-handler.h +M src/profiledata.cc +M src/profiledata.h +M src/profiler.cc +M src/raw_printer.cc +M src/raw_printer.h +M src/sampler.cc +M src/sampler.h +M src/span.cc +M src/span.h +M src/stack_trace_table.cc +M src/stack_trace_table.h +M src/stacktrace.cc +M src/stacktrace_arm-inl.h +M src/stacktrace_config.h +M src/stacktrace_generic-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +M src/stacktrace_win32-inl.h +M src/stacktrace_x86-inl.h +M src/static_vars.cc +M src/static_vars.h +M src/symbolize.cc +M src/symbolize.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tcmalloc.h +M src/tcmalloc_guard.h +M src/tests/addressmap_unittest.cc +M src/tests/atomicops_unittest.cc +M src/tests/current_allocated_bytes_test.cc +M src/tests/debugallocation_test.cc +M src/tests/frag_unittest.cc +M src/tests/getpc_test.cc +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/malloc_extension_c_test.c +M src/tests/malloc_extension_test.cc +M src/tests/malloc_hook_test.cc +M src/tests/markidle_unittest.cc +M src/tests/memalign_unittest.cc +M src/tests/packed-cache_test.cc +M src/tests/page_heap_test.cc +M src/tests/pagemap_unittest.cc +M src/tests/profile-handler_unittest.cc +M src/tests/profiledata_unittest.cc +M src/tests/profiler_unittest.cc +M src/tests/raw_printer_test.cc +M src/tests/realloc_unittest.cc +M src/tests/sampler_test.cc +M src/tests/sampling_test.cc +M src/tests/simple_compat_test.cc +M src/tests/stack_trace_table_test.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_large_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.cc +M src/tests/testutil.h +M src/tests/thread_dealloc_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/auto_testing_hook.h +M src/windows/get_mangled_names.cc +M src/windows/gperftools/tcmalloc.h +M src/windows/gperftools/tcmalloc.h.in +M src/windows/mingw.h +M src/windows/mini_disassembler.cc +M src/windows/mini_disassembler.h +M src/windows/mini_disassembler_types.h +M src/windows/override_functions.cc +M src/windows/port.cc +M src/windows/port.h +M src/windows/preamble_patcher.cc +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_test.cc +M src/windows/preamble_patcher_with_stub.cc + +commit 799a22624c85e8749f8bed0bfa63282b03e75bdd +Author: Aliaksey Kandratsenka +Date: Sat Sep 28 19:32:20 2013 -0700 + + issue-575: do not use cycle count register on arm6 + + Apparently not all arm6 implementations implement it in this + particular way. + + This applies patch by Ben Avison. + +M src/base/cycleclock.h + +commit 2a2d6596f8c3d62b7ec444761f4edf0c85d10d92 +Author: Petr Hosek +Date: Fri Aug 23 23:58:47 2013 -0700 + + Adds system-alloc_unittest Visual Studio project + +M gperftools.sln +A vsprojects/system-alloc_unittest/system-alloc_unittest.vcproj + +commit 83aed118e009b92ea88645ef1f7b842a921612c5 +Author: Petr Hosek +Date: Fri Aug 23 13:53:35 2013 -0700 + + issue-567: Allows for overriding system allocator on Windows + + [alk@tut.by: minor changes to make mingw build work] + Signed-off-by: Aliaksey Kandratsenka + +M Makefile.am +M src/windows/port.cc +A src/windows/system-alloc.cc +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 4ad16873a0a2d8861a0bfe8234d45e31cc70ee90 +Author: Petr Hosek +Date: Sat Aug 24 14:24:47 2013 -0700 + + Exports SysAllocator class to avoid .dll build errors + +M src/gperftools/malloc_extension.h + +commit 326990b5c30d249c3cf4688a88fc415b05494aca +Author: Aliaksey Kandratsenka +Date: Sat Sep 14 14:38:53 2013 -0700 + + issue-557: added support for dumping heap profile via signal + + This applies patch from Jean Lee. + + I've reformatted it to match surronding code style and changed + validation logic a bit. I.e. we're not checking signal for range + anymore given we're not sure what different platforms support, but + we're checking return value of signal() for SIG_ERR instead. + +M src/heap-profiler.cc + +commit cb65e49b83c84bc205203c12793f2dd00c4a7721 +Author: Aliaksey Kandratsenka +Date: Sat Sep 14 16:45:42 2013 -0700 + + issue-536: do not PrintStats if running under valgrind + + When we detect running under valgrind we do not initialize our own + malloc. So trying to print malloc stats when asked via MALLOCSTATS + cannot work. + + This does fix proposed by Philippe Waroquiers. In which we detect + running under valgrind prior to checking MALLOCSTATS environment + variable and refuse printing stats if we detect valgrind. + +M src/tcmalloc.cc + +commit 6979583592df555a369a2c975f5117a1f61911af +Author: Aliaksey Kandratsenka +Date: Mon Sep 9 07:59:25 2013 -0700 + + issue-564: added atomic ops support for mips{,64} + + This merges patch contributed by Jovan Zelincevic. + + And with that patch tcmalloc build with --enable-minimal (just malloc + replacement) appears to work (passes unit tests). + +M Makefile.am +A src/base/atomicops-internals-mips.h +M src/base/atomicops.h +M src/base/basictypes.h +M src/base/linux_syscall_support.h +M src/stacktrace_config.h + +commit 28dd85e2825af71138621a4417e6ab004631924d +Author: Aliaksey Kandratsenka +Date: Fri Aug 30 16:57:14 2013 +0300 + + implement pc from ucontext access for mips + +M m4/pc_from_ucontext.m4 + +commit 819a2b051f1dba9526f2338098fff6dd1700bdb6 +Author: Aliaksey Kandratsenka +Date: Thu Aug 29 19:00:31 2013 +0300 + + issue-413: disable __thread usage on OSX + + Because it was found that __thread variables access is compiled into + calls to tlv_get_addr which was found to call malloc. Because we + actually use thread-local storage from inside malloc it leads to stack + overflow. So we'll continue using pthreads API for that which is known + to work on OSX. + +M configure.ac + +commit 43809080931127037ce6e748f37a28ce7489387d +Author: Aliaksey Kandratsenka +Date: Thu Aug 29 18:51:48 2013 +0300 + + lowered autoconf requirement + + Autoconf 2.59 works. And most notably it will not affect our releases + which are all prepared with newer autoconf. + +M configure.ac + +commit 7a178d472737d988583bade3f0345201651cd43f +Author: Joon-Sung Um +Date: Tue Aug 27 22:16:18 2013 +0900 + + Update document for tcmalloc + + Update tcmalloc.html for new parameters. + + * kMaxSize = 256k + * kNumClasses = 88 + * kPageShift = 13 + + Signed-off-by: Aliaksey Kandratsenka + +M doc/tcmalloc.html + +commit 313e08b5a1a951f710b0323b3ca4e1e8d869520e +Author: Aliaksey Kandratsenka +Date: Sun Aug 4 20:44:06 2013 +0300 + + issue-560: Revert "issue-481: ... + + ...Replaced test mechanism for distinct address spaces with a more + reliable mechanism" + + This reverts commit 5dd53ab6cbf9d98f2d60546835e84785a104da46 (svn + revision 167) + + With this commit rhel 6.2 fails heap-checker-death_unittest and + without it passes. + + Ticket refers to 2 things and both are invalid: + + * that ptrace PEEKDATA ignores data argument. I've checked kernel + source and found it to be wrong + + * something about distinct address spaces + + And in addition to all that original ticket admits that it doesn't fix + anything. + + It looks like, compared to original code that "fix" is not succesfully + wait-ing on parent's ptrace request. I.e. by adding some additional + diagnostics I'm seeing this sys_waitpid returning ECHILD. + +M src/base/linuxthreads.cc + +commit 6d00cbce92c5576b4bcf07a2b5634b4dcfa14f8a +Author: Aliaksey Kandratsenka +Date: Sat Aug 17 15:52:53 2013 +0300 + + issue-561: don't cast function pointer to void * + + Which gcc-3.4 (as shipped in rhel 4) doesn't like. + + Cast to void * was originally added to avoid issue on OSX which + doesn't have sighandler_t. + + In that place we only need to know if it's null or not. So casting to + intptr_t looks like simplest possible way to achieve that. + +M src/profiler.cc + +commit 7d8d522d737f6c55169264b35ebe0be1f9b23efd +Author: Aliaksey Kandratsenka +Date: Sat Aug 17 15:52:22 2013 +0300 + + add heap-profile-stats.h to dist .tar.gz + +M Makefile.am + +commit d76cfa6d6ca5944d6300765fcb9160e889423750 +Author: Aliaksey Kandratsenka +Date: Sun Aug 4 18:35:55 2013 +0300 + + issue-502: Count m(un)map for each stacktrace in MemoryRegionMap + + ..instead of HeapProfileTable + + This upstreams chromium commit reviewed at: + https://codereview.chromium.org/12388070 + + Original and upstreaming author is: Dai MIKURUBE + + This patch fixes a bug that gperftools(TCMalloc)'s mmap profiler + (HEAP_PROFILE_MMAP) doesn't hook some memory pages used by the + profiler itself. + + This problem has been lived in gperftools for a long time. + It is discussed in gperftools' issue 502. + https://code.google.com/p/gperftools/issues/detail?id=502 + + Some bugs in the mmap profiler were fixed by + https://code.google.com/p/gperftools/issues/detail?id=383, + but the patch in the issue 383 didn't fix the bug mentioned in + the issue 502. + + This change reverts the previous patch and http://crrev.com/132771 + at first. Then, it modifies MemoryRegionMap to count m(un)map + calls for each stacktrace in itself instead of merging the counts + for each stacktrace in HeapProfileTable. + + This change also cleans up heap-profiler, heap-profile-table and + deep-heap-profile. + + Chromium-BUG=https://code.google.com/p/chromium/issues/detail?id=181517 + Chromium-Committed: + https://src.chromium.org/viewvc/chrome?view=rev&revision=188176 + +M src/heap-checker.cc +A src/heap-profile-stats.h +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/memory_region_map.cc +M src/memory_region_map.h + +commit 89b163a0883d40a612331ed8565b8ab1219fdbd0 +Author: Aliaksey Kandratsenka +Date: Sun Aug 4 18:27:07 2013 +0300 + + added .gitignore + +A .gitignore + +commit 18fbc316eebea9db2d7ec41e161c0a3fbb09fa42 +Author: alkondratenko@gmail.com + +Date: Wed Jul 31 04:02:19 2013 +0000 + + Fix a C++11 error. + + This merges patch by Nico Weber. + + New clang versions complain in C++11 mode that: + + error: cannot initialize a variable of type 'void *' with an rvalue + of type 'uintptr_t' (aka 'unsigned long') + + This same change was done for the google-internal version of + tcmalloc too. + + Reviewed-at: https://codereview.appspot.com/12132043 + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@238 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/stack_trace_table.cc + +commit 674fcd94a8a0a3595f64e13762ba3a6529e09926 +Author: alkondratenko@gmail.com + +Date: Tue Jul 30 09:14:20 2013 +0000 + + bump version to 2.1 + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@236 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS +M configure.ac +M packages/deb/changelog +M src/windows/config.h +M src/windows/gperftools/tcmalloc.h + +commit 805a6601939edd9bca60a8911e56b217e477c75e +Author: alkondratenko@gmail.com + +Date: Tue Jul 30 08:30:45 2013 +0000 + + issue-559: don't setup fork handler in InitStaticVars + + Because on OSX it calls malloc which leads to deadlock. + + Given that we don't really need that fork handler _that_ early, it's + fine to change it to normal static initializer + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@235 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/static_vars.cc + +commit c583a5babb54aedf6ab6e7746fd976ef2469839d +Author: alkondratenko@gmail.com + +Date: Tue Jul 30 08:30:19 2013 +0000 + + issue-559: don't depend on sighandler_t + + Which is not available on OSX. + + I've also fixed style around this place. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@234 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/profiler.cc + +commit 1af20041bf5821167e69bf905596b2d45d1d94da +Author: alkondratenko@gmail.com + +Date: Tue Jul 30 08:29:46 2013 +0000 + + issue-559: AtomicWord xxx_AtomicExchange are all inline + + Otherwise OSX correctly complains about duplicate definitions + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@233 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops.h + +commit 7a9c4e075fe2572307cddd11bc2f5c7d6b3d29ee +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 19:36:08 2013 +0000 + + issue-556: update windows PACKAGE_{VERSION,STRING} + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@232 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/config.h + +commit 11d46f0aac5ef941b74114412bda4747a349c60d +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 19:35:38 2013 +0000 + + issue-556: dll-export getpagesize + + Because page_heap_test needs this. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@231 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/port.cc +M src/windows/port.h + +commit 6d4ad4428bb8f587d890fa5b7a76ba65dcf48dcb +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 19:35:20 2013 +0000 + + issue-556: drop malloc limit at the end of page_heap_test + + Which otherwise causes somewhat weird stack overflow on release + windows builds. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@230 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/page_heap_test.cc + +commit be54c3f3ed192eabab9b075ec924d2479a956b9d +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 19:34:54 2013 +0000 + + issue-556: dll-export TCMalloc_System{Alloc,Release} + + because page_heap_test is using this stuff + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@229 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/system-alloc.h +M src/windows/port.cc + +commit e3716145cbfa1247fa37dd627b2136a061944255 +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 18:19:05 2013 +0000 + + issue-552: Fix page_heap_test for system with different page size + + This is patch by Adhemerval Zanella. + + PowerPC uses 64K page size instead of 4k for x86 and x86_64. It + makes the + page_heap_test fails because the following test: + + static bool HaveSystemRelease = + TCMalloc_SystemRelease(TCMalloc_SystemAlloc(kPageSize, NULL, + 0), kPageSize); + + will always fail if kPageSize is less than getpagesize() (the default + configuration). + + The following patch fixes it by trying to allocate/deallocate + an entire + page instead. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@228 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/page_heap_test.cc + +commit f45133e75c09ca7d5e86bda2db16e30c6fa348c0 +Author: alkondratenko@gmail.com + +Date: Fri Jul 26 18:04:03 2013 +0000 + + issue-553: Fix syscall wrapper for PowerPC + + This is patch by Adhemerval Zanella. + + * src/stacktrace_powerpc-inl.h: It is just a cleanup for the + stacktrace + functions for PowerPC. The idea is to simplify the code. + * src/tests/heap-checker_unittest.cc: Handles the PPC64 function + descriptor + correctly in malloc tracers. Different from other architecture, + for PPC64 + the address returned in function pointers are the ODP entry, not the + symbol address in .text segment. This leads the comparison bogus, + since + it will compare a ODP entry with a .text address. + * src/heap-checker.cc: Add support for PPC in ptrace. + * src/base/elfcore.h: Likewise. + * src/base/linuxthreads.cc: Fix the thread creation using the clone + wrapper. + * src/base/linux_syscall_support.h: Various fixes for PPC32 and PPC64: + fixes the kernel_stat[64] struct layout, and sys_clone and + sys_socket + implementation. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@227 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/elfcore.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.cc +M src/heap-checker.cc +M src/stacktrace_powerpc-inl.h +M src/tests/heap-checker_unittest.cc + +commit ee2bf097133b115e3da249e43507e02645e46e59 +Author: alkondratenko@gmail.com + +Date: Sat Jul 20 21:37:26 2013 +0000 + + updated NEWS and packages/ for 2.1rc + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@226 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS +M packages/deb/changelog +M packages/deb/control +M packages/deb/copyright +M packages/rpm/rpm.spec + +commit 60ab178aeb827378d78cae8f1c6f893b14deaaf0 +Author: alkondratenko@gmail.com + +Date: Sat Jul 20 21:37:01 2013 +0000 + + bump version number for 2.1rc + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@225 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure.ac +M src/windows/gperftools/tcmalloc.h + +commit 7c2aa2f7c2cf901c17b9b9215224f725e798d1f2 +Author: alkondratenko@gmail.com + +Date: Sat Jul 20 21:35:56 2013 +0000 + + issue-546: fixed return type of Release_AtomicExchange on arm6+ + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@224 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-v6plus.h + +commit d8e12e94ea09eaf8b040c6887f75cdf832b5619b +Author: alkondratenko@gmail.com + +Date: Sat Jul 20 21:35:14 2013 +0000 + + issue-549: handle most recent mingw that has sleep and nanosleep + + I.e. we have to check their presence in configure and in case of their + presence we have to avoid re-defining then in window's port.h + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@223 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure.ac +M src/windows/port.h + +commit ac354636de8a4f11e4fde679b52e9f58fda0e079 +Author: alkondratenko@gmail.com + +Date: Sun Jul 14 04:19:02 2013 +0000 + + issue-550: remove config.h.in + + Which is autoconf product and thus is not needed in source repository + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@222 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +D src/config.h.in + +commit e54971d58641853a9515d9f0313645729eab113a +Author: alkondratenko@gmail.com + +Date: Sat Jul 6 21:54:34 2013 +0000 + + issue-534: fixed a number of gcc warnings + + This applies patch from Adhemerval Zanella. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@221 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/basictypes.h +M src/heap-profiler.cc +M src/profiler.cc +M src/tests/heap-checker_unittest.cc +M src/tests/page_heap_test.cc + +commit 7dd038d7c58c9de889e3fcc552161533ea1baab1 +Author: alkondratenko@gmail.com + +Date: Sat Jul 6 20:48:18 2013 +0000 + + issue-545: corrected README for CPUPROFILE_FREQUENCY variable + + Applied patch by Mikhail Veltishchev + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@220 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M README + +commit a833a146b7de93774f0a9428edc5eda410d9a7dc +Author: alkondratenko@gmail.com + +Date: Sat Jul 6 20:46:50 2013 +0000 + + issue-528: fixed spelling + + This simply applies patch by Lajos Veres + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@219 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M doc/heapprofile.html +M doc/pprof_remote_servers.html +M src/base/spinlock.cc +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/gperftools/profiler.h +M src/pprof +M src/stacktrace_x86-inl.h +M src/windows/patch_functions.cc +M src/windows/preamble_patcher.cc + +commit 205abf1e7cb860224cbf391c7f69a6192ccc5076 +Author: alkondratenko@gmail.com + +Date: Sun May 12 19:15:13 2013 +0000 + + issue-518: add support for x32 ABI to linux_syscall_support.h + + As pointed out in the ticket this is taken from chromium review system + here: https://codereview.chromium.org/13648012 + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@218 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linux_syscall_support.h + +commit 376a3107aa06063d72132318ac5ad266466e4325 +Author: alkondratenko@gmail.com + +Date: Tue May 7 22:28:05 2013 +0000 + + issue-368: allocate enough bytes for large metadata allocations + + During issue-368 review it was correctly pointed out then in place + where I compare metadata allocation size to threshold I should pass + that size down to TCMalloc_SystemAlloc instead of threshold. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@217 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/common.cc + +commit 58d39a1b2190b9d0b719ee33f7bc5383a9b27462 +Author: alkondratenko@gmail.com + +Date: Tue May 7 22:23:37 2013 +0000 + + issue-368: added missing large_heap_fragmentation_unittest.cc + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@216 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +A src/tests/large_heap_fragmentation_unittest.cc + +commit c45bb7d6033952ea33bb181c1f96999317b535a1 +Author: alkondratenko@gmail.com + +Date: Tue May 7 19:22:45 2013 +0000 + + issue-511: fixed negative offset handling for conditional jumps + + While doing and testing issue-511 I've found one subtle bug which is + incorrect handling of short offsets. They are defined to be signed but + previous code used unsigned char for them which caused negative + offsets to look like larger positive offsets. Fix is trivial. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@215 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/preamble_patcher.cc + +commit 3567b1701aa55a6421aefa5f3de1ca5507cbdf79 +Author: alkondratenko@gmail.com + +Date: Tue May 7 19:15:35 2013 +0000 + + issue-511: recognise rex.w jmpq *(%rip) as iat jump + + Apparently Windows Server 2012 (and presumably windows 8) now has this + form of iat jump. Which is quite useless (rex.w is according to my + understanding is not needed at all) but because of rex.w our code to + recognize jumps like that didn't work. + + Fix is just skip this prefix. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@214 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/preamble_patcher.cc + +commit 7fcb5ac0696e7ef7f7e7e51c18745af25de7da96 +Author: alkondratenko@gmail.com + +Date: Tue May 7 19:13:29 2013 +0000 + + issue-511: implemented rel8 jump patching + + I've found that Visual Studio 2012 release 32-bit C runtime library + patching fails because array new has rel8 jmp which previous code + could not handle. + + Implementation is largely copied from conditional jumps handling code. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@213 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/preamble_patcher.cc +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_with_stub.cc + +commit 8cb4086a0aee539869bd087a85881788545b23d6 +Author: alkondratenko@gmail.com + +Date: Mon May 6 19:50:59 2013 +0000 + + issue-368: test that we don't fragment large spans too badly + + This adds unit test that does essentially same things as code to + reproduce bug in + https://code.google.com/p/gperftools/issues/detail?id=368 + + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@212 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am + +commit f25ac4421f9efb635b88105e9c0830293ce19f9d +Author: alkondratenko@gmail.com + +Date: Mon May 6 19:50:23 2013 +0000 + + issue-{368,443}: allocate metadata in big batches + + It uses same approach as PageHeapAllocator. Namely allocates big chunk + which is then used to satisfy smaller allocations. + + In issue-443 gradual heap grows causes old code that allocates + metadata in smaller pieces and thus more frequently to fragment the + heap. It's also causing most of 368 heap fragmentation too. + + New code allocates 8 megs of address space at once for metadata + allocations. Most OSes will allocate actual memory only when + corresponding pages are touched. Thus this change should not cause + increased memory usage. + + I've also made sure metadata is always properly aligned in case we + ever allocate something that breaks natural alignment. E.g. strings. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@211 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/common.cc + +commit 4fd762cead660d4661359ad507083ac4f4967ee4 +Author: alkondratenko@gmail.com + +Date: Mon May 6 19:49:48 2013 +0000 + + issue-368: unmap free spans and retry before growing heap + + Because unmapped spans are not coalesced with normal spans it's + possible that we indeed have a large enough free span, but we fail to + see that because we always consider unmapped and normal spans + separately. That behavior is more likely for larger spans. + + In order to protect programs that grow heap frequently and by small + amounts from much more frequent minor page faults, there's limit of + running that force pages unmap path once per 128 megs of heap growth. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@210 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/page_heap.cc + +commit 99fe9944de32046fd954399e60415fba7d03eeb0 +Author: alkondratenko@gmail.com + +Date: Mon Apr 1 05:32:22 2013 +0000 + + issue-510: remove duplicate arm #elif + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@209 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/basictypes.h + +commit 6354e2c8cdaaaeffdfe7d5b347b125394e2d55fa +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:24:49 2013 +0000 + + issue-506: fixed bogus unit test failure + + Looks like my version of GCC is aware that free(malloc(X)) is a + no-op. So it optimizes that away completely ignoring simple fact that + we're observing malloc hooks invocations. By adding check that malloc + succeeded we force gcc to actually preserve that malloc call. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@208 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/malloc_extension_c_test.c + +commit 7896dcb9db2375fcd1d8d19052985a12ad113ba9 +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:16:47 2013 +0000 + + issue-504: disable tls on mingw + + Which is known to fail. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@207 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure.ac + +commit 8bf4522aa53a7b612a865bc10716192f0f05314b +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:15:46 2013 +0000 + + issue-504: do not define HAVE_MMAP on mingw + + Because, clearly, windows doesn't have one + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@206 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure.ac + +commit 9c24d255cdd8dab7482d968acc69d493680233ce +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:15:23 2013 +0000 + + issue-504: add AM_LDFLAGS to all *_la targets + + Because automake will not automatically add AM_LDFLAGS if there's + per-target LDFLAGS. See their good info manual. + + This fixes .dll compilation of tcmalloc + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@205 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am + +commit a2275fc6b48b98d5265388bb8586faa7c8cc581f +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:14:18 2013 +0000 + + issue-504: don't try to typedef pid_t on mingw + + Because recent mingws (more then few years ago seemingly) do that + already. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@204 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/mingw.h +M src/windows/port.h + +commit f00977533de6fd27a2f796b2e8e9adb7fcd965e8 +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:13:53 2013 +0000 + + issue-504: use gcc inline assembly atomic ops on mingw + + Because those are well tested and can be trusted + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@203 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M src/base/atomicops.h + +commit 34cdd6821b637b124722687578aa119e8714266c +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 19:13:13 2013 +0000 + + issue-504: use lowercase windows includes for mingw x-compilation + + I.e. so that I can build tcmalloc.dll using comfortable environment of + my GNU/Linux box and without having to touch actual windows box or VM. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@202 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M src/base/sysinfo.h +M src/windows/patch_functions.cc + +commit 0971d80d0ef0c881dcf46453e576a7e289d86975 +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 18:35:16 2013 +0000 + + issue-503: updated svn:ignore to ignore generated files + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@201 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit 05b100d9d4ffeb1342eb5ecf50bd0d2339e626c5 +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 18:32:05 2013 +0000 + + issue-503: removed checked in configure and other auto* products + + So that it's easier to contribute and review contributions. + + People wishing to build gperftools from svn checkout should run + autogen.sh first which will create those files and then ./configure && + make as usual + + INSTALL file has updated instructions too. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@200 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +D Makefile.in +D aclocal.m4 +M autogen.sh +D compile +D config.guess +D config.sub +D configure +M configure.ac +D depcomp +D install-sh +D ltmain.sh +D m4/libtool.m4 +D m4/ltoptions.m4 +D m4/ltsugar.m4 +D m4/ltversion.m4 +D m4/lt~obsolete.m4 +D missing +D mkinstalldirs + +commit dcf55b976f19a186ac04d60d95e03ed2795285c4 +Author: alkondratenko@gmail.com + +Date: Mon Mar 11 18:29:00 2013 +0000 + + issue-503: recover original INSTALL file + + That was accidently overwritten by autotools files update in r196 + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@199 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL + +commit 5037f687d1de80722f634e84763572caf2725f98 +Author: chappedm@gmail.com + +Date: Mon Mar 11 01:35:37 2013 +0000 + + issue-425: Fixed tcmalloc unittest crashes for windows builds + + Missing use of volatile was causing vs2010 to perform unwanted + optimization resulting in the crash. See issue for more details. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@198 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/tcmalloc_unittest.cc + +commit beb78cc05babf0a49d21aed0ec789f19fc0f2d28 +Author: chappedm@gmail.com + +Date: Mon Mar 11 00:23:03 2013 +0000 + + issue-493: Fix for building against ARM targets + + gperftools was failing to build for arm targets for the following + reasons: + 1. Some ARMv7 instructions used when the target is ARMv6 so those + fail to assemble + 2. The cache line length is undefined for ARM architectures + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@197 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-v6plus.h +M src/base/basictypes.h + +commit bd3b3a7e9a67fac846cf574f5bfd241157bdfe3c +Author: chappedm@gmail.com + +Date: Sun Mar 10 20:17:21 2013 +0000 + + issue-496: Fixes an issue where tcmalloc might deadlock in a thread + calling fork + + tcmalloc contained a bug where some internal locks were left in a + undefined state + between fork, leaving the child process in a deadlock state. This + patch fixes the + issue by introducing stricter locking between the parent nd child + while forking. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@196 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.in +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +M depcomp +M install-sh +M missing +M mkinstalldirs +M src/central_freelist.h +M src/config.h.in +M src/static_vars.cc + +commit 560ca8650c8a9d2971420970f0ed5e17848150eb +Author: chappedm@gmail.com + +Date: Sun Mar 10 20:02:46 2013 +0000 + + issue-491: Significant performance improvement for spin lock + contention + + This patch fixes issues where spinlocks under contention were + failing to + wakeup waiters, sometimes resulting in blow ups from 13ns to as high + as 256ms. + Under heavy contention, applications were observed sleeping for + minutes at a + time giving the appearance of a hang. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@195 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/spinlock.h + +commit b591d53af951eac60683237204464ebfec2c3afa +Author: chappedm@gmail.com + +Date: Sun Mar 10 19:54:39 2013 +0000 + + issue-490: Added support for acquire/release atomic exchange + + The atomic ops API was missing support for all of the various + flavors of Acquire_AtomicExchange and Release_AtomicExchange + which have now been added. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@194 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-generic.h +M src/base/atomicops-internals-arm-v6plus.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-windows.h +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/tests/atomicops_unittest.cc + +commit 687207b5fcfadc821a3d5b94f2ea112ca933e476 +Author: chappedm@gmail.com + +Date: Sun Mar 10 19:44:43 2013 +0000 + + issue-443: Increase the number of objects transferred between thread + cache and central free list + + This fix is a result of a performance degradation observed in + multi-threaded programs where large + amounts of memory (30GB) are consumed, released by a pool of threads + in a cyclic manner. This was + mainly due to the amount of time we were spending in the slow path + consolidating memory between + the thread cache and central free list. The default has been bumped + up to 32768 and is now also + controllable through the TCMALLOC_TRANSFER_NUM_OBJ environment + setting. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@193 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M src/common.cc +M src/common.h +A src/tests/tcmalloc_unittest.sh + +commit 19eff86f850e54683c8868316e362af8919df18a +Author: alkondratenko@gmail.com + +Date: Sat Mar 9 01:16:17 2013 +0000 + + actually made svn:ignore work + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@192 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit 177a896a8273ae73affc48a126fcf9a3ba91f502 +Author: alkondratenko@gmail.com + +Date: Sat Mar 9 01:06:58 2013 +0000 + + added proper svn:ignore + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@191 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit b96203b591f63d24cd2979241b18534d22358bca +Author: chappedm@gmail.com + +Date: Sat Dec 22 20:14:08 2012 +0000 + + issue-461: Fix to malloc_extension.h so that it builds with + -std=gnu++98 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@190 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/gperftools/malloc_extension.h + +commit 84b983c8d43f43a3c7f71d45d51fc4adcc688cd9 +Author: chappedm@gmail.com + +Date: Sat Dec 22 20:06:47 2012 +0000 + + issue-465: Adding automagic support for __builtin_expect + + Previously __builtin_ expect was based on a macro check against + gcc version. + Now we perform the check via AM which is a cleaner approach. There + are also + a number of code changes here to utilize LIKELY/UNLIKELY macros + based on + __builtin_expect to improve performance. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@189 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure +M configure.ac +M src/base/basictypes.h +M src/common.h +M src/config.h.in +M src/tcmalloc.cc + +commit a5dacccd6ae4cbfedb5263bfe0f325f03c7f0db8 +Author: chappedm@gmail.com + +Date: Sat Dec 22 19:06:35 2012 +0000 + + issue-466: Clarified stats output and comments for ExtractStats() + and GetThreadStats() + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@188 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tcmalloc.cc +M src/thread_cache.h + +commit 09d97533b09e473c0cdd269e8cf4e9a9737e49fa +Author: chappedm@gmail.com + +Date: Sat Dec 22 19:02:52 2012 +0000 + + issue-467: Fixed issue with allocation size being narrowed to 32-bit + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@187 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tcmalloc.cc + +commit 990889e6232ff3787f1d42d4091a0478ffb93988 +Author: chappedm@gmail.com + +Date: Sat Dec 22 18:53:18 2012 +0000 + + issue-470: Allows the default system allocator to be overidden + + This is useful when you run into cases where you need an allocator + before tcmalloc has been fully initialized. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@186 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/system-alloc.cc + +commit 3bf5f55d78769d2f8525626dd662457d2f014151 +Author: chappedm@gmail.com + +Date: Sat Dec 22 18:38:48 2012 +0000 + + issue-482: Adds support for CACHELINE_ALIGNED value for arm based + devices + + Hardcoded the cacheline size to 32 because this value is supported + by several + arm devices, however a better logic needs to be implemented at some + point to + handle more arm devices. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@185 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/basictypes.h + +commit 6856d1d1b2a807efd84dcafa10b865b6de22bc28 +Author: chappedm@gmail.com + +Date: Sat Dec 22 18:34:43 2012 +0000 + + issue-488: Performance improvement for initialization checks + + These came in from the Google-internal version of tcmalloc. They + saw some + decent speed improvements, both on microbenchmarks and big + programs. The + idea is to improve the speed of the "Is everything initialized?" type + of + code, that's at the start of all allocations and deallocations. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@184 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/static_vars.h +M src/tcmalloc.cc +M src/thread_cache.cc +M src/thread_cache.h + +commit ad5aa05838121d52ad1fde5463a796c3320fe067 +Author: chappedm@gmail.com + +Date: Sat Dec 22 18:25:58 2012 +0000 + + issue-483: Speed up accesses to ClassIndex() + + Making its return type unsigned can save a conversion from + signed to unsigned, and getting rid of the ternary operators + seems to help a little bit as well. Various gcc versions weren't + generating conditional moves for them as one would expect. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@183 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/basictypes.h +M src/common.h + +commit 8de78fd85b69bc569ac8fc9e75144e02f5cae851 +Author: chappedm@gmail.com + +Date: Mon Nov 5 04:45:01 2012 +0000 + + issue-452: Adds a control mechanism to the cpu profiler to be switched + on and off using a user defined signal. + + CPUPROFILESIGNAL - Takes a signal number between the value of 1 and + 64 inclusive which represents a signal + number as defined by signal.h. The signal must + not be in use by the program. Sending this + signal to the program turns profiling on and off + like a switch. By default the switch is + off when the program starts. Successive profiles + are suffixed with a monotonically increasing + number. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@182 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M doc/cpuprofile.html +M src/profiler.cc + +commit 46f06ca0db41d3f598750caefdaf3c6063969e64 +Author: chappedm@gmail.com + +Date: Sun Nov 4 23:08:17 2012 +0000 + + issue-451: Fixed incorrect assembly for 64-bit barrier load and + store on windows platforms. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@181 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-windows.h + +commit 5fe91d5623c2351ba4675db71822fc6be5e2cbce +Author: chappedm@gmail.com + +Date: Sun Nov 4 22:53:01 2012 +0000 + + issue-450: Move includes for struct mallinfo from tcmalloc.cc to + tcmalloc.h to fix compiler warnings from clang. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@180 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/gperftools/tcmalloc.h.in +M src/tcmalloc.cc + +commit 86a55316baf2a7c0718670fd7342b648e0ef4a87 +Author: chappedm@gmail.com + +Date: Sun Nov 4 19:12:42 2012 +0000 + + issue-449: Disables mmap check when cross compiling since it is + meaningless anyways + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@179 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure +M configure.ac + +commit 6f6c2bf68576e43491884364fc05c9ed752adb4f +Author: chappedm@gmail.com + +Date: Sun Nov 4 19:02:15 2012 +0000 + + issue-448: New environment setting that allows you to set an explicit + heap limit + + TCMALLOC_HEAP_LIMIT_MB - The maximum amount of heap memory that + tcmalloc can use. + TCMALLOC_DISABLE_MEMORY_RELEASE - emulate platform with no + MADV_DONTNEED support (generally for testing purposes). + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@178 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/page_heap.cc +M src/page_heap.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tests/page_heap_test.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/port.cc + +commit 644b1c6e355a0f5dd948ca482a575f49a4bd2032 +Author: chappedm@gmail.com + +Date: Sun Nov 4 18:30:05 2012 +0000 + + issue-445: Fix for wrong cmpx instruction in OSAtomicCompareAndSwap64 + for ppc64 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@177 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-linuxppc.h + +commit e32bb2d9a76dc5ee42ee41a2ca2c6e5caece0150 +Author: chappedm@gmail.com + +Date: Sun Nov 4 18:24:46 2012 +0000 + + issue-444: Fix for invalid conversion build error in signal handler + code + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@176 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linux_syscall_support.h + +commit abeaf46028c8dfab7e7867ee7a3a49ebe21cf129 +Author: chappedm@gmail.com + +Date: Sun Nov 4 18:15:11 2012 +0000 + + issue-430: Introduces 8-byte alignment support for tcmalloc + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@175 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/common.cc +M src/common.h +M src/tests/tcmalloc_unittest.cc + +commit baaf0188295582ca68df03f70baa13d96a88e2eb +Author: chappedm@gmail.com + +Date: Sun Nov 4 17:41:47 2012 +0000 + + issue-473: Fix for make install error regarding + src/windows/google/tcmalloc.h + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@174 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in + +commit 1363bc69550f43af693f6455118432988042a8dd +Author: chappedm@gmail.com + +Date: Sun Nov 4 17:21:00 2012 +0000 + + issue-475: Re-applying changes made originally for r150 and r151 + + - Used aclocal, autoupdate, autoconf, and automake to + correctly apply changes made to Makefile.am. Detailed + instructions on this procedure can be found here + http://inti.sourceforge.net/tutorial/libinti/autotoolsproject.html. + - Fixed a number of error/warning messages due to use of newer + aclocal, autoconf, and automake utilities. + - Directly and indirectly related to issue-385 and issue-480. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@173 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M aclocal.m4 +M configure +M configure.ac +M m4/libtool.m4 + +commit 1243295cdcc20f2f47df9bdc9b8bb50b69c085b0 +Author: chappedm@gmail.com + +Date: Sun Nov 4 15:59:08 2012 +0000 + + issue-475: Amend of r151 and r150 + + In revisions 151 and 150 an attempt was made to enable frame pointers + by default for i386. However, in the process of doing so a number of + files were inadvertently touched as a result of running autogen.sh. As + a result, I have needed to roll back these revisions so that I can + reattempt the change. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@172 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.am +M Makefile.in +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +M depcomp +M install-sh +M ltmain.sh +M m4/libtool.m4 +M m4/ltoptions.m4 +M m4/ltversion.m4 +M m4/lt~obsolete.m4 +M missing +M mkinstalldirs + +commit 5c17459c5e7b4133a2dec5ffe6a9237a114f5378 +Author: chappedm@gmail.com + +Date: Sat Nov 3 16:14:25 2012 +0000 + + issue-476: Amendment to r152:issue-437 to fix a build error due to + PR_SET_TRACER not being defined in older glibc releases. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@171 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linuxthreads.cc + +commit 6287bbbbad8730712cfd1ee28ecc0648cbaa9f94 +Author: chappedm@gmail.com + +Date: Sat Nov 3 15:56:27 2012 +0000 + + issue-477: Fix clang compilation errors regarding format specifiers + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@170 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/sysinfo.cc +M src/debugallocation.cc +M src/getpc.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/memory_region_map.cc +M src/symbolize.cc +M src/tcmalloc.cc +M src/tests/markidle_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit 87699c97cc07b30fc2765415853ae685f7bc45f2 +Author: chappedm@gmail.com + +Date: Sat Nov 3 15:40:01 2012 +0000 + + issue-478: Added the heap profiler tunnable setting + HEAP_PROFILER_TIME_INTERVAL used to dump heap profiles on a specified + time interval. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@169 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M doc/heapprofile.html +M src/heap-profiler.cc + +commit 4eb6946d689bbaa74f8be78265f6d6ff9ae04ab2 +Author: chappedm@gmail.com + +Date: Sat Nov 3 15:27:58 2012 +0000 + + issue-479: Replaced sscanf usage while iterating proc maps entries + to fix a deadlock introduced by glibc-2.15. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@168 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/sysinfo.cc + +commit 5dd53ab6cbf9d98f2d60546835e84785a104da46 +Author: chappedm@gmail.com + +Date: Sat Nov 3 14:52:42 2012 +0000 + + issue-481: Replaced test mechanism for distinct address spaces with + a more reliable mechanism + + Rather than using sys_ptrace+PTRACE_PEEK_DATA to determine whether + address spaces are distinct, we now use sys_waitpid+__WCLONE. See + issue-481 for a more detailed rationale. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@167 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linuxthreads.cc + +commit 6c436203522156699ef11c6792ed481e02cef366 +Author: chappedm@gmail.com + +Date: Sat Nov 3 14:36:33 2012 +0000 + + amend-r165: forgot to regenrate configure and Makefile.in + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@166 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.in +M configure + +commit c566266b10d2fc4e0c67fec25e2a45ebad803196 +Author: chappedm@gmail.com + +Date: Sat Nov 3 14:13:21 2012 +0000 + + issue-480: duplicate of issue-385 fixed in r150 however some of the + comments in the code + regarding frame pointers needed to be clarified. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@165 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M configure.ac + +commit 4f325fbcc9f0db17fbf108188a32b2c67bcd38e0 +Author: chappedm@gmail.com + +Date: Sun Oct 28 19:45:03 2012 +0000 + + issue-424: Updated heap profiler documentation that had + mispelling for the heap profiler mmap only environment setting + (HEAP_PROFILE_ONLY_MMAP) + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@164 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M doc/heapprofile.html + +commit a828c0a8ff59300fffce466cc617d40fa39dedea +Author: chappedm@gmail.com + +Date: Sun Oct 28 19:30:23 2012 +0000 + + issue-417: This commit removed the fatal error message printed along + with the pprof usage information when pprof is run with no arguments. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@163 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/pprof + +commit e5b095abdc2368111f53cedf376cd1505a2c7583 +Author: chappedm@gmail.com + +Date: Sun Oct 28 18:28:21 2012 +0000 + + issue-411: This commit adds additional logging to the cpu profiler + to warn when the profiler is run and no CPUPROFILE environment + setting can be found. It also adds a new environment variable + PERFTOOLS_UNITTEST to allow certain modules to take action when + running under the umbrella of a unit test. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@162 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/profiler.cc +M src/tests/profiler_unittest.sh + +commit 57c48e9b5ffdb0f177c07ea8420c4072e816e1a7 +Author: chappedm@gmail.com + +Date: Sun Oct 28 14:51:41 2012 +0000 + + issue-405: backed out original commit made in revision 147 due to + the fact that it didn't work as intended + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@161 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/heap-checker.cc + +commit 3e296c28c3c2b67df624d372b75650ae65c87b04 +Author: chappedm@gmail.com + +Date: Tue Sep 18 02:47:24 2012 +0000 + + issue-442: Fixes an issue encountered on PPC with undefined + conversions from 'base::subtle::Atomic64*' to 'const volatile + Atomic32*' + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@160 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/spinlock_internal.cc + +commit 1f59bb34d3ce03df51c8356dd44fcb0b15de4769 +Author: chappedm@gmail.com + +Date: Tue Sep 18 02:33:00 2012 +0000 + + Adding support for CPU frequencies for Linux on PowerPC + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@159 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/sysinfo.cc + +commit a2fec7c694ce992a3b7d3fe4205bb8710b017bab +Author: chappedm@gmail.com + +Date: Tue Sep 18 01:43:02 2012 +0000 + + issue-446: Fixes compatability issues in malloc_hook_test for PPC64 + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@158 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/malloc_hook_test.cc + +commit b05b6fc7655ba7fee8397da7013db007f0c47e30 +Author: chappedm@gmail.com + +Date: Tue Sep 18 01:27:34 2012 +0000 + + issue-458: Optimizes malloc hooks for weakly consistent memory + architectures + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@157 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/malloc_hook-inl.h + +commit 00edf667f62e17a268f03c6aaef19946add75dcf +Author: chappedm@gmail.com + +Date: Tue Sep 18 01:18:15 2012 +0000 + + issue-456: Adds support for CACHELINE_ALIGNED values for PPC + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@156 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/basictypes.h + +commit 731d0932a081d521a36462df7dcbc45fa4221011 +Author: chappedm@gmail.com + +Date: Tue Sep 18 00:59:16 2012 +0000 + + issue-455: Adds another size for large pages in tcmalloc through + the new define TCMALLOC_LARGE_PAGES64K + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@155 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/common.h + +commit 771b6bcf689bd089b802ddcdb27a40b4fb4a8e3b +Author: chappedm@gmail.com + +Date: Tue Sep 18 00:52:13 2012 +0000 + + issue-457: Fixed an issue where the 'getpc' testcase was using the + wrong PPC64 preprocessor directive + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@154 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tests/getpc_test.cc + +commit 711232a1ef4997305a681287191de74f6597dabc +Author: chappedm@gmail.com + +Date: Tue Sep 18 00:42:23 2012 +0000 + + issue-453 Added support to get the timebase register value using + just one instruction and also adjusts the PPC32 code to the recent + GLIBC one that implements the same functionality + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@153 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/cycleclock.h + +commit fa0209f261c5e065d523bb1858f84fd91eb2f39a +Author: chappedm@gmail.com + +Date: Tue Sep 18 00:00:20 2012 +0000 + + issue-437 Fixed issues related to new glibc shipped with Ubuntu 10.10 + + 1. ptrace permissions were modifed to be a bit more strict which + required + us to programatically set the permissions while syncing up to + the profiling + thread. + + 2. Order of destructors registered with atexit changed which was + casuing us to + miss generating the backtrace when heap checker was finished. Seems + that we + initially fixed this for FreeBSD and now linux has changed their + behaviour + to be the same. We are now a bit stricter on the rules here + accross all + platforms. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@152 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linuxthreads.cc +M src/heap-checker.cc + +commit cd723b43ff783a05321f0c0ba79a82494185b23c +Author: chappedm@gmail.com + +Date: Wed May 16 12:24:13 2012 +0000 + + issue-385: updates to automake to pick up the explicit setting of + the -fno-omit-frame-pointer for i386 + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@151 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.am +M Makefile.in +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +M depcomp +M install-sh +M ltmain.sh +M m4/libtool.m4 +M m4/ltoptions.m4 +M m4/ltversion.m4 +M m4/lt~obsolete.m4 +M missing +M mkinstalldirs + +commit 0c0382234d5812474b070b6eccdfd99c98490548 +Author: chappedm@gmail.com + +Date: Wed May 16 01:28:08 2012 +0000 + + issue-385: as of gcc 4.6 we now need to enable frame pointers for + i386 platforms since the default is to now omit frame pointers + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@150 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am + +commit bafd0f8b7cec4dd0b74a4a8e5456b96744640679 +Author: chappedm@gmail.com + +Date: Sat Apr 21 17:27:54 2012 +0000 + + Changing internal behaviour of tcmalloc to return an + allocated size of 0 when the target pointer is null (refer to + TCMallocImplementation::GetAllocatedSize). This change was reviewed + as https://codereview.appspot.com/5833050/. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@149 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tcmalloc.cc + +commit 9be2f8d802a19ab6e4b2abed3f7cd84780628d16 +Author: chappedm@gmail.com + +Date: Sat Apr 21 16:15:20 2012 +0000 + + Adding in further support for 64-bit NoBarrier_Load on windows + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@148 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-windows.h + +commit 68df7fa6057a29b3130d41a27592f74d58c2df57 +Author: chappedm@gmail.com + +Date: Sat Mar 3 19:45:49 2012 +0000 + + issue-405: Added a tunable to the heap checker that allows the heap + checker error exit code to be overridden. For larger projects this + allows certain heap checked programs that have intentional/known + leaks to be managed. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@147 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/heap-checker.cc + +commit 0a9d3f8af373c71e5fabdc8c01239c47df4743ed +Author: chappedm@gmail.com + +Date: Fri Mar 2 06:04:08 2012 +0000 + + issue-410: This set of changes exposes the central cache free list + size, transfer cache free list size, and the meta data overhead size + through the getNumericProperty() function. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@146 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/gperftools/malloc_extension.h +M src/tcmalloc.cc + +commit 1233f0f9101c3f4e85e04711c7223dc7f73ec4fb +Author: csilvers +Date: Tue Feb 21 03:02:43 2012 +0000 + + This file is in the tarball, but I forgot to put it in svn as well. + (It's tricky because it's auto-generated from tcmalloc.h.in at + tarball-making time.) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@145 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +A src/windows/gperftools/tcmalloc.h + +commit ce2891234584069f90e6e0a446e28bf7ca3e031d +Author: csilvers +Date: Sat Feb 4 00:10:11 2012 +0000 + + Url-typo in the latest NEWS message. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@144 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS + +commit 4e9432c5090d5b8354b0b57fca8b96b2efef37e3 +Author: csilvers +Date: Sat Feb 4 00:07:36 2012 +0000 + + Fri Feb 03 15:40:45 2012 Google + Inc. + + * gperftools: version 2.0 + * Renamed the project from google-perftools to gperftools + (csilvers) + * Renamed the .deb/.rpm packagse from google-perftools to + gperftools too + * Renamed include directory from google/ to gperftools/ + (csilvers) + * Changed the 'official' perftools email in setup.py/etc + * Renamed google-perftools.sln to gperftools.sln + * PORTING: Removed bash-isms & grep -q in + heap-checker-death_unittest.sh + * Changed copyright text to reflect Google's relinquished + ownership + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@142 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M AUTHORS +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M NEWS +M README +M README_windows.txt +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +M depcomp +M doc/cpuprofile.html +M doc/designstyle.css +M doc/heap_checker.html +M doc/heapprofile.html +M doc/index.html +M doc/pprof.1 +M doc/pprof.see_also +M doc/pprof_remote_servers.html +R100 google-perftools.sln gperftools.sln +M install-sh +M missing +M mkinstalldirs +M packages/deb/changelog +M packages/deb/control +M packages/deb/copyright +R071 packages/deb/libgoogle-perftools-dev.dirs +packages/deb/libgperftools-dev.dirs +R079 packages/deb/libgoogle-perftools-dev.install +packages/deb/libgperftools-dev.install +R100 packages/deb/libgoogle-perftools0.dirs +packages/deb/libgperftools0.dirs +R100 packages/deb/libgoogle-perftools0.install +packages/deb/libgperftools0.install +R100 packages/deb/libgoogle-perftools0.manpages +packages/deb/libgperftools0.manpages +M packages/rpm/rpm.spec +M src/base/low_level_alloc.cc +M src/config.h.in +M src/debugallocation.cc +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +A src/google/tcmalloc.h +C099 src/google/heap-checker.h src/gperftools/heap-checker.h +C100 src/google/heap-profiler.h src/gperftools/heap-profiler.h +C100 src/google/malloc_extension.h src/gperftools/malloc_extension.h +C100 src/google/malloc_extension_c.h +src/gperftools/malloc_extension_c.h +C099 src/google/malloc_hook.h src/gperftools/malloc_hook.h +C100 src/google/malloc_hook_c.h src/gperftools/malloc_hook_c.h +C100 src/google/profiler.h src/gperftools/profiler.h +C100 src/google/stacktrace.h src/gperftools/stacktrace.h +R098 src/google/tcmalloc.h.in src/gperftools/tcmalloc.h.in +M src/heap-checker-bcad.cc +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/internal_logging.cc +M src/libc_override.h +M src/libc_override_gcc_and_weak.h +M src/libc_override_glibc.h +M src/libc_override_osx.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/profiler.cc +M src/stacktrace.cc +M src/stacktrace_arm-inl.h +M src/stacktrace_generic-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +M src/stacktrace_win32-inl.h +M src/stacktrace_x86-inl.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/current_allocated_bytes_test.cc +M src/tests/debugallocation_test.cc +M src/tests/frag_unittest.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/malloc_extension_c_test.c +M src/tests/malloc_extension_test.cc +M src/tests/malloc_hook_test.cc +M src/tests/markidle_unittest.cc +M src/tests/profiler_unittest.cc +M src/tests/sampling_test.cc +C059 src/tests/current_allocated_bytes_test.cc +src/tests/simple_compat_test.cc +M src/tests/stacktrace_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/thread_dealloc_unittest.cc +A src/windows/auto_testing_hook.h +M src/windows/config.h +A src/windows/google/tcmalloc.h +R098 src/windows/google/tcmalloc.h.in +src/windows/gperftools/tcmalloc.h.in +M src/windows/patch_functions.cc +M +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/malloc_extension_test/malloc_extension_test.vcproj +M vsprojects/malloc_hook_test/malloc_hook_test.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit e10b720797359e1855a5e4769424988b4e76c3e7 +Author: csilvers +Date: Sat Feb 4 00:06:48 2012 +0000 + + Last of the remnant empty directories that I don't know why they're + there. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@141 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit e55949bba69b7a6eede3468765e86c5ed000be52 +Author: csilvers +Date: Sat Feb 4 00:06:06 2012 +0000 + + This directory got renamed tmu-static a long time ago. Get rid of + this ancient remnant. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@140 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit 0f588815f979721346a6cb05a1cbd83d670b975a +Author: csilvers +Date: Sat Feb 4 00:05:39 2012 +0000 + + Apparently I'm not good at deleting files from svn after they're no + longer used anymore. Get rid of a few more that fall into this + category. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@139 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +D src/stacktrace_nacl-inl.h +D src/stacktrace_x86_64-inl.h + +commit 2b2016f6844a88b9448d445f90ad1c849a56ea23 +Author: csilvers +Date: Sat Feb 4 00:03:35 2012 +0000 + + I have no idea why I created this directory, but it's never been + used. Delete it. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@138 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit ace2da06732ee549b6d64c1f59b62181f5110230 +Author: csilvers +Date: Sat Feb 4 00:02:15 2012 +0000 + + This file has been obsolete for almost a year now; I just forgot to + delete it from svn. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@137 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +D src/base/atomicops-internals-arm-gcc.h + +commit 0afb078b34700859cef8d708463fc5c955e26c31 +Author: csilvers +Date: Tue Jan 31 19:11:26 2012 +0000 + + Tue Jan 31 10:43:50 2012 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@135 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M NEWS +M README_windows.txt +M configure +M configure.ac +M google-perftools.sln +M packages/deb/changelog +M packages/deb/copyright +M src/pprof +M src/system-alloc.cc +M src/tcmalloc.cc +M src/windows/config.h +M src/windows/mini_disassembler.h +M src/windows/patch_functions.cc +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_test.cc +M src/windows/shortproc.asm +A vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj + +commit e0eaf5981eede6311e311ac5054489b85015c5d7 +Author: csilvers +Date: Sat Jan 28 00:13:43 2012 +0000 + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@134 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS +M configure +M configure.ac +M doc/cpuprofile.html +M src/base/atomicops-internals-arm-v6plus.h +M src/base/linux_syscall_support.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/debugallocation.cc +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/sampler_test.cc +M src/thread_cache.cc +M src/windows/ia32_opcode_map.cc +M src/windows/mini_disassembler.cc +M src/windows/mini_disassembler.h +M src/windows/mini_disassembler_types.h +M src/windows/patch_functions.cc +M src/windows/preamble_patcher.cc +M src/windows/preamble_patcher.h +A src/windows/preamble_patcher_test.cc +M src/windows/preamble_patcher_with_stub.cc +A src/windows/shortproc.asm + +commit 4fa02db374683d3c69c1b36158534c011513ed31 +Author: csilvers +Date: Sat Dec 24 01:00:32 2011 +0000 + + Ready to release perftools 1.9.1 :-/ + + Added the ARM stacktrace file to the tarball (for 'make dist') + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@132 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M NEWS +M configure +M configure.ac + +commit 2a7b3b88371c2f78ab31be202f384fd0ed466890 +Author: csilvers +Date: Fri Dec 23 00:45:49 2011 +0000 + + Thu Dec 22 16:22:45 2011 Google Inc. + + * google-perftools: version 1.9 release + * Lightweight check for double-frees (blount) + * BUGFIX: Fix pprof to exit properly if run with no args + (dagitses) + * Suggest ASan as a way to diagnose buggy code (ppluzhnikov) + * Get rid of unused CACHELINE_SIZE (csilvers) + * Replace atexit() calls with global dtors; helps freebsd + (csilvers) + * Disable heap-checker under AddressSanitizer (kcc) + * Fix bug in powerpc stacktracing (ppluzhnikov) + * PERF: Use exponential backoff waiting for spinlocks (m3b) + * Fix 64-bit nm on 32-bit binaries in pprof (csilvers) + * Add ProfileHandlerDisallowForever (rsc) + * BUGFIX: Shell escape when forking in pprof (csilvers) + * No longer combine overloaded functions in pprof (csilvers) + * Fix address-normalizing bug in pprof (csilvers) + * More consistently call abort() instead of exit() on failure + (csilvers) + * Allow NoGlobalLeaks to be safely called more than once + (csilvers) + * PORTING/BUGFIX: Fix ARM cycleclock to use volatile asm + (dougkwan) + * PORTING: 64-bit atomic ops for ARMv7 (dougkwan) + * PORTING: Implement stacktrace for ARM (dougkwan) + * PORTING: Fix malloc_hook_mmap_linux for ARM (dougkwan) + * PORTING: Update linux_syscall_support.h for ARM/etc + (evannier, sanek) + * PORTING: Fix freebsd to work on x86_64 (chapp...@gmail.com) + * PORTING: Added additional SYS_mmap fixes for FreeBSD + (chappedm) + * PORTING: Allow us to compile on OS X 10.6 and run on 10.5 + (raltherr) + * PORTING: Check for mingw compilers that *do* define timespec + * PORTING: Add "support" for MIPS cycletimer + * PORTING: Fix fallback cycle-timer to work with Now + (dougkwan) + * PERF: Move stack trace collecting out of the mutex (taylorc) + * PERF: Get the deallocation stack trace outside the mutex + (sean) + * Make PageHeap dynamically allocated for leak checks (maxim) + * BUGFIX: Fix probing of nm -f behavior in pprof (dpeng) + * BUGFIX: Fix a race with the CentralFreeList lock before main + (sanjay) + * Support /pprof/censusprofile url arguments (rajatjain) + * Change IgnoreObject to return its argument (nlewycky) + * Update malloc-hook files to support more CPUs + * BUGFIX: write our own strstr to avoid libc problems + (csilvers) + * Use simple callgrind compression facility in pprof + * Print an error message when we can't run pprof to symbolize + (csilvers) + * Die in configure when g++ is't installed (csilvers) + * DOC: Beef up the documentation a bit about using libunwind + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@130 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M NEWS +M configure +M configure.ac +M packages/deb/changelog +M src/pprof +M src/windows/config.h + +commit 75f5a791bc1c0af0ddf43453c18f44723884f37e +Author: csilvers +Date: Fri Dec 23 00:45:14 2011 +0000 + + Add the magical incantations to get perftools to compile + cleanly under windows. The only non-trivial one is the #undef + of small, which I needed to compile under the latest cygwin -- + I ran g++ with -dD under cygwin and saw the '#define small + char' with my own eyes. I wouldn't have thought it... + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@129 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/internal_logging.h +M src/tcmalloc.cc +M src/windows/port.h + +commit 76131b04cf41a7f0fed99503f985847fc261b930 +Author: csilvers +Date: Fri Dec 23 00:44:53 2011 +0000 + + In my testing for a new release, I was noticing hangs on + cygwin, that went away when I turned off tls support. Since I + didn't use to have such problems, I am being conservative and + only turning off TLS for the particular version of cygwin I'm + testing on (as returned by uname()). + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@128 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/thread_cache.cc + +commit 3d30fbcc85021b267f7e3faf4c2280d70681920c +Author: csilvers +Date: Fri Dec 23 00:44:30 2011 +0000 + + We use mmx instructions now in perftools, so specify -xmms for + gcc on i386, where it's not on by default (it is for + gcc/x86_64, in my tests). This could potentially cause an + error for embedded systems, which can have i386 but no mms, + but the code wouldn't run properly on them anyway without + tweaks. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@127 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in + +commit f622d261e9a4331724d222cc2a41b517607c07d7 +Author: csilvers +Date: Tue Dec 20 18:43:38 2011 +0000 + + * Fix ARM cycleclock to use volatile asm (dougkwan) + * BUGFIX: Define BASE_HAS_ATOMIC64 for ARMv7 (dougkwan) + * Fix fallback cycle-timer to work with Now (dougkwan) + * Fix pprof to exit properly if run with no args (dagitses) + * Suggest ASan as a way to diagnose buggy code (ppluzhnikov) + * Get rid of unused CACHELINE_SIZE (csilvers) + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@126 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-v6plus.h +M src/base/basictypes.h +M src/base/cycleclock.h +M src/debugallocation.cc +M src/malloc_hook_mmap_freebsd.h +M src/pprof +M src/windows/port.h + +commit 7da02003014644f73893df8530ee788dc0e626de +Author: chappedm@gmail.com + +Date: Wed Nov 30 02:54:35 2011 +0000 + + Added additional SYS_mmap fixes for FreeBSD due to syscall differences + between os versions (pulled from differences between FreeBSD6 and + FreeBSD8 mmap implementations) + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@125 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/malloc_hook_mmap_freebsd.h + +commit 8c8329390cd05a1bf1bf9613712521a9ee9fe260 +Author: csilvers +Date: Tue Nov 22 01:06:33 2011 +0000 + + * Eliminate some TSAN warnings (wilsonh) + * Better fix for freebsd on x86_64 (chapp...@gmail.com) + * Lightweight check for double-frees (blount) + * 64-bit atomic ops for ARMv7 (dougkwan) + * Remove dynamic annotations in some cases (dvyukov) + * Update linux_syscall_support.h for ARM, etc (evannier) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@124 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-v6plus.h +M src/base/dynamic_annotations.c +M src/malloc_hook_mmap_freebsd.h +M src/profile-handler.cc +M src/thread_cache.h + +commit ca23f57679e2bd4e0390d6891aa765b7e9daca22 +Author: csilvers +Date: Thu Nov 17 00:11:42 2011 +0000 + + Fix bad #include paths. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@123 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/stacktrace.cc +M src/stacktrace_config.h + +commit e580d7888154fa7f95b3cef9e18f1ce69182212b +Author: csilvers +Date: Wed Nov 16 21:20:45 2011 +0000 + + Some linux_syscall_support.h improvements: + + * Fix socketcall functions (mec) + * Add ARM related defs and syscall asembly code (sanek) + * Use __arm__ instead of particular ARM arch macro (dougkwan) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@122 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/linux_syscall_support.h + +commit 6c3eaabd7306173b6b71b63797ebf050675046cf +Author: csilvers +Date: Wed Nov 16 05:21:54 2011 +0000 + + * Check for mingw compilers that *do* define timespec + * Replace atexit() calls with global dtors; helps freebsd + (csilvers) + * Fix malloc_hook_mmap_linux for ARM (dougkwan) + * Disalbe heap-checker under AddressSanitizer (kcc) + * Fix bug in powerpc stacktracing (ppluzhnikov) + * Use exponential backoff waiting for spinlocks (m3b) + * Fix 64-bit nm on 32-bit binaries in pprof (csilvers) + * Implement stacktrace for ARM (dougkwan) + * Add ProfileHandlerDisallowForever (rsc) + * Shell escape when forking in pprof (csilvers) + * Fix freebsd to work on x86_64 (chapp...@gmail.com) + * No longer combine overloaded functions in pprof (csilvers) + * Fix address-normalizing bug in pprof (csilvers) + * More consistently call abort() instead of exit() on failure + (csilvers) + * Allow NoGlobalLeaks to be safely called more than once + (csilvers) + * Beef up the documentation a bit about using libunwind + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@121 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.am +M Makefile.in +M src/base/googleinit.h +M src/base/linux_syscall_support.h +M src/base/logging.h +M src/base/spinlock_internal.cc +M src/base/spinlock_linux-inl.h +M src/base/spinlock_posix-inl.h +M src/base/spinlock_win32-inl.h +M src/debugallocation.cc +M src/google/heap-checker.h +M src/heap-checker.cc +M src/malloc_hook_mmap_freebsd.h +M src/malloc_hook_mmap_linux.h +M src/pprof +M src/profile-handler.cc +M src/profile-handler.h +M src/stacktrace.cc +C059 src/stacktrace_powerpc-inl.h src/stacktrace_arm-inl.h +M src/stacktrace_config.h +M src/stacktrace_powerpc-inl.h +M src/stacktrace_x86-inl.h +M src/tests/heap-checker_unittest.cc +M src/tests/profile-handler_unittest.cc + +commit a6076edd177d59e67207753b799ce047a3663cb0 +Author: csilvers +Date: Tue Oct 18 20:57:45 2011 +0000 + + * Get the deallocation stack trace outside the lock (sean) + * Make PageHeap dynamically allocated for leak checks (maxim) + * BUGFIX: Fix probing of nm -f behavior in pprof (dpeng) + * PORTING: Add "support" for MIPS cycletimer + * BUGFIX: Fix a race with the CentralFreeList lock (sanjay) + * Allow us to compile on OS X 10.6 and run on 10.5 (raltherr) + * Support /pprof/censusprofile url arguments (rajatjain) + * Die in configure when g++ is't installed (csilvers) + * Change IgnoreObject to return its argument (nlewycky) + * Update malloc-hook files to support more CPUs + * Move stack trace collecting out of the mutex (taylorc) + * BUGFIX: write our own strstr to avoid libc problems + (csilvers) + * use simple callgrind compression facility in pprof + * print an error message when we can't run pprof to symbolize + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@120 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.am +M Makefile.in +M configure +M configure.ac +M packages/rpm.sh +M src/base/basictypes.h +M src/base/cycleclock.h +M src/base/dynamic_annotations.h +M src/base/spinlock_internal.cc +M src/base/spinlock_linux-inl.h +M src/central_freelist.cc +M src/central_freelist.h +M src/common.cc +M src/common.h +M src/debugallocation.cc +M src/google/heap-checker.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/libc_override_osx.h +M src/malloc_hook.cc +M src/malloc_hook_mmap_linux.h +M src/memfs_malloc.cc +M src/page_heap.cc +M src/page_heap.h +M src/page_heap_allocator.h +M src/pprof +M src/profile-handler.cc +M src/profiler.cc +M src/span.cc +M src/span.h +M src/stack_trace_table.cc +M src/stacktrace.cc +M src/stacktrace_config.h +M src/static_vars.cc +M src/static_vars.h +M src/symbolize.cc +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/config.h + +commit c2eedce2a718913ed6264ac8e96571c233761e3b +Author: csilvers +Date: Fri Aug 26 21:08:59 2011 +0000 + + Fri Aug 26 13:29:25 2011 Google Inc. + + * google-perftools: version 1.8.3 release + * Added back the 'pthreads unsafe early' #define, needed + for FreeBSD + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@117 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M NEWS +M configure +M configure.ac +M src/config.h.in +M src/pprof +M src/windows/config.h + +commit f633b40ba5d3785c7e31fd9b575c5cf5e7c174f3 +Author: csilvers +Date: Thu Aug 11 22:06:22 2011 +0000 + + Thu Aug 11 15:01:47 2011 Google Inc. + + * google-perftools: version 1.8.2 release + * Fixed calculation of patchlevel, 'make check' should all + pass again + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@115 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M NEWS +M configure +M configure.ac +M src/pprof +M src/windows/config.h + +commit ffcdf7bf5a7e97428f7521b3c9e6d854e3a424a9 +Author: csilvers +Date: Thu Aug 11 22:05:09 2011 +0000 + + Fix #includes for ARM. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@114 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-arm-generic.h + +commit d2faf4646dc79486babfbd63cf5f658b917dd6ab +Author: csilvers +Date: Wed Jul 27 04:18:01 2011 +0000 + + Tue Jul 26 20:57:51 2011 Google Inc. + + * google-perftools: version 1.8 release + * Added an #include to fix compile breakage on latest gcc's + * Removed an extra , in the configure.ac script + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@112 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M NEWS +M configure +M configure.ac +M src/base/elf_mem_image.cc +M src/config.h.in +M src/pprof +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h + +commit 100c38c1a225446c1bbeeaac117902d0fbebfefe +Author: csilvers +Date: Sat Jul 16 01:07:10 2011 +0000 + + Fri Jul 15 16:10:51 2011 Google Inc. + + * google-perftools: version 1.8 release + * PORTING: (Disabled) support for patching mmap on freebsd + (chapp...) + * PORTING: Support volatile __malloc_hook for glibc 2.14 + (csilvers) + * PORTING: Use _asm rdtsc and __rdtsc to get cycleclock in + windows (koda) + * PORTING: Fix fd vs. HANDLE compiler error on cygwin + (csilvers) + * PORTING: Do not test memalign or double-linking on OS X + (csilvers) + * PORTING: Actually enable TLS on windows (jontra) + * PORTING: Some work to compile under Native Client (krasin) + * PORTING: deal with pthread_once w/o -pthread on freebsd + (csilvers) + * Rearrange libc-overriding to make it easier to port + (csilvers) + * Display source locations in pprof disassembly (sanjay) + * BUGFIX: Actually initialize allocator name (mec) + * BUGFIX: Keep track of 'overhead' bytes in malloc reporting + (csilvers) + * Allow ignoring one object twice in the leak checker (glider) + * BUGFIX: top10 in pprof should print 10 lines, not 11 (rsc) + * Refactor vdso source files (tipp) + * Some documentation cleanups + * Document MAX_TOTAL_THREAD_CACHE_SIZE <= 1Gb (nsethi) + * Add MallocExtension::GetOwnership(ptr) (csilvers) + * BUGFIX: We were leaving out a needed $(top_srcdir) in + the Makefile + * PORTING: Support getting argv0 on OS X + * Add 'weblist' command to pprof: like 'list' but html + (sanjay) + * Improve source listing in pprof (sanjay) + * Cap cache sizes to reduce fragmentation (ruemmler) + * Improve performance by capping or increasing sizes + (ruemmler) + * Add M{,un}mapReplacmenet hooks into MallocHook (ribrdb) + * Refactored system allocator logic (gangren) + * Include cleanups (csilvers) + * Add TCMALLOC_SMALL_BUT_SLOW support (ruemmler) + * Clarify that tcmalloc stats are MiB (robinson) + * Remove support for non-tcmalloc debugallocation (blount) + * Add a new test: malloc_hook_test (csilvers) + * Change the configure script to be more crosstool-friendly + (mcgrathr) + * PORTING: leading-underscore changes to support win64 + (csilvers) + * Improve debugallocation tc_malloc_size (csilvers) + * Extend atomicops.h and cyceclock to use ARM V6+ optimized + code (sanek) + * Change malloc-hook to use a list-like structure (llib) + * Add flag to use MAP_PRIVATE in memfs_malloc (gangren) + * Windows support for pprof: nul and /usr/bin/file (csilvers) + * TESTING: add test on strdup to tcmalloc_test (csilvers) + * Augment heap-checker to deal with no-inode maps (csilvers) + * Count .dll/.dylib as shared libs in heap-checker (csilvers) + * Disable sys_futex for arm; it's not always reliable (sanek) + * PORTING: change lots of windows/port.h macros to functions + * BUGFIX: Generate correct version# in tcmalloc.h on windows + (csilvers) + * PORTING: Some casting to make solaris happier about types + (csilvers) + * TESTING: Disable debugallocation_test in 'minimal' mode + (csilvers) + * Rewrite debugallocation to be more modular (csilvers) + * Don't try to run the heap-checker under valgrind + (ppluzhnikov) + * BUGFIX: Make focused stat %'s relative, not absolute + (sanjay) + * BUGFIX: Don't use '//' comments in a C file (csilvers) + * Quiet new-gcc compiler warnings via -Wno-unused-result, + etc (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@110 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M NEWS +M README +M configure +M configure.ac +M doc/heapprofile.html +M doc/tcmalloc.html +M google-perftools.sln +M packages/deb/changelog +M src/base/atomicops-internals-windows.h +M src/base/atomicops.h +M src/base/cycleclock.h +C067 src/base/vdso_support.cc src/base/elf_mem_image.cc +A src/base/elf_mem_image.h +M src/base/low_level_alloc.cc +M src/base/spinlock_internal.cc +M src/base/vdso_support.cc +M src/base/vdso_support.h +M src/central_freelist.cc +M src/central_freelist.h +M src/common.cc +M src/common.h +M src/config.h.in +M src/debugallocation.cc +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/malloc_hook.h +M src/heap-checker.cc +A src/libc_override.h +A src/libc_override_gcc_and_weak.h +A src/libc_override_glibc.h +A src/libc_override_osx.h +A src/libc_override_redefine.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +A src/malloc_hook_mmap_freebsd.h +A src/malloc_hook_mmap_linux.h +M src/maybe_threads.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/pprof +M src/profile-handler.cc +M src/profiler.cc +M src/stack_trace_table.h +M src/stacktrace.cc +M src/stacktrace_config.h +C053 src/stack_trace_table.h src/stacktrace_nacl-inl.h +M src/symbolize.cc +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/debugallocation_test.cc +M src/tests/malloc_extension_c_test.c +M src/tests/malloc_extension_test.cc +M src/tests/malloc_hook_test.cc +M src/tests/profiler_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc +M src/windows/config.h +M src/windows/google/tcmalloc.h.in +M src/windows/mingw.h +M src/windows/port.cc +M src/windows/port.h +M +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcproj +M vsprojects/malloc_hook_test/malloc_hook_test.vcproj + +commit 8c7d2289d24f7a49f1f6f60d4a6eaee06fa04c60 +Author: csilvers +Date: Thu May 19 21:37:12 2011 +0000 + + * Fix typos in comment in profiler.h (nrhodes) + * #include fixes (jyrki) + * Add missing stddef.h for ptrdiff_t (mec) + * Add M{,un}mapReplacement hooks into MallocHook (ribrdb) + * Force big alloc in frag test (ruemmler) + * PERF: Increase the size class cache to 64K entries + (ruemmler) + * PERF: Increase the transfer cache by 16x (ruemmler) + * Use windows intrinsic to get the tsc (csilvers) + * Rename atomicops-internals-x86-msvc.h->windows.h (csilvers) + * Remove flaky DEATH test in malloc_hook_test (ppluzhnikov) + * Expose internal ReadStackTraces()/etc (lantran) + * Refactored system allocator logic (gangren) + * Include-what-you-use: cleanup tcmalloc #includes (csilvers) + * Don't set kAddressBits to 48 on 32-bit systems (csilvers) + * Add declaration for __rdtsc() for windows (koda) + * Don't revert to system alloc for expected errors (gangren) + * Add TCMALLOC_SMALL_BUT_SLOW support (ruemmler) + * Clarify that tcmalloc stats are MiB (robinson) + * Avoid setting cpuinfo_cycles_per_second to 0 (koda) + * Fix frag_unittest memory calculations (ruemmler) + * Remove support for non-tcmalloc debugallocation (blount) + * Add malloc_hook_test (llib) + * Change the objcopy -W test to be cross-friendly (mcgrathr) + * Export __tcmalloc in addition to _tcmalloc, for 86_64 + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@109 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M Makefile.am +M Makefile.in +M README +M README_windows.txt +M configure +M configure.ac +M google-perftools.sln +R096 src/base/atomicops-internals-x86-msvc.h +src/base/atomicops-internals-windows.h +M src/base/atomicops.h +M src/base/cycleclock.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/vdso_support.h +M src/central_freelist.cc +M src/central_freelist.h +M src/common.cc +M src/common.h +M src/config.h.in +M src/debugallocation.cc +M src/google/malloc_extension.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/tcmalloc.h.in +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/packed-cache-inl.h +M src/page_heap.cc +M src/page_heap.h +M src/page_heap_allocator.h +M src/pagemap.h +M src/sampler.cc +M src/sampler.h +M src/span.cc +M src/stack_trace_table.cc +M src/stack_trace_table.h +M src/static_vars.cc +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/frag_unittest.cc +M src/tests/heap-checker_unittest.cc +A src/tests/malloc_hook_test.cc +M src/tests/memalign_unittest.cc +M src/tests/page_heap_test.cc +M src/tests/realloc_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_large_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/patch_functions.cc +M src/windows/port.cc +A vsprojects/malloc_hook_test/malloc_hook_test.vcproj + +commit 1d30e525ae6ac38ae381bb3118f7f47998af2942 +Author: csilvers +Date: Mon Mar 21 21:41:55 2011 +0000 + + * Improve debugallocation tc_malloc_size (csilvers) + * Extend atomicops.h to use ARM V6+ optimized code (sanek) + * Fix failure in Ranges test (ppluzhnikov) + * Change malloc-hook to use a list-like structure (llib) + * Update tcmalloc_regtest to use new malloc hooks (llib) + * PARTIAL: Keep track of 'overhead' bytes in the page cache + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@108 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M google-perftools.sln +A src/base/atomicops-internals-arm-generic.h +A src/base/atomicops-internals-arm-v6plus.h +M src/base/atomicops.h +M src/central_freelist.cc +M src/central_freelist.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/heap-checker-bcad.cc +M src/heap-checker.cc +M src/heap-profiler.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/tcmalloc.cc +A src/tests/current_allocated_bytes_test.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/malloc_extension_c_test.c +M src/tests/tcmalloc_unittest.cc +A +vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcproj + +commit 6fe07cd2c0527e18276cc79a57e2212a4b048746 +Author: csilvers +Date: Fri Mar 4 23:52:33 2011 +0000 + + * add a flag to use MAP_PRIVATE in memfs_malloc (gangren) + * pthread_self() is now safe to use early (ppluzhnikov) + * windows support for pprof: nul and /usr/bin/file (csilvers) + * fix tc_malloc_size for debugallocation (csilvers) + * add test on strdup to tcmalloc_test (csilvers) + * augment heap-checker to deal with no-inode maps (csilvers) + * Get rid of -Wno-unused-result: not all gcc's support it + (csilvers) + * /bin/true -> ':', which is faster and more portable + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@107 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M doc/tcmalloc.html +M src/debugallocation.cc +M src/heap-checker.cc +M src/memfs_malloc.cc +M src/pprof +M src/tcmalloc.cc +M src/tests/debugallocation_test.sh +M src/tests/memalign_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc + +commit 75584139e40c9d6c952d9c5339c52e5b58302fc8 +Author: csilvers +Date: Wed Mar 2 08:10:05 2011 +0000 + + * Enhance cycleclock on ARM v6 and above (sanek) + * Reduce object copying by using a reference (nherring) + * Modified lock annotations a bit (lcwu) + * Make debugallocation test a bit more forgiving (csilvers) + * Count .dll/.dylib as shared libs in heapchecker (csilvers) + * Disable sys_futex for arm (sanek) + * Don't use macros as much in windows/port.h (andrey.s...) + * Update #includes in case malloc.h is in weird places + (csilvers) + * Turn off some not-so-useful warnings in gcc 4 (csilvers) + * Do some casting to make solaris happier about types + (csilvers) + * Disable debugallocation_test in 'minimal' mode (csilvers) + * Rewrite debugallocation to be more modular (csilvers) + * We can't run the heap-checker under valgrind (ppluzhnikov) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@106 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M configure +M configure.ac +C055 src/raw_printer.cc src/base/arm_instruction_set_select.h +M src/base/cycleclock.h +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/spinlock_linux-inl.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/config.h.in +M src/debugallocation.cc +M src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/internal_logging.cc +M src/raw_printer.cc +M src/tcmalloc.cc +M src/tests/debugallocation_test.cc +M src/tests/heap-checker_unittest.cc +M src/tests/memalign_unittest.cc +M src/tests/sampler_test.cc +M src/windows/config.h +R094 src/windows/google/tcmalloc.h src/windows/google/tcmalloc.h.in +M src/windows/port.cc +M src/windows/port.h + +commit c1abbfae802af5bf949c78e0bfdfd58d5c669a86 +Author: csilvers +Date: Sat Feb 19 00:11:09 2011 +0000 + + * avoid unused-var warnings with annotalysis (lcwu) + * make focused stats %'s relative, not absolute (sanjay) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@105 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/dynamic_annotations.h +M src/pprof + +commit dd3d9d969e9b889e96c2af497e436856fac1a2a7 +Author: csilvers +Date: Tue Feb 8 01:03:37 2011 +0000 + + * Fix tcmalloc_unittest on MSVC 10 in release mode (csilvers) + * Fix malloc_hook_c.h to compile with -ansi under gcc + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@104 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS +M src/google/malloc_hook_c.h +M src/tests/tcmalloc_unittest.cc + +commit 7375b4f3cb3ab4471d0016017be5e18ba5451c5f +Author: csilvers +Date: Sat Feb 5 00:19:37 2011 +0000 + + Fri Feb 04 15:54:31 2011 Google Inc. + + * google-perftools: version 1.7 release + * Reduce page map key size under x86_64 by 4.4MB (rus) + * Remove a flaky malloc-extension test (fdabek) + * Improve the performance of PageHeap::New (ond..., csilvers) + * Improve sampling_test with no-inline additions/etc (fdabek) + * 16-byte align debug allocs (jyasskin) + * Change FillProcSelfMaps to detect out-of-buffer-space + (csilvers) + * Document the need for sampling to use GetHeapSample + (csilvers) + * Try to read TSC frequency from tsc_freq_khs (adurbin) + * Do better at figuring out if tests are running under gdb + (ppluzhnikov) + * Improve spinlock contention performance (ruemmler) + * Better internal-function list for pprof's /contention + (ruemmler) + * Speed up GoogleOnce (m3b) + * Limit number of incoming/outgoing edges in pprof (sanjay) + * Add pprof --evince to go along with --gv (csilvers) + * Document the various ways to get heap-profiling information + (csilvers) + * Separate out synchronization profiling routines (ruemmler) + * Improve malloc-stats output to be more understandable + (csilvers) + * Add support for census profiler in pporf (nabeelmian) + * Document how pprof's /symbol must support GET requests + (csilvers) + * Improve acx_pthread.m4 (ssuomi, liujisi) + * Speed up pprof's ExtractSymbols (csilvers) + * Ignore some known-leaky (java) libraries in the heap checker + (davidyu) + * Make kHideMask use all 64 bits in tests (ppluzhnikov) + * Clean up pprof input-file handling (csilvers) + * BUGFIX: Don't crash if __environ is NULL (csilvers) + * BUGFIX: Fix totally broken debugallocation tests (csilvers) + * BUGFIX: Fix up fake_VDSO handling for unittest (ppluzhnikov) + * BUGFIX: Suppress all large allocs when report threshold is 0 + (lexie) + * BUGFIX: mmap2 on i386 takes an off_t, not off64_t (csilvers) + * PORTING: Add missing PERFTOOLS_DLL_DECL (csilvers) + * PORTING: Add stddef.h to make newer gcc's happy (csilvers) + * PORTING: Document some tricks for working under OS X + (csilvers) + * PORTING: Don't try to check valgrind for windows (csilvers) + * PORTING: Make array-size a var to compile under clang + (chandlerc) + * PORTING: No longer hook _aligned_malloc and _aligned_free + (csilvers) + * PORTING: Quiet some gcc warnings (csilvers) + * PORTING: Replace %PRIxPTR with %p to be more portable + (csilvers) + * PORTING: Support systems that capitalize /proc weirdly + (sanek) + * PORTING: Treat arm3 the same as arm5t in cycletimer + (csilvers) + * PORTING: Update windows logging to not allocate memory + (csilvers) + * PORTING: avoid double-patching newer windows DLLs + (roger.orr) + * PORTING: get dynamic_annotations.c to work on windows + (csilvers) + * Add pkg-config .pc files for the 5 libraries we produce + (csilvers) + * Added proper libtool versioning, so this lib will be 0.1.0 + (csilvers) + * Moved from autoconf 2.64 to 2.65 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@102 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M NEWS +M README +M configure +M configure.ac +M m4/acx_pthread.m4 +M packages/deb/changelog +M src/base/cycleclock.h +M src/base/dynamic_annotations.c +M src/base/logging.h +M src/base/stl_allocator.h +M src/base/vdso_support.cc +M src/debugallocation.cc +M src/heap-checker.cc +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/symbolize.h +M src/system-alloc.cc +M src/tests/debugallocation_test.cc +M src/tests/debugallocation_test.sh +M src/tests/malloc_extension_test.cc +M src/windows/port.h + +commit 3d77cbf7d569a7c7f0ce39a83f6c98da1718f1c4 +Author: csilvers +Date: Wed Jan 19 21:37:15 2011 +0000 + + * Make kHideMask use all 64 bits (ppluzhnikov) + * Add new IsDebuggerAttached method (ppluzhnikov) + * Document some tricks for maybe getting perftools to work + on OS X + * Redo file-top pprof commands (csilvers) + * Clean up pprof input-file handling (csilvers) + * 16-byte align debug allocs (jyasskin) + * Ignore JVM memory leakage in the heap checker (davidyu, + kkurimoto) + * Better internal-function list for contentionz (ruemmler) + * mmap2 on i386 takes an off_t, not an off64_t (csilvers) + * Fix up fake-VDSO handling for unittest (ppluzhnikov) + * Don't try to check valgrind for windows (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@101 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M README +M src/base/dynamic_annotations.c +M src/base/linux_syscall_support.h +M src/base/vdso_support.cc +M src/base/vdso_support.h +M src/debugallocation.cc +M src/heap-checker.cc +M src/malloc_hook.cc +M src/pprof +M src/tcmalloc.cc +M src/tests/heap-checker_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h + +commit a0a2ff3b493481ff52e4b4deec2fcc494756b64a +Author: csilvers +Date: Wed Nov 24 00:33:20 2010 +0000 + + * PORTING: Add PERFTOOLS_DLL_DECL to malloc_hook_c.h + (csilvers) + * Add new .h files to Makefile (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@100 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M src/google/malloc_hook_c.h + +commit 3014cf142e5a2409c88ab4559f3274434ed9a29b +Author: csilvers +Date: Thu Nov 18 01:07:25 2010 +0000 + + * Suppress all large allocs when report threshold==0 + * Clarified meaning of various malloc stats + * Change from ATTRIBUTED_DEPRECATED to comments + * Make array-size a var to compile under clang + * Reduce page map key size under x86_64 by 4.4MB + * Added full qualification to MemoryBarrier + * Support systems that capitalize /proc weirdly + * Avoid gcc warning: exporting type in unnamed ns + * Add some dynamic annotations for gcc attributes + * Add support for census profiler in pprof + * Speed up pprof's ExtractSymbols + * Speed up GoogleOnce + * Add pkg-config (.pc) files + * Detect when __environ exists but is NULL + * Improve spinlock contention performance + * Add GetFreeListSizes + * Improve sampling_test, eg by adding no-inline + * Relax malloc_extension test-check for big pages + * Add proper library version number information + * Update from autoconf 2.64 to 2.65 + * Better document how to write a server that works with pprof + * Change FillProcSelfMaps to better handle out-of-space + * No longer hook _aligned_malloc/free in windows + * Handle function-forwarding in DLLs when patching (in + windows) + * Update .vcproj files that had wrong .cc files in them (!) + * get rid of unnecessary 'size < 0' + * fix comments a bit in sysinfo.cc + * another go at improving malloc-stats output + * fix comment typo in profiler.cc + * Add a few more thread annotations + * Try to read TSC frequency from 'tsc_freq_khz' + * Fix annotalysis/TSAN incompatibility + * Add pprof --evince to go along with --gv + * Document need for sampling to use GetHeapSample + * Fix flakiness in malloc_extension_test + * Separate out synchronization profiling routines + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@99 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M NEWS +M README +M aclocal.m4 +M configure +M configure.ac +M doc/pprof_remote_servers.html +M ltmain.sh +A m4/libtool.m4 +A m4/ltoptions.m4 +A m4/ltsugar.m4 +A m4/ltversion.m4 +A m4/lt~obsolete.m4 +M packages/deb/libgoogle-perftools-dev.dirs +M packages/deb/libgoogle-perftools-dev.install +M packages/rpm/rpm.spec +A src/base/atomicops-internals-arm-gcc.h +M src/base/basictypes.h +M src/base/dynamic_annotations.h +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/spinlock.cc +M src/base/spinlock.h +A src/base/spinlock_internal.cc +C057 src/base/spinlock_win32-inl.h src/base/spinlock_internal.h +M src/base/spinlock_linux-inl.h +M src/base/spinlock_posix-inl.h +M src/base/spinlock_win32-inl.h +C067 src/base/spinlock_win32-inl.h +src/base/synchronization_profiling.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/thread_annotations.h +M src/base/vdso_support.cc +M src/common.h +M src/config.h.in +M src/debugallocation.cc +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/heap-profile-table.cc +M src/malloc_extension.cc +M src/memory_region_map.cc +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/profiler.cc +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/debugallocation_test.cc +M src/tests/malloc_extension_test.cc +M src/tests/sampling_test.cc +M src/tests/sampling_test.sh +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/packed-cache_test/packed-cache_test.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 682ff7da1205398376ee725b4ce3219c107b3f8a +Author: csilvers +Date: Thu Aug 5 20:36:47 2010 +0000 + + Thu Aug 5 12:48:03 PDT 2010 + + * google-perftools: version 1.6 release + * Add tc_malloc_usable_size for compatibility with glibc + (csilvers) + * Override malloc_usable_size with tc_malloc_usable_size + (csilvers) + * Default to no automatic heap sampling in tcmalloc (csilvers) + * Add -DTCMALLOC_LARGE_PAGES, a possibly faster tcmalloc (rus) + * Make some functions extern "C" to avoid false ODR warnings + (jyasskin) + * pprof: Add SVG-based output (rsc) + * pprof: Extend pprof --tools to allow per-tool configs + (csilvers) + * pprof: Improve support of 64-bit and big-endian profiles + (csilvers) + * pprof: Add interactive callgrind suport (weidenri...) + * pprof: Improve address->function mapping a bit (dpeng) + * Better detection of when we're running under valgrind + (csilvers) + * Better CPU-speed detection under valgrind (saito) + * Use, and recommend, -fno-builtin-malloc when compiling + (csilvers) + * Avoid false-sharing of memory between caches (bmaurer) + * BUGFIX: Fix heap sampling to use correct alloc size (bmauer) + * BUGFIX: Avoid gcc 4.0.x bug by making hook-clearing atomic + (csilvers) + * BUGFIX: Avoid gcc 4.5.x optimization bug (csilvers) + * BUGFIX: Work around deps-determining bug in libtool 1.5.26 + (csilvers) + * BUGFIX: Fixed test to use HAVE_PTHREAD, not HAVE_PTHREADS + (csilvers) + * BUGFIX: Fix tls callback behavior on windows when using wpo + (wtc) + * BUGFIX: properly align allocation sizes on Windows (antonm) + * BUGFIX: Fix prototypes for tcmalloc/debugalloc wrt throw() + (csilvers) + * DOC: Updated heap-checker doc to match reality better + (fischman) + * DOC: Document ProfilerFlush, ProfilerStartWithOptions + (csilvers) + * DOC: Update docs for heap-profiler functions (csilvers) + * DOC: Clean up documentation around tcmalloc.slack_bytes + (fikes) + * DOC: Renamed README.windows to README_windows.txt (csilvers) + * DOC: Update the NEWS file to be non-empty (csilvers) + * PORTING: Fix windows addr2line and nm with proper rc code + (csilvers) + * PORTING: Add CycleClock and atomicops support for arm 5 + (sanek) + * PORTING: Improve PC finding on cygwin and redhat 7 + (csilvers) + * PORTING: speed up function-patching under windows (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@97 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M NEWS +M README +M configure +M configure.ac +M doc/heap_checker.html +M m4/pc_from_ucontext.m4 +M packages/deb/changelog +M src/base/atomicops.h +M src/base/cycleclock.h +M src/base/dynamic_annotations.c +M src/base/dynamic_annotations.h +M src/base/sysinfo.cc +M src/base/thread_annotations.h +M src/base/vdso_support.h +M src/common.cc +M src/common.h +M src/google/malloc_extension.h +M src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/heap-profiler.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/pprof +M src/stacktrace_x86-inl.h +M src/tcmalloc.cc +M src/tests/sampler_test.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/google/tcmalloc.h +M src/windows/port.cc +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 488eee994d571da216ef105d4144282c801f0eee +Author: csilvers +Date: Wed Jun 23 16:42:31 2010 +0000 + + Oops, I thought I had done this last time, but maybe not. Submit the + name change. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@96 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +R092 README.windows README_windows.txt + +commit cb7393cbe2d737009001fd9d30dad568bac7a3d8 +Author: csilvers +Date: Mon Jun 21 15:59:56 2010 +0000 + + * Default to not sampling in tcmalloc (csilvers) + * Add -DTCMALLOC_LARGE_PAGES: better perf for some workloads + (rus) + * Extend pprof --tools to allow per-tool configs (csilvers) + * Have STL_Allocator pass on # bytes to free (richardfang) + * Add a header guard to config.h (csilvers) + * DOC: Clean up documentation around tcmalloc.slack_bytes + (fikes) + * DOC: Document ProfilerFlush, ProfilerStartWithOptions + (csilvers) + * PORTING: Work around a gcc 4.5.0 optimization bug (csilvers) + * PORTING: Use -fno-builtin-malloc and friends when compiling + tcmalloc + * PORTING: Define _WIN32_WINNT high enough for mingw + (csilvers) + * PORTING: Work around libtool bug getting deps wrong in + some cases + * Update README.windows to emphasize $IncludeDir more + (csilvers) + * Rename README.windows to README_windows.txt (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@95 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M README +M configure +M configure.ac +M doc/cpuprofile.html +M doc/tcmalloc.html +M src/base/dynamic_annotations.c +M src/base/dynamic_annotations.h +M src/base/stl_allocator.h +M src/central_freelist.cc +M src/common.h +M src/config.h.in +M src/google/malloc_extension.h +M src/heap-checker.cc +M src/internal_logging.h +M src/linked_list.h +M src/memory_region_map.h +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/sampler.cc +M src/span.h +M src/tcmalloc.cc +M src/tests/frag_unittest.cc +M src/tests/page_heap_test.cc +M src/tests/testutil.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/config.h +M src/windows/mingw.h + +commit d8c02761689ba909f474b85618f99ac6dfc9a168 +Author: csilvers +Date: Fri May 7 21:53:24 2010 +0000 + + * Update docs for heap-profiler fns (csilvers) + * In pprof, accept URLs without ports but with http:// (rsc) + * Refactor sizeclass handling in tcmalloc (bmaurer) + * Always log failed calls to FindAllocDetails (mec) + * Clarify comments for ProfilerStart* (malcolmr) + * Add #include guards to stacktrace_win32-inl.h (glider) + * Add ANNOTATE_ENABLE_RACE_DETECTION(enable) (kcc) + * Make a contentful NEWS file (csilvers) + * Fix addr2line --help (which pprof relies on) for windows + (csilvers) + * Fixes a bug in tcmalloc's TLS callback on windows -static + (wtc) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@94 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M NEWS +M doc/heapprofile.html +M packages/deb/control +M packages/rpm/rpm.spec +M src/base/dynamic_annotations.c +M src/base/dynamic_annotations.h +M src/base/vdso_support.cc +M src/central_freelist.cc +M src/common.h +M src/google/profiler.h +M src/heap-checker.cc +M src/internal_logging.h +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/span.h +M src/stacktrace_win32-inl.h +M src/tcmalloc.cc +M src/tests/page_heap_test.cc +M src/windows/addr2line-pdb.c +M src/windows/nm-pdb.c +M src/windows/port.cc + +commit b0fe220d503eb23830e622939c2e14f084392d1e +Author: csilvers +Date: Thu Apr 22 17:29:02 2010 +0000 + + * Fix pthread_once extern declarations (willchan) + * Add missing closing brace that resulted in compile failure + (willchan) + * Handle closed stdin/out/err properly when forking (glider) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@93 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/maybe_threads.cc +M src/profile-handler.cc +M src/symbolize.cc +M src/tcmalloc.cc + +commit 21c65ecb037d7d41dcd574c70cd7b7e9d5045462 +Author: csilvers +Date: Mon Apr 12 21:18:48 2010 +0000 + + * Speed up IsSymbolizedProfile by checking for NUL (csilvers) + * Fix heap sampling to use correct alloc size (bmaurer) + * Make pprof ignore tc_new{,array}_nothrow (csilvers) + * PORTING: Have IsHeapProfilerRunning return an int, for C + (csilvers) + * Avoid false-sharing of memory between caches (bmaurer) + * Fix some variable shadowing (rt) + * SVG-based ouptut in pprof; also, wget->curl (rsc) + * Allow arbitrary prefix before obvious handler (rsc) + * Advertise when using libunwind (ppluzhnikov) + + Also, the install file seems to have reverted back to the default at + some previous point in time (autotools will do that occasionally). + Change that back to have the perftools-specific text in there. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@92 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M INSTALL +M src/base/basictypes.h +M src/google/heap-profiler.h +M src/heap-checker.cc +M src/heap-profiler.cc +M src/page_heap_allocator.h +M src/pprof +M src/stacktrace_config.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/thread_cache.h + +commit 92beff88437b31f4a618640b88487e0f8dfb7017 +Author: csilvers +Date: Tue Mar 23 20:39:55 2010 +0000 + + * Add new (std::nothrow) to debugallocation (corrado) + * Add a flag to ingore unaligned-ptr leaks (archanakannan) + * PORTING: Add get-pc capabilities for a new OS (csilvers) + * Don't register malloc extension under valgrind (csilvers) + * Fix throw specs for our global operator new (chandlerc) + * PORTING: link to instructions on windows static overrides + (mbelshe) + * Fix prototype differences in debugalloc (chandlerc, + csilvers, wan) + * Change pprof to handle big-endian input files (csilvers) + * Properly align allocation sizes on Windows (antonm) + * Improve IsRunningOnValgrind, using valgrind.h (csilvers, + kcc) + * Improve the accuracy of system_alloc actual_size (csilvers) + * Add interactive callgrind support to pprof (weidenri...) + * Fix off-by-one problems when symbolizing in pprof (dpeng) + * Be more permissive in allowed library names, in pprof + (csilvers) + * PORTING: Fix pc_from_ucontext to handle cygwin and redhat7 + (csilvers) + * Fix stacktrace to avoid inlining (ppluzhnikov) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@91 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M README.windows +M configure +M configure.ac +M doc/heap_checker.html +M m4/pc_from_ucontext.m4 +A src/base/dynamic_annotations.c +D src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +M src/base/low_level_alloc.cc +M src/config.h.in +M src/debugallocation.cc +M src/google/stacktrace.h +M src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/memory_region_map.cc +M src/pprof +M src/stacktrace.cc +M src/stacktrace_generic-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +D src/stacktrace_with_context.cc +M src/stacktrace_x86-inl.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/debugallocation_test.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/profiler_unittest.cc +M src/tests/profiler_unittest.sh +M src/tests/tcmalloc_unittest.cc +A src/third_party/valgrind.h +M src/windows/google/tcmalloc.h +M src/windows/port.cc + +commit 23dd124970bc11636feaa240394063ba5889ca54 +Author: csilvers +Date: Thu Feb 11 01:32:42 2010 +0000 + + * Speed up patching by not patching modules that are already + loaded + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@88 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/config.h +M src/windows/patch_functions.cc + +commit 8f8a010cab7d3070069a31990cb0e269f03dceb0 +Author: csilvers +Date: Wed Jan 20 23:00:51 2010 +0000 + + Oops, I submitted the wrong version of patch_functions.cc with the + previous commit. This is really the one that goes with release 1.5. + . + ?\027[D + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@86 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/patch_functions.cc + +commit fef86cfeba8915e34575f09499e18b184d7254a9 +Author: csilvers +Date: Wed Jan 20 22:47:29 2010 +0000 + + * google-perftools: version 1.5 release + * Add tc_set_new_mode (willchan) + * Make memalign functions + realloc respect tc_set_new_mode + (willchan) + * Add ReleaseToSystem(num_bytes) (kash) + * Handle zero-length symbols a bit better in pprof (csilvers) + * Prefer __environ to /proc/self/environ in cpu profiler + (csilvers) + * Add HEAP_CHECK_MAX_LEAKS flag to control #leaks to report + (glider) + * Add two new numeric pageheap properties to MallocExtension + (fikes) + * Print alloc size when mmap fails (hakon) + * Add ITIMER_REAL support to cpu profiler (csilvers, + nabeelmian) + * Speed up symbolizer in heap-checker reporting (glider) + * Speed up futexes with FUTEX_PRIVATE_FLAG (m3b) + * Speed up tcmalloc but doing better span coalescing (sanjay) + * Better support for different wget's and addr2maps in pprof + (csilvres) + * Implement a nothrow version of delete and delete[] + (csilvers) + * BUGFIX: fix a race on module_libcs[i] in windows patching + (csilvers) + * BUGFIX: Fix debugallocation to call cpp_alloc for new + (willchan) + * BUGFIX: A simple bugfix for --raw mode (mrabkin) + * BUGFIX: Fix C shims to actually be valid C (csilvers) + * BUGFIX: Fix recursively-unmapped-region accounting + (ppluzhnikov) + * BUGFIX: better distinguish real and fake vdso (ppluzhnikov) + * WINDOWS: replace debugmodule with more reliable psai + (andrey) + * PORTING: Add .bundle as another shared library extension + (csilvers) + * PORTING: Fixed a typo bug in the ocnfigure PRIxx m4 macro + (csilvers) + * PORTING: Augment sysinfo to work on 64-bit OS X (csilvers) + * PORTING: Use sys/ucontext.h to fix compiing on OS X 10.6 + (csilvers) + * PORTING: Fix sysinfo libname reporting for solaris x86 + (jeffrey) + * PORTING: Use libunwind for i386 when using --omitfp + (ppluzhnikov) + + NOTE: This release uses an older version of + src/windows/patch_functions.cc + because I decided the latest optimizations were not well enough tested + for a release. I'll aim to get them into next release. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@84 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M autogen.sh +M configure +M configure.ac +M packages/deb/changelog +M src/pprof +M src/windows/patch_functions.cc + +commit 63b8d63beb7d771713774f9a5d57381cbd29bf19 +Author: csilvers +Date: Thu Jan 14 16:26:05 2010 +0000 + + * PORTING: Revised patch_functions to avoid deadlock + (csilvers, andrey) + * PORTING: Revised patch_functions to speed up .dll loads + (csilvers) + * PORTING: Build and run sampling_test for windows (csilvers) + * Correctly init tc structs even when libc isn't patched + (csilvers) + * Make low-level allocs async-signal-safe (saito) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@83 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M README.windows +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +M src/google/malloc_hook.h +M src/malloc_hook.cc +M src/pprof +M src/stacktrace_x86-inl.h +M src/tcmalloc.cc +M src/tests/sampling_test.sh +M src/thread_cache.cc +M src/windows/patch_functions.cc +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit eeeacd5ec4fa36256091f45e5b3af81cee2a4d86 +Author: csilvers +Date: Wed Jan 6 00:34:23 2010 +0000 + + * PORTING: Fix a race condition in windows patching + * PORTING: Use Psapi instead of debugmodule to get windows + module info + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@82 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M README.windows +M google-perftools.sln +M src/page_heap.h +M src/windows/patch_functions.cc +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 6e7479331c751bdfe04d272dbb1bbbe877f0e86a +Author: csilvers +Date: Tue Dec 15 01:41:30 2009 +0000 + + * Fix a memory leak with repeated Patch() calls on windows + (csilvers) + * Fix a bug when we re-Patch() a previously unpatched lib + (csilvers) + * Add .bundle as another .so extension in pprof (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@81 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/spinlock.h +M src/heap-checker.cc +M src/heap-profile-table.h +M src/memfs_malloc.cc +M src/memory_region_map.h +M src/packed-cache-inl.h +M src/pprof +M src/profile-handler.cc +M src/profiledata.h +M src/windows/patch_functions.cc +M src/windows/preamble_patcher.cc + +commit 1d981b6997f73e6d92b647d042cfe8649d4728c1 +Author: csilvers +Date: Wed Dec 2 21:42:10 2009 +0000 + + * Make memalign && posix_memalign respect tc_set_new_mode + (willchan) + * Fix windows patch functions to respect tc_set_new_mode + (willchan) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@80 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tcmalloc.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/patch_functions.cc + +commit a94d5f797412bac7b811bf8d69d9298fec54f5cc +Author: csilvers +Date: Wed Dec 2 18:15:13 2009 +0000 + + * Prefer __environ to /proc/self/environ (csilvers) + * Add HEAP_CHECK_MAX_LEAKS envvar (glider) + * BUGFIX: debugallocation now calls cpp_alloc for new + (willchan) + * BUGFIX: tc_set_new_mode() respected for realloc and calloc + (willchan) + * BUGFIX: fix opt-mode maybe-crash on debugallocation_test + (csilvers) + * Print alloc size when mmap fails (hakon) + * Add ITIMER_REAL support (csilvers, nabeelmian) + * BUGFIX: correctly report double-frees (csilvers) + * Export tc_set_new_mode() from the .h file (willchan) + * Restructure Symbolize to make it more efficient (glider) + * PORTING: Augment sysinfo to work on 64-bit OS X (csilvers) + * Add two numeric pageheap properties to MallocExtension + (fikes) + * PORTING: Use libunwind for i386 when using --omitfp + (ppluzhnikov) + * Add ReleaseToSystem(num_bytes) (kash) + * Provide correct library filenames under solaris (jeffrey) + * BUGFIX: simple fix in pprof --raw mode (mrabkin) + * PORTING: Prefer sys/ucontext.h to fix OS 10.6 builds + (csilvers) + * Improve support for inlined functions in pprof (sanjay) + * Update wget code to not use keepalive (mrabkin, csilvers) + * PORTING: correctly handle x86_64 machines that use fp's + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@79 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M configure +M configure.ac +M doc/cpuprofile.html +M doc/heap_checker.html +M m4/compiler_characteristics.m4 +M src/base/logging.h +M src/base/sysinfo.cc +M src/config.h.in +M src/debugallocation.cc +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/tcmalloc.h.in +M src/heap-profile-table.cc +M src/malloc_extension.cc +M src/memfs_malloc.cc +M src/pprof +M src/profile-handler.cc +M src/symbolize.cc +M src/symbolize.h +M src/tcmalloc.cc +M src/tests/atomicops_unittest.cc +M src/tests/debugallocation_test.cc +M src/tests/malloc_extension_test.cc +M src/tests/profile-handler_unittest.cc +M src/tests/profiler_unittest.sh +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h +M src/windows/google/tcmalloc.h + +commit 5b80f01df1137337131b4c50ce97faaff9973e90 +Author: csilvers +Date: Tue Nov 10 16:24:57 2009 +0000 + + * Replace usleep() and poll() with nanosleep() (glider) + * Document problems with _recalloc (csilvers) + * Detect when x86_64 doesn't turn off frame pointers + (csilvers) + * Fix sysinfo.cc/etc to work with 64-bit os x (csilvers) + * BUGFIX: Use __TEXT instead of __DATA to store tcmalloc fns + (csilvers) + * Added two numeric pageheap properties to tcmalloc (fikes) + * Support for mallocranges stats visualization (sanjay) + * Use libunwind for i386, not just x86_64 (ppluzhnikov) + * Add ReleaseToSystem(num_bytes) (kash) + * Provide corect library filenames under solaris (jeffrey) + * BUGFIX: a simple bug in pprof --raw mode (mrabkin) + * Prfer sys/ucontext.h to ucontext.h, to fix OS X 10.6 + (csilvers) + * Improve supprot for inlined functions in pprof (sanjay) + * Document inaccuracies in profiling mmap calls (csilvers) + * Update wget code to not use keepalive (mrabkin, csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@78 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M README.windows +M configure +M configure.ac +M doc/heapprofile.html +M google-perftools.sln +M m4/pc_from_ucontext.m4 +M src/base/basictypes.h +M src/base/dynamic_annotations.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/debugallocation.cc +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/heap-checker.cc +M src/malloc_extension.cc +M src/page_heap.cc +M src/page_heap.h +M src/pagemap.h +M src/pprof +M src/stacktrace_config.h +M src/symbolize.cc +M src/symbolize.h +M src/tcmalloc.cc +M src/tests/malloc_extension_c_test.c +A src/tests/page_heap_test.cc +M src/tests/pagemap_unittest.cc +M src/tests/profile-handler_unittest.cc +M src/tests/tcmalloc_unittest.cc +A vsprojects/page_heap_test/page_heap_test.vcproj + +commit 25eed16e1b042a80c9a3e83bbf7ed227d04fb45a +Author: csilvers +Date: Tue Oct 27 17:30:52 2009 +0000 + + * Fix Symbolize() to call pprof once, rather than once/symbol + (glider) + * Fix unsetting of hooks before forking, in debug mode (maxim) + * Add some documention for pmuprofile (aruns) + * Speed up futex with FUTEX_PRIVATE_FLAG (m3b) + * Fix os x 10.6: prefer sys/ucontext.h to ucontext.h + (csilvers) + * Fix C shims to be actually valid C: malloc_extension/etc + (csilvers) + * Fix a longtime memset bug (csilvers) + * Implement nothrow versions of delete (csilvers) + * Fix recursively-unmapped-region accounting (ppluzhnikov) + * Better distinguish between real and fake VDSO (ppluzhnikov) + * Modify span coalescing to improve performance (sanjay) + * WINDOWS: Remove unnecessary lock around VirtualAlloc + (mbelshe) + * Remove performance tests for ptmalloc2 (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@77 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M Makefile.am +M Makefile.in +M configure +M configure.ac +M doc/pprof_remote_servers.html +M src/base/spinlock_linux-inl.h +M src/base/vdso_support.cc +M src/config.h.in +M src/debugallocation.cc +M src/getpc.h +M src/google/malloc_extension_c.h +M src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/malloc_extension.cc +M src/memory_region_map.cc +M src/page_heap.cc +M src/page_heap.h +M src/pprof +M src/profiler.cc +M src/sampler.cc +M src/stacktrace_libunwind-inl.h +M src/stacktrace_x86-inl.h +M src/symbolize.cc +M src/symbolize.h +M src/tcmalloc.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +A src/tests/malloc_extension_c_test.c +D src/tests/ptmalloc/COPYRIGHT +D src/tests/ptmalloc/lran2.h +D src/tests/ptmalloc/malloc-machine.h +D src/tests/ptmalloc/t-test.h +D src/tests/ptmalloc/t-test1.c +D src/tests/ptmalloc/t-test2.c +D src/tests/ptmalloc/thread-m.h +D src/tests/ptmalloc/thread-st.h +M src/tests/tcmalloc_unittest.cc +M src/windows/config.h +M src/windows/google/tcmalloc.h +M src/windows/port.cc + +commit 19dfa9e3733155e57406fbd082273eb53cb2750e +Author: csilvers +Date: Fri Sep 11 18:42:32 2009 +0000 + + Thu Sep 10 13:51:15 2009 Google Inc. + + * google-perftools: version 1.4 release + * Add debugallocation library, to catch memory leaks, + stomping, etc + * Add --raw mode to allow for delayed processing of pprof + files + * Use less memory when reading CPU profiles + * New environment variables to control kernel-allocs (sbrk, + memfs, etc) + * Add MarkThreadBusy(): performance improvement + * Remove static thread-cache-size code; all is dynamic now + * Add new HiddenPointer class to heap checker + * BUGFIX: pvalloc(0) allocates now (found by new debugalloc + library) + * BUGFIX: valloc test (not implementation) no longer + overruns memory + * BUGFIX: GetHeapProfile no longer deadlocks + * BUGFIX: Support unmapping memory regions before main + * BUGFIX: Fix some malloc-stats formatting + * BUGFIX: Don't crash as often when freeing libc-allocated + memory + * BUGFIX: Deal better with incorrect PPROF_PATH when + symbolizing + * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc + * BUGFIX: Fix return value of GetAllocatedSize + * PORTING: Fix mmap-#define problem on some 64-bit systems + * PORTING: Call ranlib again (some OS X versions need it) + * PORTING: Fix a leak when building with LLVM + * PORTING: Remove some unneeded bash-ishs from testing scripts + * WINDOWS: Support library unloading as well as loading + * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when + patching + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@76 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M aclocal.m4 +M configure +M configure.ac +M doc/tcmalloc.html +M google-perftools.sln +M m4/install_prefix.m4 +A m4/pc_from_ucontext.m4 +M packages/deb/changelog +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h +M src/base/basictypes.h +M src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +M src/base/simple_mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +A src/base/spinlock_linux-inl.h +A src/base/spinlock_posix-inl.h +A src/base/spinlock_win32-inl.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/vdso_support.cc +M src/base/vdso_support.h +M src/common.cc +M src/common.h +M src/config.h.in +A src/debugallocation.cc +M src/getpc.h +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/packed-cache-inl.h +M src/page_heap.h +M src/pagemap.h +M src/pprof +M src/profiler.cc +M src/sampler.h +M src/stacktrace_win32-inl.h +M src/stacktrace_with_context.cc +M src/stacktrace_x86-inl.h +A src/symbolize.cc +C060 src/stacktrace_with_context.cc src/symbolize.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +A src/tests/debugallocation_test.cc +A src/tests/debugallocation_test.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/heap-profiler_unittest.sh +M src/tests/low_level_alloc_unittest.cc +M src/tests/malloc_extension_test.cc +M src/tests/markidle_unittest.cc +M src/tests/memalign_unittest.cc +M src/tests/pagemap_unittest.cc +M src/tests/profile-handler_unittest.cc +M src/tests/profiledata_unittest.cc +M src/tests/profiler_unittest.cc +M src/tests/profiler_unittest.sh +M src/tests/sampler_test.cc +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/config.h +M src/windows/google/tcmalloc.h +M src/windows/patch_functions.cc +M src/windows/port.h +M src/windows/preamble_patcher.cc +M vsprojects/addr2line-pdb/addr2line-pdb.vcproj +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M vsprojects/frag_unittest/frag_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/malloc_extension_test/malloc_extension_test.vcproj +M vsprojects/markidle_unittest/markidle_unittest.vcproj +M vsprojects/nm-pdb/nm-pdb.vcproj +M vsprojects/packed-cache_test/packed-cache_test.vcproj +M vsprojects/pagemap_unittest/pagemap_unittest.vcproj +M vsprojects/realloc_unittest/realloc_unittest.vcproj +M vsprojects/sampler_test/sampler_test.vcproj +M vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj +M +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj +M +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj +M vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit 2197cc670204c583bba3903b765c77620f349609 +Author: csilvers +Date: Wed Jun 10 02:04:26 2009 +0000 + + Tue Jun 9 18:19:06 2009 Google Inc. + + * google-perftools: version 1.3 release + * Provide our own name for memory functions: tc_malloc, etc + (csilvers) + * Weaken memory-alloc functions so user can override them + (csilvers) + * Remove meaningless delete(nothrow) and delete[](nothrow) + (csilvers) + * BUILD: replace clever libtcmalloc/profiler.a with a new .a + (csilvers) + * PORTING: improve windows port by using google spinlocks + (csilvers) + * PORTING: Fix RedHat 9 memory allocation in heapchecker + (csilvers) + * PORTING: Rename OS_WINDOWS macro to PLATFORM_WINDOWS + (mbelshe) + * PORTING/BUGFIX: Make sure we don't clobber GetLastError + (mbelshe) + * BUGFIX: get rid of useless data for callgrind (weidenrinde) + * BUGFIX: Modify windows patching to deadlock sometimes + (csilvers) + * BUGFIX: an improved fix for hook handling during fork + (csilvers) + * BUGFIX: revamp profiler_unittest.sh, which was very broken + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@74 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M README +M aclocal.m4 +M configure +M configure.ac +D m4/stl_hash.m4 +M packages/deb/changelog +M packages/rpm/rpm.spec +M src/base/atomicops-internals-linuxppc.h +M src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +M src/base/spinlock.cc +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/vdso_support.cc +M src/base/vdso_support.h +M src/config.h.in +A src/google/tcmalloc.h.in +M src/heap-checker.cc +M src/pprof +M src/profile-handler.cc +M src/tcmalloc.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/profiler_unittest.sh +M src/tests/stacktrace_unittest.cc +M src/windows/config.h +A src/windows/google/tcmalloc.h +M src/windows/override_functions.cc +M src/windows/patch_functions.cc + +commit 104bf697fbd2a0b90b5f01344ee01c8caa1745d0 +Author: csilvers +Date: Mon May 18 22:50:20 2009 +0000 + + Use the google spinlock code instead of the built-in windows code. + The main benefit for perftools is that google spinlocks allow for + link-time (static) initialization, which we had to simulate before, + yielding bugs and worse performance. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@73 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops-internals-x86-msvc.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/windows/config.h +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/packed-cache_test/packed-cache_test.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit ad03b009ef2046cee9dc38afe022b487de37db5c +Author: csilvers +Date: Sat Apr 25 01:01:23 2009 +0000 + + In the case of windows with HAS_EXCEPTIONS turned off we weren't able + to use the std::set_new_handler correctly. Rework the #ifdefs to + allow use of the std_new_handler, but ignore the exceptions. + + Patch submitted by mbelshe. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@72 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/tcmalloc.cc + +commit 1894763f57b00f72a720c4c126815c073d9ed0f3 +Author: csilvers +Date: Wed Apr 22 22:53:41 2009 +0000 + + Make sure we don't clobber GetLastError() (for windows). + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@71 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/windows/port.h + +commit a63235c4331445d718d151a2a659ec9687a0b8c8 +Author: csilvers +Date: Tue Apr 21 17:10:29 2009 +0000 + + 1) Change #include "config.h" to . This is what automake + recommends, and makes it easier to override a config file. + + 2) Rename OS_WINDOWS in sysinfo.cc, to not conflict with a macro + defined in a windows SDK somewhere. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@70 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M src/base/atomicops.h +M src/base/basictypes.h +M src/base/commandlineflags.h +M src/base/elfcore.h +M src/base/logging.cc +M src/base/logging.h +M src/base/low_level_alloc.h +M src/base/simple_mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/vdso_support.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/page_heap.cc +M src/page_heap.h +M src/profiledata.cc +M src/profiledata.h +M src/raw_printer.cc +M src/raw_printer.h +M src/span.cc +M src/span.h +M src/stack_trace_table.cc +M src/stack_trace_table.h +M src/stacktrace.cc +M src/stacktrace_with_context.cc +M src/static_vars.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tcmalloc.h +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/override_functions.cc +M src/windows/patch_functions.cc +M src/windows/port.cc + +commit beb6a9a183c1ca25c99e4401b58266ce73b8c846 +Author: csilvers +Date: Sat Apr 18 00:02:25 2009 +0000 + + Fri Apr 17 16:40:48 2009 Google Inc. + + * google-perftools: version 1.2 release + * Allow large_alloc_threshold=0 to turn it off entirely + (csilvers) + * Die more helpfully when out of memory for internal data + (csilvers) + * Refactor profile-data gathering, add a new unittest (cgd, + nabeelmian) + * BUGFIX: fix rounding errors with static thread-size caches + (addi) + * BUGFIX: disable hooks better when forking in leak-checker + (csilvers) + * BUGFIX: fix realloc of crt pointers on windows (csilvers) + * BUGFIX: do a better job of finding binaries in .sh tests + (csilvers) + * WINDOWS: allow overriding malloc/etc instead of patching + (mbelshe) + * PORTING: fix compilation error in a ppc-specific file + (csilvers) + * PORTING: deal with quirks in cygwin's /proc/self/maps + (csilvers) + * PORTING: use 'A' version of functions for ascii input + (mbelshe) + * PORTING: generate .so's on cygwin and mingw (ajenjo) + * PORTING: disable profiler methods on cygwin (jperkins) + * Updated autoconf version to 2.61 and libtool version + to 1.5.26 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@68 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README.windows +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +M ltmain.sh +M packages/deb/changelog +M packages/rpm.sh +M packages/rpm/rpm.spec +M src/base/atomicops-internals-linuxppc.h +M src/base/logging.cc +M src/base/logging.h +M src/base/simple_mutex.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/config.h.in +M src/google/heap-checker.h +M src/google/profiler.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/page_heap_allocator.h +M src/pprof +A src/profile-handler.cc +A src/profile-handler.h +M src/profiledata.cc +M src/profiledata.h +M src/profiler.cc +M src/sampler.cc +M src/stacktrace_win32-inl.h +M src/stacktrace_x86-inl.h +M src/tcmalloc.cc +M src/tests/frag_unittest.cc +A src/tests/profile-handler_unittest.cc +M src/tests/profiledata_unittest.cc +M src/tests/sampling_test.cc +M src/tests/sampling_test.sh +M src/tests/testutil.cc +M src/thread_cache.cc +M src/windows/addr2line-pdb.c +M src/windows/config.h +M src/windows/mingw.h +M src/windows/nm-pdb.c +A src/windows/override_functions.cc +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h + +commit edd03a831f350bc72d76d4fad2b390d43faccb79 +Author: csilvers +Date: Wed Mar 11 20:50:03 2009 +0000 + + Wed Mar 11 11:25:34 2009 Google Inc. + + * google-perftools: version 1.1 release + * Dynamically resize thread caches -- nice perf. improvement + (kash) + * Add VDSO support to give better stacktraces in linux + (ppluzhnikov) + * Improve heap-profiling sampling algorithm (ford) + * Rewrite leak-checking code: should be faster and more robust + (sanjay) + * Use ps2 instead of ps for dot: better page cropping for gv + (csilvers) + * Disable malloc-failure warning messages by default + (csilvers) + * Update config/Makefile to disable tests on a per-OS basis + (csilvers) + * PORTING: Get perftools compiling under MSVC 7.1 again + (csilvers) + * PORTING: Get perftools compiling under cygwin again + (csilvers) + * PORTING: automatically set library flags for solaris x86 + (csilvers) + * Add TCMALLOC_SKIP_SBRK to mirror TCMALLOC_SKIP_MMAP + (csilvers) + * Add --enable flags to allow selective building (csilvers) + * Put addr2line-pdb and nm-pdb in proper output directory + (csilvers) + * Remove deprecated DisableChecksIn (sanjay) + * DOCUMENTATION: Document most MallocExtension routines + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@66 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README +M README.windows +M aclocal.m4 +M configure +M configure.ac +M doc/pprof_remote_servers.html +M doc/tcmalloc.html +M google-perftools.sln +A m4/acx_nanosleep.m4 +M packages/deb.sh +M packages/deb/changelog +M src/base/basictypes.h +M src/base/cycleclock.h +M src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +M src/base/linux_syscall_support.h +M src/base/simple_mutex.h +M src/base/spinlock.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/thread_annotations.h +A src/base/vdso_support.cc +A src/base/vdso_support.h +M src/central_freelist.cc +M src/common.cc +M src/common.h +M src/config.h.in +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/google/malloc_extension_c.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/memory_region_map.cc +M src/page_heap.cc +M src/pprof +M src/profiler.cc +C061 src/static_vars.cc src/raw_printer.cc +A src/raw_printer.h +A src/sampler.cc +A src/sampler.h +M src/span.cc +A src/stack_trace_table.cc +C056 src/static_vars.cc src/stack_trace_table.h +M src/stacktrace.cc +C057 src/stacktrace.cc src/stacktrace_config.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_win32-inl.h +C059 src/static_vars.cc src/stacktrace_with_context.cc +M src/stacktrace_x86-inl.h +M src/stacktrace_x86_64-inl.h +M src/static_vars.cc +M src/static_vars.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.sh +C060 src/tests/sampling_test.cc src/tests/malloc_extension_test.cc +A src/tests/pagemap_unittest.cc +A src/tests/raw_printer_test.cc +A src/tests/realloc_unittest.cc +A src/tests/sampler_test.cc +M src/tests/sampling_test.cc +M src/tests/sampling_test.sh +A src/tests/stack_trace_table_test.cc +M src/tests/tcmalloc_unittest.cc +M src/thread_cache.cc +M src/thread_cache.h +M src/windows/addr2line-pdb.c +M src/windows/config.h +M src/windows/patch_functions.cc +M src/windows/port.h +M vsprojects/addr2line-pdb/addr2line-pdb.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +C061 vsprojects/nm-pdb/nm-pdb.vcproj +vsprojects/malloc_extension_test/malloc_extension_test.vcproj +M vsprojects/nm-pdb/nm-pdb.vcproj +C064 vsprojects/nm-pdb/nm-pdb.vcproj +vsprojects/pagemap_unittest/pagemap_unittest.vcproj +C065 vsprojects/nm-pdb/nm-pdb.vcproj +vsprojects/realloc_unittest/realloc_unittest.vcproj +C063 vsprojects/nm-pdb/nm-pdb.vcproj +vsprojects/sampler_test/sampler_test.vcproj +C061 vsprojects/nm-pdb/nm-pdb.vcproj +vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj +M vsprojects/tmu-static/tmu-static.vcproj + +commit c75de4d1e91c339fb5142a8a21be8b3ba5224ef7 +Author: csilvers +Date: Tue Jan 6 19:41:15 2009 +0000 + + Tue Jan 6 13:58:56 2009 Google Inc. + * google-perftools: version 1.0 release + * Exactly the same as 1.0rc2 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@64 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M packages/deb/changelog +M src/pprof + +commit 49b02736109f9fe3383971e62bda2192ae86a36d +Author: csilvers +Date: Mon Dec 15 01:20:31 2008 +0000 + + Sun Dec 14 17:10:35 2008 Google Inc. + * google-perftools: version 1.0rc2 release + * Fix compile error on 64-bit systems (casting ptr to int) + (csilvers) + + Thu Dec 11 16:01:32 2008 Google Inc. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@62 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/heap-checker.cc + +commit 6fa2a2574ce1c15ac12293e24691d69a41972e54 +Author: csilvers +Date: Sat Dec 13 01:35:42 2008 +0000 + + Thu Dec 11 16:01:32 2008 Google Inc. + + * google-perftools: version 1.0rc1 release + * Replace API for selectively disabling heap-checker in code + (sanjay) + * Add a pre-mmap hook (daven, adlr) + * Add MallocExtension interface to set memory-releasing rate + (fikes) + * Augment pprof to allow any string ending in /pprof/profile + (csilvers) + * PORTING: Rewrite -- and fix -- malloc patching for windows + (dvitek) + * PORTING: Add nm-pdb and addr2line-pdb for use by pprof + (dvitek) + * PORTING: Improve cygwin and mingw support (jperkins, + csilvers) + * PORTING: Fix pprof for mac os x, other pprof improvements + (csilvers) + * PORTING: Fix some PPC bugs in our locking code + (anton.blanchard) + * A new unittest, smapling_test, to verify tcmalloc-profiles + (csilvers) + * Turn off TLS for gcc < 4.1.2, due to a TLS + -fPIC bug + (csilvers) + * Prefer __builtin_frame_address to assembly for stacktraces + (nlewycky) + * Separate tcmalloc.cc out into multiple files -- + finally! (kash) + * Make our locking code work with -fPIC on 32-bit x86 (aruns) + * Fix an initialization-ordering bug for tcmalloc/profiling + (csilvers) + * Use "initial exec" model of TLS to speed up tcmalloc + (csilvers) + * Enforce 16-byte alignment for tcmalloc, for SSE (sanjay) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@60 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README.windows +M configure +M configure.ac +M doc/heap_checker.html +M doc/pprof_remote_servers.html +M google-perftools.sln +M packages/deb.sh +M packages/deb/changelog +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-x86.h +M src/base/basictypes.h +M src/base/linux_syscall_support.h +M src/base/logging.cc +M src/base/logging.h +M src/base/simple_mutex.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +A src/base/thread_annotations.h +M src/base/thread_lister.c +A src/central_freelist.cc +A src/central_freelist.h +A src/common.cc +A src/common.h +M src/getpc.h +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_hook.h +M src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +A src/linked_list.h +M src/malloc_extension.cc +M src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/memory_region_map.cc +M src/memory_region_map.h +A src/page_heap.cc +A src/page_heap.h +A src/page_heap_allocator.h +M src/pprof +M src/profiler.cc +A src/span.cc +A src/span.h +M src/stacktrace.cc +M src/stacktrace_libunwind-inl.h +A src/stacktrace_win32-inl.h +M src/stacktrace_x86-inl.h +C059 src/base/logging.cc src/static_vars.cc +A src/static_vars.h +M src/tcmalloc.cc +C071 src/base/logging.cc src/tcmalloc_guard.h +M src/tests/atomicops_unittest.cc +M src/tests/frag_unittest.cc +M src/tests/heap-checker_unittest.cc +M src/tests/low_level_alloc_unittest.cc +C052 src/base/logging.cc src/tests/sampling_test.cc +A src/tests/sampling_test.sh +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.cc +A src/thread_cache.cc +A src/thread_cache.h +A src/windows/addr2line-pdb.c +A src/windows/get_mangled_names.cc +M src/windows/mingw.h +M src/windows/mini_disassembler.cc +M src/windows/mini_disassembler.h +M src/windows/mini_disassembler_types.h +A src/windows/nm-pdb.c +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h +M src/windows/preamble_patcher.cc +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_with_stub.cc +D src/windows/vc7and8.def +R059 vsprojects/memalign_unittest/memalign_unittest.vcproj +vsprojects/addr2line-pdb/addr2line-pdb.vcproj +M vsprojects/frag_unittest/frag_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/markidle_unittest/markidle_unittest.vcproj +C068 vsprojects/frag_unittest/frag_unittest.vcproj +vsprojects/nm-pdb/nm-pdb.vcproj +M +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj +M +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj +M vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj +R074 +vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj +vsprojects/tmu-static/tmu-static.vcproj + +commit 16191f87ff8dc78295c0f617060460664fc444bd +Author: csilvers +Date: Tue Sep 23 17:51:05 2008 +0000 + + Tue Sep 23 08:56:31 2008 Google Inc. + + * google-perftools: version 0.99.2 release + * COMPILE FIX: add #include needed for FreeBSD and OS X + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@58 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/tests/heap-profiler_unittest.cc + +commit 8b2dd25dc9d1523ab9a86bd39c4fb798c89db899 +Author: csilvers +Date: Sat Sep 20 17:15:23 2008 +0000 + + Sat Sep 20 09:37:18 2008 Google Inc. + + * google-perftools: version 0.99.1 release + * BUG FIX: look for nm, etc in /usr/bin, not /usr/crosstool + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@56 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M packages/deb/changelog +M src/pprof + +commit 106aef86ce5697cf44bdbec90ab6833b9254d273 +Author: csilvers +Date: Fri Sep 19 20:06:40 2008 +0000 + + Thu Sep 18 16:00:27 2008 Google Inc. + + * google-perftools: version 0.99 release + * Add IsHeapProfileRunning (csilvers) + * Add C shims for some of the C++ header files (csilvers) + * Fix heap profile file clean-up logic (maxim) + * Rename linuxthreads.c to .cc for better compiler support + (csilvers) + * Add source info to disassembly in pprof (sanjay) + * Use open instead of fopen to avoid memory alloc (csilvers) + * Disable malloc extensions when running under valgrind (kcc) + * BUG FIX: Fix out-of-bound error by reordering a check + (larryz) + * Add Options struct to ProfileData (cgd) + * Correct PC-handling of --base in pprof (csilvers) + * Handle 1 function occurring twice in an image (sanjay) + * Improve stack-data cleaning (maxim) + * Use 'struct Foo' to make header C compatible (csilvers) + * Add 'total' line to pprof --text (csilvers) + * Pre-allocate buffer for heap-profiler to avoid OOM errors + (csilvers) + * Allow a few more env-settings to control tcmalloc (csilvers) + * Document some of the issues involving thread-local storage + (csilvers) + * BUG FIX: Define strtoll and friends for windows (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@54 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README +M README.windows +M configure +M configure.ac +M doc/heapprofile.html +M doc/tcmalloc.html +M packages/deb/changelog +M src/addressmap-inl.h +M src/base/basictypes.h +M src/base/commandlineflags.h +M src/base/cycleclock.h +M src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +R099 src/base/linuxthreads.c src/base/linuxthreads.cc +M src/base/spinlock.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +A src/google/malloc_extension_c.h +M src/google/malloc_hook.h +A src/google/malloc_hook_c.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/memory_region_map.cc +M src/pprof +M src/profiledata.cc +M src/profiledata.h +M src/profiler.cc +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/markidle_unittest.cc +M src/tests/profiledata_unittest.cc +M src/windows/port.h + +commit 100e657c5092bc274424286a728db5116a4bbc54 +Author: csilvers +Date: Sat Jun 14 02:30:53 2008 +0000 + + Mon Jun 9 16:47:03 2008 Google Inc. + + * google-perftools: version 0.98 release + * Add ProfilerStartWithOptions() (cgd) + * Change tcmalloc_minimal to not do any stack-tracing at all + (csilvers) + * Prefer mmap to sbrk for 64-buit debug mode (sanjay) + * Fix accounting for some tcmalloc stats (sanjay) + * Use setrlimit() to keep unittests from killing the machine + (odo) + * Fix a bug when sbrk-ing near address 4G (csilvers) + * Make MallocHook thread-safe (jyasskin) + * Fix windows build for MemoryBarrier (jyasskin) + * Fix CPU-profiler docs to mention correct libs (csilvers) + * Fix for GetHeapProfile() when heap-profiling is off (maxim) + * Avoid realloc resizing ping-pongs using hysteresis + (csilvers) + * Add --callgrind output support to pprof (klimek) + * Fix profiler.h and heap-profiler.h to be C-compatible + (csilvers) + * Break malloc_hook.h into two parts to reduce dependencies + (csilvers) + * Better handle systems that don't implement mmap (csilvers) + * PORTING: disable system_alloc_unittest for msvc (csilvers) + * PORTING: Makefile tweaks to build better on cygwin + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@52 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M Makefile.in +M README.windows +M configure +M configure.ac +M doc/cpuprofile.html +M google-perftools.sln +M m4/acx_pthread.m4 +M packages/deb/changelog +M src/addressmap-inl.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-x86-msvc.h +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/commandlineflags.h +M src/base/cycleclock.h +M src/base/dynamic_annotations.cc +M src/base/dynamic_annotations.h +M src/base/linux_syscall_support.h +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +M src/base/simple_mutex.h +M src/base/spinlock.h +M src/base/stl_allocator.h +M src/base/sysinfo.h +M src/config.h.in +M src/getpc.h +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_hook.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.h +A src/malloc_hook-inl.h +M src/malloc_hook.cc +M src/maybe_threads.cc +M src/maybe_threads.h +M src/memory_region_map.cc +M src/memory_region_map.h +M src/packed-cache-inl.h +M src/pagemap.h +M src/pprof +M src/profiledata.h +M src/profiler.cc +M src/stacktrace_generic-inl.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/maybe_threads_unittest.sh +M src/tests/memalign_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.cc +M src/tests/testutil.h +M src/windows/config.h +M src/windows/mingw.h +M src/windows/mini_disassembler.h +M src/windows/mini_disassembler_types.h +M src/windows/patch_functions.cc +M src/windows/port.h +M src/windows/preamble_patcher.h +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M vsprojects/memalign_unittest/memalign_unittest.vcproj +D vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj +M +vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj + +commit 7ec719093b1c9fda979ba0d07eed288e2a7c3c9b +Author: csilvers +Date: Tue Apr 22 01:47:16 2008 +0000 + + Mon Apr 21 15:20:52 2008 Google Inc. + + * google-perftools: version 0.97 release + * Refactor GetHeapProfile to avoid using malloc (maxim) + * Fix heap-checker and heap-profiler hook interactions (maxim) + * Fix a data race in MemoryRegionMap::Lock (jyasskin) + * Improve thread-safety of leak checker (maxim) + * Fix mmap profile to no longer deadlock (maxim) + * Fix rpm to have devel package depend on non-devel (csilvers) + * PORTING: Fix clock-speed detection for Mac OS X (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@50 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M doc/heapprofile.html +M packages/deb/changelog +M packages/rpm/rpm.spec +M src/addressmap-inl.h +M src/base/cycleclock.h +M src/base/elfcore.h +M src/base/low_level_alloc.cc +M src/base/spinlock.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/profiler.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/memory_region_map.cc +M src/memory_region_map.h +M src/pprof +M src/stacktrace_libunwind-inl.h +M src/stacktrace_x86-inl.h +M src/tcmalloc.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/maybe_threads_unittest.sh +M src/windows/port.cc + +commit 97fdd4a4f97dd15e8803ed51ac153903c2cdffc2 +Author: csilvers +Date: Wed Mar 19 23:35:27 2008 +0000 + + Tue Mar 18 14:30:44 2008 Google Inc. + + * google-perftools: version 0.96 release + * major atomicops rewrite; fixed atomic ops code for linux/ppc + (vchen) + * nix the stacktrace library; now build structure is simpler + (csilvers) + * Speed up heap-checker, and reduce extraneous logging (maxim) + * Improve itimer code for NPTL case (cgd) + * Add source code annotations for use by valgrind, etc (kcc) + * PORTING: Fix high resolution timers for Mac OS X (adlr) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@48 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M TODO +M configure +M configure.ac +M doc/cpuprofile.html +M doc/heapprofile.html +M packages/deb/changelog +M packages/rpm/rpm.spec +M src/addressmap-inl.h +M src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-macosx.h +M src/base/atomicops-internals-x86-msvc.h +M src/base/atomicops-internals-x86.cc +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/basictypes.h +M src/base/cycleclock.h +A src/base/dynamic_annotations.cc +A src/base/dynamic_annotations.h +M src/base/linux_syscall_support.h +M src/base/low_level_alloc.cc +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/sysinfo.cc +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/memfs_malloc.cc +M src/pprof +M src/profiler.cc +M src/tests/atomicops_unittest.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/maybe_threads_unittest.sh +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +M +vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj + +commit a644b4f2d61b9610ec6eeb1f09ebce7054aa0762 +Author: csilvers +Date: Tue Feb 19 22:19:22 2008 +0000 + + Tue Feb 19 12:01:31 2008 Google Inc. + + * google-perftools: version 0.95.1 release (bugfix release) + * x86_64 compile-fix: nix pread64 and pwrite64 (csilvers) + * more heap-checker debug logging (maxim) + * minor improvement to x86_64 CycleClock (gpike) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@46 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/base/cycleclock.h +M src/base/linux_syscall_support.h +M src/heap-checker.cc + +commit 8a0a3101bc6a7d56ac04b278f28bdf3f95b00a3c +Author: csilvers +Date: Wed Feb 13 00:55:09 2008 +0000 + + Tue Feb 12 12:28:32 2008 Google Inc. + + * google-perftools: version 0.95 release + * Better -- not perfect -- support for linux-ppc (csilvers) + * Fix race condition in libunwind stacktrace (aruns) + * Speed up x86 spinlock locking (m3b) + * Improve heap-checker performance (maxim) + * Heap checker traverses more ptrs inside heap-alloced objects + (maxim) + * Remove deprecated ProfilerThreadState function (cgd) + * Update libunwind documentation for statically linked + binaries (aruns) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@44 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M configure +M configure.ac +M doc/heap_checker.html +M doc/tcmalloc.html +M packages/deb/changelog +M packages/deb/docs +M packages/rpm/rpm.spec +M src/addressmap-inl.h +A src/base/atomicops-internals-linuxppc.h +M src/base/atomicops-internals-x86-msvc.h +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/commandlineflags.h +A src/base/cycleclock.h +M src/base/elfcore.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.c +M src/base/linuxthreads.h +M src/base/logging.h +R090 src/base/mutex.h src/base/simple_mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/google/heap-checker.h +M src/google/profiler.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/maybe_threads.cc +M src/packed-cache-inl.h +M src/profiledata.h +M src/profiler.cc +M src/stacktrace.cc +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +M src/tests/heap-checker_unittest.cc +M src/tests/profiler_unittest.cc +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/preamble_patcher.h + +commit b43ba444fcd74fa7c3260f6b2494dcbaa3fdb296 +Author: csilvers +Date: Wed Dec 5 00:08:28 2007 +0000 + + Mon Dec 3 23:51:54 2007 Google Inc. + + * google-perftools: version 0.94.1 release (bugfix release) + * Fix missing #includes for x86_64 compile using libunwind + (csilvers) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@42 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/stacktrace_libunwind-inl.h + +commit 11b02f7aebd05cf39f6f93bdd48786909f99f34e +Author: csilvers +Date: Thu Nov 29 23:39:24 2007 +0000 + + Thu Nov 29 07:59:43 2007 Google Inc. + + * google-perftools: version 0.94 release + * PORTING: MinGW/Msys support -- runs same code as MSVC does + (csilvers) + * PORTING: Add NumCPUs support for Mac OS X (csilvers) + * Work around a sscanf bug in glibc(?) (waldemar) + * Fix Windows MSVC bug triggered by thread deletion (csilvers) + * Fix bug that triggers in MSVC /O2: missing volatile (gpike) + * March-of-time support: quiet warnings/errors for gcc 4.2, + OS X 10.5 + * Modify pprof so it works without nm: useful for windows + (csilvers) + * pprof: Support filtering for CPU profiles (cgd) + * Bugfix: have realloc report to hooks in all situations + (maxim) + * Speed improvement: replace slow memcpy with std::copy + (soren) + * Speed: better iterator efficiency in RecordRegionRemoval + (soren) + * Speed: minor speed improvements via better bitfield + alignment (gpike) + * Documentation: add documentation of binary profile output + (cgd) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@40 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M configure +M configure.ac +A doc/cpuprofile-fileformat.html +M doc/cpuprofile.html +M packages/deb/changelog +M src/base/linux_syscall_support.h +M src/base/spinlock.cc +M src/base/sysinfo.cc +M src/config.h.in +M src/getpc.h +M src/google/heap-checker.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/malloc_hook.cc +M src/memfs_malloc.cc +M src/memory_region_map.cc +M src/packed-cache-inl.h +M src/pprof +A src/profiledata.cc +A src/profiledata.h +M src/profiler.cc +M src/stacktrace_generic-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_powerpc-inl.h +M src/stacktrace_x86-inl.h +M src/stacktrace_x86_64-inl.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +M src/tests/heap-checker_unittest.cc +M src/tests/low_level_alloc_unittest.cc +M src/tests/maybe_threads_unittest.sh +A src/tests/profiledata_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.cc +M src/windows/config.h +A src/windows/mingw.h +M src/windows/mini_disassembler.h +M src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h +M src/windows/preamble_patcher.h +M src/windows/preamble_patcher_with_stub.cc +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj + +commit 49b74b9508797f8aafe6b86e62e7efc4ec200e48 +Author: csilvers +Date: Fri Aug 17 20:56:15 2007 +0000 + + * 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. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@38 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README +M README.windows +M autogen.sh +M configure +M configure.ac +M google-perftools.sln +M m4/program_invocation_name.m4 +M packages/deb/changelog +M src/addressmap-inl.h +M src/base/basictypes.h +M src/base/logging.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/base/thread_lister.c +M src/config.h.in +M src/config_for_unittests.h +A src/getpc.h +M src/google/heap-checker.h +M src/google/malloc_hook.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profile-table.h +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/malloc_hook.cc +A src/memfs_malloc.cc +M src/memory_region_map.cc +M src/memory_region_map.h +M src/pprof +M src/profiler.cc +M src/stacktrace_powerpc-inl.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +A src/tests/getpc_test.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.sh +M src/tests/low_level_alloc_unittest.cc +M src/tests/maybe_threads_unittest.sh +M src/tests/memalign_unittest.cc +M src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/windows/TODO +M src/windows/config.h +A src/windows/ia32_modrm_map.cc +A src/windows/ia32_opcode_map.cc +A src/windows/mini_disassembler.cc +A src/windows/mini_disassembler.h +A src/windows/mini_disassembler_types.h +A src/windows/patch_functions.cc +M src/windows/port.cc +M src/windows/port.h +A src/windows/preamble_patcher.cc +A src/windows/preamble_patcher.h +A src/windows/preamble_patcher_with_stub.cc +M src/windows/vc7and8.def +M vsprojects/addressmap_unittest/addressmap_unittest.vcproj +M vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +M +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +C054 vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +vsprojects/tcmalloc_minimal_unittest-static/tcmalloc_minimal_unittest-static.vcproj + +commit c437e1fcdd1e6ff3f032928d460cbfc115e2324f +Author: csilvers +Date: Wed Jul 18 18:30:50 2007 +0000 + + Tue Jul 17 22:26:27 2007 Google Inc. + + * 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 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@36 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README +A README.windows +M aclocal.m4 +A autogen.sh +M compile +M config.guess +M config.sub +M configure +M configure.ac +M depcomp +M doc/cpuprofile.html +M doc/heap_checker.html +M doc/heapprofile.html +A google-perftools.sln +M install-sh +A m4/ac_have_attribute.m4 +A m4/acx_pthread.m4 +A m4/compiler_characteristics.m4 +A m4/install_prefix.m4 +A m4/namespaces.m4 +A m4/program_invocation_name.m4 +A m4/stl_hash.m4 +A m4/stl_namespace.m4 +M missing +M mkinstalldirs +M packages/deb/changelog +M packages/rpm/rpm.spec +M src/base/atomicops-internals-x86-msvc.h +M src/base/atomicops-internals-x86.h +M src/base/atomicops.h +M src/base/basictypes.h +M src/base/commandlineflags.h +M src/base/logging.h +M src/base/low_level_alloc.cc +M src/base/low_level_alloc.h +D src/base/mutex.cc +M src/base/mutex.h +M src/base/spinlock.cc +M src/base/spinlock.h +M src/base/stl_allocator.h +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/config.h.in +C068 src/tests/testutil.h src/config_for_unittests.h +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_hook.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker.cc +M src/heap-profile-table.cc +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/maybe_threads.cc +M src/maybe_threads.h +M src/memory_region_map.cc +M src/memory_region_map.h +A src/packed-cache-inl.h +M src/pprof +M src/profiler.cc +M src/solaris/libstdc++.la +M src/stacktrace.cc +A src/stacktrace_powerpc-inl.h +M src/stacktrace_x86-inl.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +C053 src/tests/testutil.cc src/tcmalloc.h +M src/tests/frag_unittest.cc +M src/tests/heap-checker_unittest.cc +M src/tests/heap-profiler_unittest.cc +M src/tests/heap-profiler_unittest.sh +M src/tests/low_level_alloc_unittest.cc +M src/tests/markidle_unittest.cc +A src/tests/maybe_threads_unittest.sh +M src/tests/memalign_unittest.cc +C065 src/tests/testutil.h src/tests/packed-cache_test.cc +M src/tests/profiler_unittest.cc +M src/tests/stacktrace_unittest.cc +C051 src/tests/thread_dealloc_unittest.cc +src/tests/system-alloc_unittest.cc +M src/tests/tcmalloc_unittest.cc +M src/tests/testutil.cc +M src/tests/testutil.h +M src/tests/thread_dealloc_unittest.cc +A src/windows/TODO +C060 src/config.h.in src/windows/config.h +A src/windows/port.cc +A src/windows/port.h +A src/windows/vc7and8.def +A vsprojects/addressmap_unittest/addressmap_unittest.vcproj +A vsprojects/frag_unittest/frag_unittest.vcproj +A vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj +A +vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj +A vsprojects/markidle_unittest/markidle_unittest.vcproj +A vsprojects/memalign_unittest/memalign_unittest.vcproj +A vsprojects/packed-cache_test/packed-cache_test.vcproj +A vsprojects/system_alloc_unittest/system_alloc_unittest.vcproj +A +vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj +A +vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj +A vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj + +commit 6878379d5bab87c787cdd3487b5620a9c8adf376 +Author: csilvers +Date: Thu Apr 19 00:53:22 2007 +0000 + + Wed Apr 18 16:43:55 2007 Google Inc. + + * google-perftools: version 0.91 release + * Brown-paper-bag bugfix: compilation error on some x86-64 + machines + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@30 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M README +M config.guess +M config.sub +M configure +M configure.ac +M src/base/sysinfo.cc +M src/base/sysinfo.h +M src/stacktrace_libunwind-inl.h +M src/tests/ptmalloc/malloc-machine.h + +commit 74ad5d57ec08abace386befc6c3c695d85f44d1a +Author: csilvers +Date: Mon Apr 16 20:49:32 2007 +0000 + + Fri Apr 13 14:50:51 2007 Google Inc. + + * google-perftools: version 0.90 release + * (As the version-number jump hints, this is a major new + release: + almost every piece of functionality was rewritten. + I can't do + justice to all the changes, but will concentrate on + highlights.) + *** USER-VISIBLE CHANGES: + * Ability to "release" unused memory added to tcmalloc + * Exposed more tweaking knobs via environment variables + (see docs) + * pprof tries harder to map addresses to functions + * tcmalloc_minimal compiles and runs on FreeBSD 6.0 and + Solaris 10 + *** INTERNAL CHANGES: + * Much better 64-bit support + * Better multiple-processor support (e.g. multicore contention + tweaks) + * Support for recent kernel ABI changes (e.g. new arg + to mremap) + * Addition of spinlocks to tcmalloc to reduce contention cost + * Speed up tcmalloc by using __thread on systems that + support TLS + * Total redesign of heap-checker to improve liveness checking + * More portable stack-frame analysis -- no more hard-coded + constants! + * Disentangled heap-profiler code and heap-checker code + * Several new unittests to test, e.g., thread-contention costs + * Lots of small (but important!) bug fixes: e.g., fixing + GetPC on amd64 + *** KNOWN PROBLEMS: + * CPU-profiling may crash on x86_64 (64-bit) systems. + See the README + * Profiling/heap-checking may deadlock on x86_64 systems. + See README + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@28 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M INSTALL +M Makefile.am +M Makefile.in +M README +M TODO +M aclocal.m4 +M config.guess +M config.sub +M configure +M configure.ac +R050 doc/cpu_profiler.html doc/cpuprofile.html +A doc/designstyle.css +M doc/heap_checker.html +D doc/heap_profiler.html +A doc/heapprofile.html +M doc/index.html +M doc/tcmalloc.html +M ltmain.sh +M packages/deb/changelog +A packages/deb/docs +M packages/rpm/rpm.spec +M src/addressmap-inl.h +A src/base/atomicops-internals-macosx.h +A src/base/atomicops-internals-x86-msvc.h +A src/base/atomicops-internals-x86.cc +A src/base/atomicops-internals-x86.h +A src/base/atomicops.h +M src/base/basictypes.h +M src/base/commandlineflags.h +M src/base/elfcore.h +M src/base/googleinit.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.c +M src/base/linuxthreads.h +C074 src/base/googleinit.h src/base/logging.cc +M src/base/logging.h +A src/base/low_level_alloc.cc +A src/base/low_level_alloc.h +A src/base/mutex.cc +A src/base/mutex.h +A src/base/spinlock.cc +A src/base/spinlock.h +A src/base/stl_allocator.h +A src/base/sysinfo.cc +A src/base/sysinfo.h +M src/base/thread_lister.c +M src/base/thread_lister.h +M src/config.h.in +M src/google/heap-checker.h +M src/google/heap-profiler.h +M src/google/malloc_extension.h +M src/google/malloc_hook.h +M src/google/profiler.h +M src/google/stacktrace.h +M src/heap-checker-bcad.cc +M src/heap-checker.cc +A src/heap-profile-table.cc +A src/heap-profile-table.h +D src/heap-profiler-inl.h +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_logging.h +D src/internal_spinlock.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/maybe_threads.cc +A src/memory_region_map.cc +A src/memory_region_map.h +M src/pprof +M src/profiler.cc +A src/solaris/libstdc++.la +M src/stacktrace.cc +M src/stacktrace_generic-inl.h +M src/stacktrace_libunwind-inl.h +M src/stacktrace_x86-inl.h +M src/stacktrace_x86_64-inl.h +M src/system-alloc.cc +M src/system-alloc.h +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +A src/tests/atomicops_unittest.cc +A src/tests/frag_unittest.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/heap-checker_unittest.sh +M src/tests/heap-profiler_unittest.cc +M src/tests/heap-profiler_unittest.sh +A src/tests/low_level_alloc_unittest.cc +A src/tests/markidle_unittest.cc +A src/tests/memalign_unittest.cc +M src/tests/profiler_unittest.sh +M src/tests/ptmalloc/malloc-machine.h +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_large_unittest.cc +M src/tests/tcmalloc_unittest.cc +C055 src/stacktrace.cc src/tests/testutil.cc +C074 src/base/googleinit.h src/tests/testutil.h +C055 src/stacktrace.cc src/tests/thread_dealloc_unittest.cc + +commit ddbf2f027fb4ca8781fd50820ceb870570f414bc +Author: csilvers +Date: Thu Mar 22 05:03:28 2007 +0000 + + Now that we've uploaded the full source, including the doc/ directory, + we can get rid of docs/ + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@27 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +D docs/html/cpu_profiler.html +D docs/html/heap_checker.html +D docs/html/heap_profiler.html +D docs/html/tcmalloc.html +D docs/images/heap-example1.png +D docs/images/overview.gif +D docs/images/pageheap.gif +D docs/images/pprof-test.gif +D docs/images/pprof-vsnprintf.gif +D docs/images/spanmap.gif +D docs/images/tcmalloc-opspercpusec.png +D docs/images/tcmalloc-opspercpusec_002.png +D docs/images/tcmalloc-opspercpusec_003.png +D docs/images/tcmalloc-opspercpusec_004.png +D docs/images/tcmalloc-opspercpusec_005.png +D docs/images/tcmalloc-opspercpusec_006.png +D docs/images/tcmalloc-opspercpusec_007.png +D docs/images/tcmalloc-opspercpusec_008.png +D docs/images/tcmalloc-opspercpusec_009.png +D docs/images/tcmalloc-opspersec.png +D docs/images/tcmalloc-opspersec_002.png +D docs/images/tcmalloc-opspersec_003.png +D docs/images/tcmalloc-opspersec_004.png +D docs/images/tcmalloc-opspersec_005.png +D docs/images/tcmalloc-opspersec_006.png +D docs/images/tcmalloc-opspersec_007.png +D docs/images/tcmalloc-opspersec_008.png +D docs/images/tcmalloc-opspersec_009.png +D docs/images/threadheap.gif + +commit 7ede7d6a9fe772b0bfa05acb2a2a6867405b474a +Author: csilvers +Date: Thu Mar 22 05:01:39 2007 +0000 + + set mime-type for png and gifs + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@26 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit 8e188310f7d8732d81b7b04f193f89964b7af6c5 +Author: csilvers +Date: Thu Mar 22 04:55:49 2007 +0000 + + Wed Jun 14 15:11:14 2006 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@23 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M COPYING +M ChangeLog +M Makefile.am +M aclocal.m4 +M configure +M configure.ac +M doc/cpu_profiler.html +A doc/pprof_remote_servers.html +M src/base/linux_syscall_support.h +M src/base/linuxthreads.c +M src/base/thread_lister.c +M src/google/heap-checker.h +M src/heap-checker.cc +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/pprof +M src/profiler.cc +M src/stacktrace.cc +M src/stacktrace_libunwind-inl.h +M src/tcmalloc.cc +M src/tests/heap-checker_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit c3b96b3ac552160abde541bba8ac7b4f8338efa0 +Author: csilvers +Date: Thu Mar 22 04:48:00 2007 +0000 + + Thu Apr 13 20:59:09 2006 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@21 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/base/elfcore.h +M src/base/linux_syscall_support.h +M src/base/linuxthreads.c +M src/base/thread_lister.h +M src/google/heap-checker.h +M src/heap-checker.cc +M src/heap-profiler.cc +M src/malloc_hook.cc +M src/pprof +M src/profiler.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit 60a3a2ce77ed2713b2eedd20952d9cfc56ff7ccf +Author: csilvers +Date: Thu Mar 22 04:46:29 2007 +0000 + + Fri Jan 27 14:04:27 2006 Google Inc. + + * 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 + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@19 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M configure +M configure.ac +M packages/rpm/rpm.spec +M src/base/thread_lister.c +M src/config.h.in +M src/heap-checker.cc +M src/heap-profiler.cc +M src/malloc_extension.cc +M src/pprof +M src/profiler.cc +M src/stacktrace.cc +C065 src/tests/tcmalloc_unittest.cc src/stacktrace_generic-inl.h +C064 src/tests/tcmalloc_unittest.cc src/stacktrace_libunwind-inl.h +C068 src/stacktrace.cc src/stacktrace_x86-inl.h +A src/stacktrace_x86_64-inl.h +M src/tcmalloc.cc +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit 298274f8d4f474d2b16a35c8babc58817088c59e +Author: csilvers +Date: Thu Mar 22 04:45:23 2007 +0000 + + Mon Nov 14 17:28:59 2005 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@17 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/base/linux_syscall_support.h +M src/base/logging.h +M src/config.h.in + +commit ee5805f1296f8546c16f90d5427efa347a5f7338 +Author: csilvers +Date: Thu Mar 22 04:44:18 2007 +0000 + + Wed Oct 26 15:19:16 2005 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@15 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M aclocal.m4 +M configure +M configure.ac +M doc/cpu_profiler.html +D src/base/elfcore.c +M src/base/elfcore.h +A src/base/linux_syscall_support.h +M src/base/linuxthreads.c +M src/base/linuxthreads.h +M src/base/thread_lister.c +M src/base/thread_lister.h +M src/google/heap-checker.h +M src/google/malloc_extension.h +M src/google/profiler.h +M src/heap-checker.cc +M src/heap-profiler.cc +M src/internal_logging.cc +M src/internal_spinlock.h +M src/malloc_extension.cc +M src/malloc_hook.cc +M src/pagemap.h +M src/pprof +M src/profiler.cc +M src/stacktrace.cc +M src/system-alloc.cc +M src/tcmalloc.cc +A src/tests/tcmalloc_large_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit bc455d7b63949fab94ed9518d277866e95f08768 +Author: csilvers +Date: Thu Mar 22 04:42:30 2007 +0000 + + Fri Jun 24 18:02:26 2005 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@13 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M configure +M configure.ac +M src/pagemap.h +M src/stacktrace.cc +M src/tcmalloc.cc +M src/tests/heap-checker_unittest.cc +M src/tests/stacktrace_unittest.cc + +commit 91fad389784766782263133c5510976a8f76d89e +Author: csilvers +Date: Thu Mar 22 03:28:56 2007 +0000 + + Tue May 31 08:14:38 2005 Google Inc. + + * 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) + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@11 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +M ChangeLog +M Makefile.am +M README +M TODO +M configure +M configure.ac +M doc/cpu_profiler.html +A doc/heap_checker.html +M doc/heap_profiler.html +A doc/index.html +A doc/t-test1.times.txt +A doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png +A doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png +A doc/tcmalloc-opspersec.vs.size.1.threads.png +A doc/tcmalloc-opspersec.vs.size.12.threads.png +A doc/tcmalloc-opspersec.vs.size.16.threads.png +A doc/tcmalloc-opspersec.vs.size.2.threads.png +A doc/tcmalloc-opspersec.vs.size.20.threads.png +A doc/tcmalloc-opspersec.vs.size.3.threads.png +A doc/tcmalloc-opspersec.vs.size.4.threads.png +A doc/tcmalloc-opspersec.vs.size.5.threads.png +A doc/tcmalloc-opspersec.vs.size.8.threads.png +M doc/tcmalloc.html +M packages/deb/changelog +M packages/deb/control +M packages/deb/copyright +D packages/deb/files +M packages/deb/libgoogle-perftools-dev.install +M packages/deb/libgoogle-perftools0.install +M packages/rpm.sh +M packages/rpm/rpm.spec +M src/addressmap-inl.h +R099 src/google/perftools/basictypes.h src/base/basictypes.h +M src/base/commandlineflags.h +A src/base/elfcore.c +A src/base/elfcore.h +A src/base/linuxthreads.c +A src/base/linuxthreads.h +A src/base/thread_lister.c +A src/base/thread_lister.h +M src/google/heap-checker.h +M src/google/heap-profiler.h +R088 src/google/malloc_interface.h src/google/malloc_extension.h +M src/google/malloc_hook.h +D src/google/perftools/config.h.in +M src/google/stacktrace.h +M src/heap-checker-bcad.cc +M src/heap-checker.cc +M src/heap-profiler-inl.h +M src/heap-profiler.cc +M src/internal_logging.h +M src/internal_spinlock.h +R068 src/malloc_interface.cc src/malloc_extension.cc +M src/malloc_hook.cc +A src/maybe_threads.cc +C070 src/tests/tcmalloc_unittest.cc src/maybe_threads.h +M src/pagemap.h +M src/pprof +M src/profiler.cc +M src/stacktrace.cc +M src/system-alloc.cc +M src/tcmalloc.cc +M src/tests/addressmap_unittest.cc +M src/tests/heap-checker-death_unittest.sh +M src/tests/heap-checker_unittest.cc +C051 src/tests/heap-checker-death_unittest.sh +src/tests/heap-checker_unittest.sh +A src/tests/heap-profiler_unittest.cc +A src/tests/heap-profiler_unittest.sh +M src/tests/profiler_unittest.cc +M src/tests/profiler_unittest.sh +M src/tests/stacktrace_unittest.cc +M src/tests/tcmalloc_unittest.cc + +commit 51b4875f8ade3e0930eed2dc2a842ec607a94a2c +Author: csilvers +Date: Thu Mar 22 03:00:33 2007 +0000 + + Tue Feb 8 09:57:17 2005 El Goog + + * 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. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@9 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +A AUTHORS +A COPYING +A ChangeLog +A INSTALL +A Makefile.am +A Makefile.in +A NEWS +A README +A TODO +A aclocal.m4 +A compile +A config.guess +A config.sub +A configure +A configure.ac +A depcomp +A doc/cpu_profiler.html +A doc/heap-example1.png +A doc/heap_profiler.html +A doc/overview.dot +A doc/overview.gif +A doc/pageheap.dot +A doc/pageheap.gif +A doc/pprof-test-big.gif +A doc/pprof-test.gif +A doc/pprof-vsnprintf-big.gif +A doc/pprof-vsnprintf.gif +A doc/pprof.1 +A doc/pprof.see_also +A doc/spanmap.dot +A doc/spanmap.gif +A doc/tcmalloc.html +A doc/threadheap.dot +A doc/threadheap.gif +A install-sh +A ltmain.sh +A missing +A mkinstalldirs +A packages/deb.sh +A packages/deb/README +A packages/deb/changelog +A packages/deb/compat +A packages/deb/control +A packages/deb/copyright +A packages/deb/files +A packages/deb/libgoogle-perftools-dev.dirs +A packages/deb/libgoogle-perftools-dev.install +A packages/deb/libgoogle-perftools0.dirs +A packages/deb/libgoogle-perftools0.install +A packages/deb/libgoogle-perftools0.manpages +A packages/deb/rules +A packages/rpm.sh +A packages/rpm/rpm.spec +A src/addressmap-inl.h +A src/base/commandlineflags.h +A src/base/googleinit.h +A src/base/logging.h +A src/config.h.in +A src/google/heap-checker.h +A src/google/heap-profiler.h +A src/google/malloc_hook.h +A src/google/malloc_interface.h +A src/google/perftools/basictypes.h +A src/google/perftools/config.h.in +A src/google/profiler.h +A src/google/stacktrace.h +A src/heap-checker-bcad.cc +A src/heap-checker.cc +A src/heap-profiler-inl.h +A src/heap-profiler.cc +A src/internal_logging.cc +A src/internal_logging.h +A src/internal_spinlock.h +A src/malloc_hook.cc +A src/malloc_interface.cc +A src/pagemap.h +A src/pprof +A src/profiler.cc +A src/stacktrace.cc +A src/system-alloc.cc +A src/system-alloc.h +A src/tcmalloc.cc +A src/tests/addressmap_unittest.cc +A src/tests/heap-checker-death_unittest.sh +A src/tests/heap-checker_unittest.cc +A src/tests/profiler_unittest.cc +A src/tests/profiler_unittest.sh +A src/tests/ptmalloc/COPYRIGHT +A src/tests/ptmalloc/lran2.h +A src/tests/ptmalloc/malloc-machine.h +A src/tests/ptmalloc/t-test.h +A src/tests/ptmalloc/t-test1.c +A src/tests/ptmalloc/t-test2.c +A src/tests/ptmalloc/thread-m.h +A src/tests/ptmalloc/thread-st.h +A src/tests/stacktrace_unittest.cc +A src/tests/tcmalloc_unittest.cc + +commit e3a8513447d1141f083d4aaced0b240a6e161f47 +Author: trowbridge.jon + +Date: Thu Dec 28 22:53:59 2006 +0000 + + Set page mime-type to text/html. + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@5 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +commit 66737d1c2519e4a1622f61139bfe2f683ea3696c +Author: trowbridge.jon + +Date: Thu Dec 28 22:39:33 2006 +0000 + + Import of HTML documentation from SourceForge. + + + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@3 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 + +A docs/html/cpu_profiler.html +A docs/html/heap_checker.html +A docs/html/heap_profiler.html +A docs/html/tcmalloc.html +A docs/images/heap-example1.png +A docs/images/overview.gif +A docs/images/pageheap.gif +A docs/images/pprof-test.gif +A docs/images/pprof-vsnprintf.gif +A docs/images/spanmap.gif +A docs/images/tcmalloc-opspercpusec.png +A docs/images/tcmalloc-opspercpusec_002.png +A docs/images/tcmalloc-opspercpusec_003.png +A docs/images/tcmalloc-opspercpusec_004.png +A docs/images/tcmalloc-opspercpusec_005.png +A docs/images/tcmalloc-opspercpusec_006.png +A docs/images/tcmalloc-opspercpusec_007.png +A docs/images/tcmalloc-opspercpusec_008.png +A docs/images/tcmalloc-opspercpusec_009.png +A docs/images/tcmalloc-opspersec.png +A docs/images/tcmalloc-opspersec_002.png +A docs/images/tcmalloc-opspersec_003.png +A docs/images/tcmalloc-opspersec_004.png +A docs/images/tcmalloc-opspersec_005.png +A docs/images/tcmalloc-opspersec_006.png +A docs/images/tcmalloc-opspersec_007.png +A docs/images/tcmalloc-opspersec_008.png +A docs/images/tcmalloc-opspersec_009.png +A docs/images/threadheap.gif + +commit 55d679a05f0518ea73a4bca6e8b71b54fcecf68f +Author: (no author) <(no author)@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> +Date: Thu Jul 27 00:57:14 2006 +0000 + + Initial directory structure. + + git-svn-id: http://gperftools.googlecode.com/svn/trunk@1 + 6b5cf1ce-ec42-a296-1ba9-69fdba395a50 diff --git a/trunk/3rdparty/gperftools-2-fit/ChangeLog.old b/trunk/3rdparty/gperftools-2-fit/ChangeLog.old new file mode 100644 index 000000000..4b334beaa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/ChangeLog.old @@ -0,0 +1,646 @@ +Fri Feb 03 15:40:45 2012 Google Inc. + + * gperftools: version 2.0 + * Renamed the project from google-perftools to gperftools (csilvers) + * Renamed the .deb/.rpm packagse from google-perftools to gperftools too + * Renamed include directory from google/ to gperftools/ (csilvers) + * Changed the 'official' perftools email in setup.py/etc + * Renamed google-perftools.sln to gperftools.sln + * PORTING: Removed bash-isms & grep -q in heap-checker-death_unittest.sh + * Changed copyright text to reflect Google's relinquished ownership + +Tue Jan 31 10:43:50 2012 Google Inc. + + * 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. + + * google-perftools: version 1.9 release + * Lightweight check for double-frees (blount) + * BUGFIX: Fix pprof to exit properly if run with no args (dagitses) + * Suggest ASan as a way to diagnose buggy code (ppluzhnikov) + * Get rid of unused CACHELINE_SIZE (csilvers) + * Replace atexit() calls with global dtors; helps freebsd (csilvers) + * Disable heap-checker under AddressSanitizer (kcc) + * Fix bug in powerpc stacktracing (ppluzhnikov) + * PERF: Use exponential backoff waiting for spinlocks (m3b) + * Fix 64-bit nm on 32-bit binaries in pprof (csilvers) + * Add ProfileHandlerDisallowForever (rsc) + * BUGFIX: Shell escape when forking in pprof (csilvers) + * No longer combine overloaded functions in pprof (csilvers) + * Fix address-normalizing bug in pprof (csilvers) + * More consistently call abort() instead of exit() on failure (csilvers) + * Allow NoGlobalLeaks to be safely called more than once (csilvers) + * PORTING/BUGFIX: Fix ARM cycleclock to use volatile asm (dougkwan) + * PORTING: 64-bit atomic ops for ARMv7 (dougkwan) + * PORTING: Implement stacktrace for ARM (dougkwan) + * PORTING: Fix malloc_hook_mmap_linux for ARM (dougkwan) + * PORTING: Update linux_syscall_support.h for ARM/etc (evannier, sanek) + * PORTING: Fix freebsd to work on x86_64 (chapp...@gmail.com) + * PORTING: Added additional SYS_mmap fixes for FreeBSD (chappedm) + * PORTING: Allow us to compile on OS X 10.6 and run on 10.5 (raltherr) + * PORTING: Check for mingw compilers that *do* define timespec + * PORTING: Add "support" for MIPS cycletimer + * PORTING: Fix fallback cycle-timer to work with Now (dougkwan) + * PERF: Move stack trace collecting out of the mutex (taylorc) + * PERF: Get the deallocation stack trace outside the mutex (sean) + * Make PageHeap dynamically allocated for leak checks (maxim) + * BUGFIX: Fix probing of nm -f behavior in pprof (dpeng) + * BUGFIX: Fix a race with the CentralFreeList lock before main (sanjay) + * Support /pprof/censusprofile url arguments (rajatjain) + * Change IgnoreObject to return its argument (nlewycky) + * Update malloc-hook files to support more CPUs + * BUGFIX: write our own strstr to avoid libc problems (csilvers) + * Use simple callgrind compression facility in pprof + * Print an error message when we can't run pprof to symbolize (csilvers) + * Die in configure when g++ is't installed (csilvers) + * DOC: Beef up the documentation a bit about using libunwind (csilvers) + +Fri Aug 26 13:29:25 2011 Google Inc. + + * google-perftools: version 1.8.3 release + * Added back the 'pthreads unsafe early' #define, needed for FreeBSD + +Thu Aug 11 15:01:47 2011 Google Inc. + + * google-perftools: version 1.8.2 release + * Fixed calculation of patchlevel, 'make check' should all pass again + +Tue Jul 26 20:57:51 2011 Google Inc. + + * google-perftools: version 1.8.1 release + * Added an #include to fix compile breakage on latest gcc's + * Removed an extra , in the configure.ac script + +Fri Jul 15 16:10:51 2011 Google Inc. + + * google-perftools: version 1.8 release + * PORTING: (Disabled) support for patching mmap on freebsd (chapp...) + * PORTING: Support volatile __malloc_hook for glibc 2.14 (csilvers) + * PORTING: Use _asm rdtsc and __rdtsc to get cycleclock in windows (koda) + * PORTING: Fix fd vs. HANDLE compiler error on cygwin (csilvers) + * PORTING: Do not test memalign or double-linking on OS X (csilvers) + * PORTING: Actually enable TLS on windows (jontra) + * PORTING: Some work to compile under Native Client (krasin) + * PORTING: deal with pthread_once w/o -pthread on freebsd (csilvers) + * Rearrange libc-overriding to make it easier to port (csilvers) + * Display source locations in pprof disassembly (sanjay) + * BUGFIX: Actually initialize allocator name (mec) + * BUGFIX: Keep track of 'overhead' bytes in malloc reporting (csilvers) + * Allow ignoring one object twice in the leak checker (glider) + * BUGFIX: top10 in pprof should print 10 lines, not 11 (rsc) + * Refactor vdso source files (tipp) + * Some documentation cleanups + * Document MAX_TOTAL_THREAD_CACHE_SIZE <= 1Gb (nsethi) + * Add MallocExtension::GetOwnership(ptr) (csilvers) + * BUGFIX: We were leaving out a needed $(top_srcdir) in the Makefile + * PORTING: Support getting argv0 on OS X + * Add 'weblist' command to pprof: like 'list' but html (sanjay) + * Improve source listing in pprof (sanjay) + * Cap cache sizes to reduce fragmentation (ruemmler) + * Improve performance by capping or increasing sizes (ruemmler) + * Add M{,un}mapReplacmenet hooks into MallocHook (ribrdb) + * Refactored system allocator logic (gangren) + * Include cleanups (csilvers) + * Add TCMALLOC_SMALL_BUT_SLOW support (ruemmler) + * Clarify that tcmalloc stats are MiB (robinson) + * Remove support for non-tcmalloc debugallocation (blount) + * Add a new test: malloc_hook_test (csilvers) + * Change the configure script to be more crosstool-friendly (mcgrathr) + * PORTING: leading-underscore changes to support win64 (csilvers) + * Improve debugallocation tc_malloc_size (csilvers) + * Extend atomicops.h and cyceclock to use ARM V6+ optimized code (sanek) + * Change malloc-hook to use a list-like structure (llib) + * Add flag to use MAP_PRIVATE in memfs_malloc (gangren) + * Windows support for pprof: nul and /usr/bin/file (csilvers) + * TESTING: add test on strdup to tcmalloc_test (csilvers) + * Augment heap-checker to deal with no-inode maps (csilvers) + * Count .dll/.dylib as shared libs in heap-checker (csilvers) + * Disable sys_futex for arm; it's not always reliable (sanek) + * PORTING: change lots of windows/port.h macros to functions + * BUGFIX: Generate correct version# in tcmalloc.h on windows (csilvers) + * PORTING: Some casting to make solaris happier about types (csilvers) + * TESTING: Disable debugallocation_test in 'minimal' mode (csilvers) + * Rewrite debugallocation to be more modular (csilvers) + * Don't try to run the heap-checker under valgrind (ppluzhnikov) + * BUGFIX: Make focused stat %'s relative, not absolute (sanjay) + * BUGFIX: Don't use '//' comments in a C file (csilvers) + * Quiet new-gcc compiler warnings via -Wno-unused-result, etc (csilvers) + +Fri Feb 04 15:54:31 2011 Google Inc. + + * google-perftools: version 1.7 release + * Reduce page map key size under x86_64 by 4.4MB (rus) + * Remove a flaky malloc-extension test (fdabek) + * Improve the performance of PageHeap::New (ond..., csilvers) + * Improve sampling_test with no-inline additions/etc (fdabek) + * 16-byte align debug allocs (jyasskin) + * Change FillProcSelfMaps to detect out-of-buffer-space (csilvers) + * Document the need for sampling to use GetHeapSample (csilvers) + * Try to read TSC frequency from tsc_freq_khs (adurbin) + * Do better at figuring out if tests are running under gdb (ppluzhnikov) + * Improve spinlock contention performance (ruemmler) + * Better internal-function list for pprof's /contention (ruemmler) + * Speed up GoogleOnce (m3b) + * Limit number of incoming/outgoing edges in pprof (sanjay) + * Add pprof --evince to go along with --gv (csilvers) + * Document the various ways to get heap-profiling information (csilvers) + * Separate out synchronization profiling routines (ruemmler) + * Improve malloc-stats output to be more understandable (csilvers) + * Add support for census profiler in pporf (nabeelmian) + * Document how pprof's /symbol must support GET requests (csilvers) + * Improve acx_pthread.m4 (ssuomi, liujisi) + * Speed up pprof's ExtractSymbols (csilvers) + * Ignore some known-leaky (java) libraries in the heap checker (davidyu) + * Make kHideMask use all 64 bits in tests (ppluzhnikov) + * Clean up pprof input-file handling (csilvers) + * BUGFIX: Don't crash if __environ is NULL (csilvers) + * BUGFIX: Fix totally broken debugallocation tests (csilvers) + * BUGFIX: Fix up fake_VDSO handling for unittest (ppluzhnikov) + * BUGFIX: Suppress all large allocs when report threshold is 0 (lexie) + * BUGFIX: mmap2 on i386 takes an off_t, not off64_t (csilvers) + * PORTING: Add missing PERFTOOLS_DLL_DECL (csilvers) + * PORTING: Add stddef.h to make newer gcc's happy (csilvers) + * PORTING: Document some tricks for working under OS X (csilvers) + * PORTING: Don't try to check valgrind for windows (csilvers) + * PORTING: Make array-size a var to compile under clang (chandlerc) + * PORTING: No longer hook _aligned_malloc and _aligned_free (csilvers) + * PORTING: Quiet some gcc warnings (csilvers) + * PORTING: Replace %PRIxPTR with %p to be more portable (csilvers) + * PORTING: Support systems that capitalize /proc weirdly (sanek) + * PORTING: Treat arm3 the same as arm5t in cycletimer (csilvers) + * PORTING: Update windows logging to not allocate memory (csilvers) + * PORTING: avoid double-patching newer windows DLLs (roger.orr) + * PORTING: get dynamic_annotations.c to work on windows (csilvers) + * Add pkg-config .pc files for the 5 libraries we produce (csilvers) + * Added proper libtool versioning, so this lib will be 0.1.0 (csilvers) + * Moved from autoconf 2.64 to 2.65 + +Thu Aug 5 12:48:03 PDT 2010 Google Inc. + + * google-perftools: version 1.6 release + * Add tc_malloc_usable_size for compatibility with glibc (csilvers) + * Override malloc_usable_size with tc_malloc_usable_size (csilvers) + * Default to no automatic heap sampling in tcmalloc (csilvers) + * Add -DTCMALLOC_LARGE_PAGES, a possibly faster tcmalloc (rus) + * Make some functions extern "C" to avoid false ODR warnings (jyasskin) + * pprof: Add SVG-based output (rsc) + * pprof: Extend pprof --tools to allow per-tool configs (csilvers) + * pprof: Improve support of 64-bit and big-endian profiles (csilvers) + * pprof: Add interactive callgrind suport (weidenri...) + * pprof: Improve address->function mapping a bit (dpeng) + * Better detection of when we're running under valgrind (csilvers) + * Better CPU-speed detection under valgrind (saito) + * Use, and recommend, -fno-builtin-malloc when compiling (csilvers) + * Avoid false-sharing of memory between caches (bmaurer) + * BUGFIX: Fix heap sampling to use correct alloc size (bmauer) + * BUGFIX: Avoid gcc 4.0.x bug by making hook-clearing atomic (csilvers) + * BUGFIX: Avoid gcc 4.5.x optimization bug (csilvers) + * BUGFIX: Work around deps-determining bug in libtool 1.5.26 (csilvers) + * BUGFIX: Fixed test to use HAVE_PTHREAD, not HAVE_PTHREADS (csilvers) + * BUGFIX: Fix tls callback behavior on windows when using wpo (wtc) + * BUGFIX: properly align allocation sizes on Windows (antonm) + * BUGFIX: Fix prototypes for tcmalloc/debugalloc wrt throw() (csilvers) + * DOC: Updated heap-checker doc to match reality better (fischman) + * DOC: Document ProfilerFlush, ProfilerStartWithOptions (csilvers) + * DOC: Update docs for heap-profiler functions (csilvers) + * DOC: Clean up documentation around tcmalloc.slack_bytes (fikes) + * DOC: Renamed README.windows to README_windows.txt (csilvers) + * DOC: Update the NEWS file to be non-empty (csilvers) + * PORTING: Fix windows addr2line and nm with proper rc code (csilvers) + * PORTING: Add CycleClock and atomicops support for arm 5 (sanek) + * PORTING: Improve PC finding on cygwin and redhat 7 (csilvers) + * PORTING: speed up function-patching under windows (csilvers) + +Tue Jan 19 14:46:12 2010 Google Inc. + + * google-perftools: version 1.5 release + * Add tc_set_new_mode (willchan) + * Make memalign functions + realloc respect tc_set_new_mode (willchan) + * Add ReleaseToSystem(num_bytes) (kash) + * Handle zero-length symbols a bit better in pprof (csilvers) + * Prefer __environ to /proc/self/environ in cpu profiler (csilvers) + * Add HEAP_CHECK_MAX_LEAKS flag to control #leaks to report (glider) + * Add two new numeric pageheap properties to MallocExtension (fikes) + * Print alloc size when mmap fails (hakon) + * Add ITIMER_REAL support to cpu profiler (csilvers, nabeelmian) + * Speed up symbolizer in heap-checker reporting (glider) + * Speed up futexes with FUTEX_PRIVATE_FLAG (m3b) + * Speed up tcmalloc but doing better span coalescing (sanjay) + * Better support for different wget's and addr2maps in pprof (csilvres) + * Implement a nothrow version of delete and delete[] (csilvers) + * BUGFIX: fix a race on module_libcs[i] in windows patching (csilvers) + * BUGFIX: Fix debugallocation to call cpp_alloc for new (willchan) + * BUGFIX: A simple bugfix for --raw mode (mrabkin) + * BUGFIX: Fix C shims to actually be valid C (csilvers) + * BUGFIX: Fix recursively-unmapped-region accounting (ppluzhnikov) + * BUGFIX: better distinguish real and fake vdso (ppluzhnikov) + * WINDOWS: replace debugmodule with more reliable psai (andrey) + * PORTING: Add .bundle as another shared library extension (csilvers) + * PORTING: Fixed a typo bug in the ocnfigure PRIxx m4 macro (csilvers) + * PORTING: Augment sysinfo to work on 64-bit OS X (csilvers) + * PORTING: Use sys/ucontext.h to fix compiing on OS X 10.6 (csilvers) + * PORTING: Fix sysinfo libname reporting for solaris x86 (jeffrey) + * PORTING: Use libunwind for i386 when using --omitfp (ppluzhnikov) + +Thu Sep 10 13:51:15 2009 Google Inc. + + * google-perftools: version 1.4 release + * Add debugallocation library, to catch memory leaks, stomping, etc + * Add --raw mode to allow for delayed processing of pprof files + * Use less memory when reading CPU profiles + * New environment variables to control kernel-allocs (sbrk, memfs, etc) + * Add MarkThreadBusy(): performance improvement + * Remove static thread-cache-size code; all is dynamic now + * Add new HiddenPointer class to heap checker + * BUGFIX: pvalloc(0) allocates now (found by new debugalloc library) + * BUGFIX: valloc test (not implementation) no longer overruns memory + * BUGFIX: GetHeapProfile no longer deadlocks + * BUGFIX: Support unmapping memory regions before main + * BUGFIX: Fix some malloc-stats formatting + * BUGFIX: Don't crash as often when freeing libc-allocated memory + * BUGFIX: Deal better with incorrect PPROF_PATH when symbolizing + * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc + * BUGFIX: Fix return value of GetAllocatedSize + * PORTING: Fix mmap-#define problem on some 64-bit systems + * PORTING: Call ranlib again (some OS X versions need it) + * PORTING: Fix a leak when building with LLVM + * PORTING: Remove some unneeded bash-ishs from testing scripts + * WINDOWS: Support library unloading as well as loading + * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when patching + +Tue Jun 9 18:19:06 2009 Google Inc. + + * google-perftools: version 1.3 release + * Provide our own name for memory functions: tc_malloc, etc (csilvers) + * Weaken memory-alloc functions so user can override them (csilvers) + * Remove meaningless delete(nothrow) and delete[](nothrow) (csilvers) + * BUILD: replace clever libtcmalloc/profiler.a with a new .a (csilvers) + * PORTING: improve windows port by using google spinlocks (csilvers) + * PORTING: Fix RedHat 9 memory allocation in heapchecker (csilvers) + * PORTING: Rename OS_WINDOWS macro to PLATFORM_WINDOWS (mbelshe) + * PORTING/BUGFIX: Make sure we don't clobber GetLastError (mbelshe) + * BUGFIX: get rid of useless data for callgrind (weidenrinde) + * BUGFIX: Modify windows patching to deadlock sometimes (csilvers) + * BUGFIX: an improved fix for hook handling during fork (csilvers) + * BUGFIX: revamp profiler_unittest.sh, which was very broken (csilvers) + +Fri Apr 17 16:40:48 2009 Google Inc. + + * google-perftools: version 1.2 release + * Allow large_alloc_threshold=0 to turn it off entirely (csilvers) + * Die more helpfully when out of memory for internal data (csilvers) + * Refactor profile-data gathering, add a new unittest (cgd, nabeelmian) + * BUGFIX: fix rounding errors with static thread-size caches (addi) + * BUGFIX: disable hooks better when forking in leak-checker (csilvers) + * BUGFIX: fix realloc of crt pointers on windows (csilvers) + * BUGFIX: do a better job of finding binaries in .sh tests (csilvers) + * WINDOWS: allow overriding malloc/etc instead of patching (mbelshe) + * PORTING: fix compilation error in a ppc-specific file (csilvers) + * PORTING: deal with quirks in cygwin's /proc/self/maps (csilvers) + * PORTING: use 'A' version of functions for ascii input (mbelshe) + * PORTING: generate .so's on cygwin and mingw (ajenjo) + * PORTING: disable profiler methods on cygwin (jperkins) + * Updated autoconf version to 2.61 and libtool version to 1.5.26 + +Wed Mar 11 11:25:34 2009 Google Inc. + + * google-perftools: version 1.1 release + * Dynamically resize thread caches -- nice perf. improvement (kash) + * Add VDSO support to give better stacktraces in linux (ppluzhnikov) + * Improve heap-profiling sampling algorithm (ford) + * Rewrite leak-checking code: should be faster and more robust (sanjay) + * Use ps2 instead of ps for dot: better page cropping for gv (csilvers) + * Disable malloc-failure warning messages by default (csilvers) + * Update config/Makefile to disable tests on a per-OS basis (csilvers) + * PORTING: Get perftools compiling under MSVC 7.1 again (csilvers) + * PORTING: Get perftools compiling under cygwin again (csilvers) + * PORTING: automatically set library flags for solaris x86 (csilvers) + * Add TCMALLOC_SKIP_SBRK to mirror TCMALLOC_SKIP_MMAP (csilvers) + * Add --enable flags to allow selective building (csilvers) + * Put addr2line-pdb and nm-pdb in proper output directory (csilvers) + * Remove deprecated DisableChecksIn (sanjay) + * DOCUMENTATION: Document most MallocExtension routines (csilvers) + +Tue Jan 6 13:58:56 2009 Google Inc. + + * google-perftools: version 1.0 release + * Exactly the same as 1.0rc2 + +Sun Dec 14 17:10:35 2008 Google Inc. + + * google-perftools: version 1.0rc2 release + * Fix compile error on 64-bit systems (casting ptr to int) (csilvers) + +Thu Dec 11 16:01:32 2008 Google Inc. + + * google-perftools: version 1.0rc1 release + * Replace API for selectively disabling heap-checker in code (sanjay) + * Add a pre-mmap hook (daven, adlr) + * Add MallocExtension interface to set memory-releasing rate (fikes) + * Augment pprof to allow any string ending in /pprof/profile (csilvers) + * PORTING: Rewrite -- and fix -- malloc patching for windows (dvitek) + * PORTING: Add nm-pdb and addr2line-pdb for use by pprof (dvitek) + * PORTING: Improve cygwin and mingw support (jperkins, csilvers) + * PORTING: Fix pprof for mac os x, other pprof improvements (csilvers) + * PORTING: Fix some PPC bugs in our locking code (anton.blanchard) + * A new unittest, smapling_test, to verify tcmalloc-profiles (csilvers) + * Turn off TLS for gcc < 4.1.2, due to a TLS + -fPIC bug (csilvers) + * Prefer __builtin_frame_address to assembly for stacktraces (nlewycky) + * Separate tcmalloc.cc out into multiple files -- finally! (kash) + * Make our locking code work with -fPIC on 32-bit x86 (aruns) + * Fix an initialization-ordering bug for tcmalloc/profiling (csilvers) + * Use "initial exec" model of TLS to speed up tcmalloc (csilvers) + * Enforce 16-byte alignment for tcmalloc, for SSE (sanjay) + +Tue Sep 23 08:56:31 2008 Google Inc. + + * google-perftools: version 0.99.2 release + * COMPILE FIX: add #include needed for FreeBSD and OS X (csilvers) + +Sat Sep 20 09:37:18 2008 Google Inc. + + * google-perftools: version 0.99.1 release + * BUG FIX: look for nm, etc in /usr/bin, not /usr/crosstool (csilvers) + +Thu Sep 18 16:00:27 2008 Google Inc. + + * google-perftools: version 0.99 release + * Add IsHeapProfileRunning (csilvers) + * Add C shims for some of the C++ header files (csilvers) + * Fix heap profile file clean-up logic (maxim) + * Rename linuxthreads.c to .cc for better compiler support (csilvers) + * Add source info to disassembly in pprof (sanjay) + * Use open instead of fopen to avoid memory alloc (csilvers) + * Disable malloc extensions when running under valgrind (kcc) + * BUG FIX: Fix out-of-bound error by reordering a check (larryz) + * Add Options struct to ProfileData (cgd) + * Correct PC-handling of --base in pprof (csilvers) + * Handle 1 function occurring twice in an image (sanjay) + * Improve stack-data cleaning (maxim) + * Use 'struct Foo' to make header C compatible (csilvers) + * Add 'total' line to pprof --text (csilvers) + * Pre-allocate buffer for heap-profiler to avoid OOM errors (csilvers) + * Allow a few more env-settings to control tcmalloc (csilvers) + * Document some of the issues involving thread-local storage (csilvers) + * BUG FIX: Define strtoll and friends for windows (csilvers) + +Mon Jun 9 16:47:03 2008 Google Inc. + + * google-perftools: version 0.98 release + * Add ProfilerStartWithOptions() (cgd) + * Change tcmalloc_minimal to not do any stack-tracing at all (csilvers) + * Prefer mmap to sbrk for 64-buit debug mode (sanjay) + * Fix accounting for some tcmalloc stats (sanjay) + * Use setrlimit() to keep unittests from killing the machine (odo) + * Fix a bug when sbrk-ing near address 4G (csilvers) + * Make MallocHook thread-safe (jyasskin) + * Fix windows build for MemoryBarrier (jyasskin) + * Fix CPU-profiler docs to mention correct libs (csilvers) + * Fix for GetHeapProfile() when heap-profiling is off (maxim) + * Avoid realloc resizing ping-pongs using hysteresis (csilvers) + * Add --callgrind output support to pprof (klimek) + * Fix profiler.h and heap-profiler.h to be C-compatible (csilvers) + * Break malloc_hook.h into two parts to reduce dependencies (csilvers) + * Better handle systems that don't implement mmap (csilvers) + * PORTING: disable system_alloc_unittest for msvc (csilvers) + * PORTING: Makefile tweaks to build better on cygwin (csilvers) + +Mon Apr 21 15:20:52 2008 Google Inc. + + * google-perftools: version 0.97 release + * Refactor GetHeapProfile to avoid using malloc (maxim) + * Fix heap-checker and heap-profiler hook interactions (maxim) + * Fix a data race in MemoryRegionMap::Lock (jyasskin) + * Improve thread-safety of leak checker (maxim) + * Fix mmap profile to no longer deadlock (maxim) + * Fix rpm to have devel package depend on non-devel (csilvers) + * PORTING: Fix clock-speed detection for Mac OS X (csilvers) + +Tue Mar 18 14:30:44 2008 Google Inc. + + * google-perftools: version 0.96 release + * major atomicops rewrite; fixed atomic ops code for linux/ppc (vchen) + * nix the stacktrace library; now build structure is simpler (csilvers) + * Speed up heap-checker, and reduce extraneous logging (maxim) + * Improve itimer code for NPTL case (cgd) + * Add source code annotations for use by valgrind, etc (kcc) + * PORTING: Fix high resolution timers for Mac OS X (adlr) + +Tue Feb 19 12:01:31 2008 Google Inc. + + * google-perftools: version 0.95.1 release (bugfix release) + * x86_64 compile-fix: nix pread64 and pwrite64 (csilvers) + * more heap-checker debug logging (maxim) + * minor improvement to x86_64 CycleClock (gpike) + +Tue Feb 12 12:28:32 2008 Google Inc. + + * google-perftools: version 0.95 release + * Better -- not perfect -- support for linux-ppc (csilvers) + * Fix race condition in libunwind stacktrace (aruns) + * Speed up x86 spinlock locking (m3b) + * Improve heap-checker performance (maxim) + * Heap checker traverses more ptrs inside heap-alloced objects (maxim) + * Remove deprecated ProfilerThreadState function (cgd) + * Update libunwind documentation for statically linked binaries (aruns) + +Mon Dec 3 23:51:54 2007 Google Inc. + + * google-perftools: version 0.94.1 release (bugfix release) + * Fix missing #includes for x86_64 compile using libunwind (csilvers) + +Thu Nov 29 07:59:43 2007 Google Inc. + + * google-perftools: version 0.94 release + * PORTING: MinGW/Msys support -- runs same code as MSVC does (csilvers) + * PORTING: Add NumCPUs support for Mac OS X (csilvers) + * Work around a sscanf bug in glibc(?) (waldemar) + * Fix Windows MSVC bug triggered by thread deletion (csilvers) + * Fix bug that triggers in MSVC /O2: missing volatile (gpike) + * March-of-time support: quiet warnings/errors for gcc 4.2, OS X 10.5 + * Modify pprof so it works without nm: useful for windows (csilvers) + * pprof: Support filtering for CPU profiles (cgd) + * Bugfix: have realloc report to hooks in all situations (maxim) + * Speed improvement: replace slow memcpy with std::copy (soren) + * Speed: better iterator efficiency in RecordRegionRemoval (soren) + * Speed: minor speed improvements via better bitfield alignment (gpike) + * Documentation: add documentation of binary profile output (cgd) + +Fri Aug 17 12:32:56 2007 Google Inc. + + * 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. + + * 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 + +Wed Apr 18 16:43:55 2007 Google Inc. + + * 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. + + * google-perftools: version 0.90 release + * (As the version-number jump hints, this is a major new release: + almost every piece of functionality was rewritten. I can't do + justice to all the changes, but will concentrate on highlights.) + *** USER-VISIBLE CHANGES: + * Ability to "release" unused memory added to tcmalloc + * Exposed more tweaking knobs via environment variables (see docs) + * pprof tries harder to map addresses to functions + * tcmalloc_minimal compiles and runs on FreeBSD 6.0 and Solaris 10 + *** INTERNAL CHANGES: + * Much better 64-bit support + * Better multiple-processor support (e.g. multicore contention tweaks) + * Support for recent kernel ABI changes (e.g. new arg to mremap) + * Addition of spinlocks to tcmalloc to reduce contention cost + * Speed up tcmalloc by using __thread on systems that support TLS + * Total redesign of heap-checker to improve liveness checking + * More portable stack-frame analysis -- no more hard-coded constants! + * Disentangled heap-profiler code and heap-checker code + * Several new unittests to test, e.g., thread-contention costs + * Lots of small (but important!) bug fixes: e.g., fixing GetPC on amd64 + *** KNOWN PROBLEMS: + * 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 Jun 14 15:11:14 2006 Google Inc. + + * 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) + +Thu Apr 13 20:59:09 2006 Google Inc. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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. + + * 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/trunk/3rdparty/gperftools-2-fit/INSTALL b/trunk/3rdparty/gperftools-2-fit/INSTALL new file mode 100644 index 000000000..cfb6b971a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/INSTALL @@ -0,0 +1,564 @@ +Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + + +Perftools-Specific Install Notes +================================ + +*** Building from source repository + +As of 2.1 gperftools does not have configure and other autotools +products checked into it's source repository. This is common practice +for projects using autotools. + +NOTE: Source releases (.tar.gz that you download from +code.google.com/p/gperftools) still have all required files just as +before. Nothing has changed w.r.t. building from .tar.gz releases. + +But, in order to build gperftools checked out from subversion +repository you need to have autoconf, automake and libtool +installed. And before running ./configure you have to generate it (and +a bunch of other files) by running ./autogen.sh script. That script +will take care of calling correct autotools programs in correct order. + +If you're maintainer then it's business as usual too. Just run make +dist (or, preferably, make distcheck) and it'll produce .tar.gz or +.tar.bz2 with all autotools magic already included. So that users can +build our software without having autotools. + + +*** NOTE FOR 64-BIT LINUX SYSTEMS + +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 +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.) + +For that reason, if you use a 64-bit system, we strongly recommend you +install libunwind before trying to configure or install gperftools. +libunwind can be found at + + http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz + +Even if you already have libunwind installed, you should check the +version. Versions older than this will not work properly; too-new +versions introduce new code that does not work well with perftools +(because libunwind can call malloc, which will lead to deadlock). + +There have been reports of crashes with libunwind 0.99 (see +http://code.google.com/p/gperftools/issues/detail?id=374). +Alternately, you can use a more recent libunwind (e.g. 1.0.1) at the +cost of adding a bit of boilerplate to your code. For details, see +http://groups.google.com/group/google-perftools/msg/2686d9f24ac4365f + + 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 + 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. + + Also, if you link binaries statically, make sure that you add + -Wl,--eh-frame-hdr to your linker options. This is required so that + libunwind can find the information generated by the compiler + required for stack unwinding. + + Using -static is rare, though, so unless you know this will affect + you it probably won't. + +If you cannot or do not wish to install libunwind, you can still try +to use the built-in stack unwinder. The built-in stack unwinder +requires that your application, the tcmalloc library, and system +libraries like libc, all be compiled with a frame pointer. This is +*not* the default for x86-64. + +If you are on x86-64 system, know that you have a set of system +libraries with frame-pointers enabled, and compile all your +applications with -fno-omit-frame-pointer, then you can enable the +built-in perftools stack unwinder by passing the +--enable-frame-pointers flag to configure. + +Even with the use of libunwind, there are still known problems with +stack unwinding on 64-bit systems, particularly x86-64. See the +"64-BIT ISSUES" section in README. + +If you encounter problems, try compiling perftools with './configure +--enable-frame-pointers'. Note you will need to compile your +application with frame pointers (via 'gcc -fno-omit-frame-pointer +...') in this case. + + +*** TCMALLOC LARGE PAGES: TRADING TIME FOR SPACE + +You can set a compiler directive that makes tcmalloc faster, at the +cost of using more space (due to internal fragmentation). + +Internally, tcmalloc divides its memory into "pages." The default +page size is chosen to minimize memory use by reducing fragmentation. +The cost is that keeping track of these pages can cost tcmalloc time. +We've added a new flag to tcmalloc that enables a larger page size. +In general, this will increase the memory needs of applications using +tcmalloc. However, in many cases it will speed up the applications +as well, particularly if they allocate and free a lot of memory. We've +seen average speedups of 3-5% on Google applications. + +To build libtcmalloc with large pages you need to use the +--with-tcmalloc-pagesize=ARG configure flag, e.g.: + + ./configure --with-tcmalloc-pagesize=32 + +The ARG argument can be 4, 8, 16, 32, 64, 128 or 256 which sets the +internal page size to 4K, 8K, 16K, 32K, 64K, 128K and 256K respectively. +The default is 8K. + + +*** SMALL TCMALLOC CACHES: TRADING SPACE FOR TIME + +You can set a compiler directive that makes tcmalloc use less memory +for overhead, at the cost of some time. + +Internally, tcmalloc keeps information about some of its internal data +structures in a cache. This speeds memory operations that need to +access this internal data. We've added a new, experimental flag to +tcmalloc that reduces the size of this cache, decresaing the memory +needs of applications using tcmalloc. + +This feature is still very experimental; it's not even a configure +flag yet. To build libtcmalloc with smaller internal caches, run + + ./configure CXXFLAGS=-DTCMALLOC_SMALL_BUT_SLOW + +(or add -DTCMALLOC_SMALL_BUT_SLOW to your existing CXXFLAGS argument). + + +*** NOTE FOR ___tls_get_addr ERROR + +When compiling perftools on some old systems, like RedHat 8, you may +get an error like this: + ___tls_get_addr: symbol not found + +This means that you have a system where some parts are updated enough +to support Thread Local Storage, but others are not. The perftools +configure script can't always detect this kind of case, leading to +that error. To fix it, just comment out the line + #define HAVE_TLS 1 +in your config.h file before building. + + +*** TCMALLOC AND DLOPEN + +To improve performance, we use the "initial exec" model of Thread +Local Storage in tcmalloc. The price for this is the library will not +work correctly if it is loaded via dlopen(). This should not be a +problem, since loading a malloc-replacement library via dlopen is +asking for trouble in any case: some data will be allocated with one +malloc, some with another. If, for some reason, you *do* need to use +dlopen on tcmalloc, the easiest way is to use a version of tcmalloc +with TLS turned off; see the ___tls_get_addr note above. + + +*** COMPILING ON NON-LINUX SYSTEMS + +Perftools has been tested on the following systems: + FreeBSD 6.0 (x86) + FreeBSD 8.1 (x86_64) + Linux CentOS 5.5 (x86_64) + Linux Debian 4.0 (PPC) + Linux Debian 5.0 (x86) + Linux Fedora Core 3 (x86) + Linux Fedora Core 4 (x86) + Linux Fedora Core 5 (x86) + Linux Fedora Core 6 (x86) + Linux Fedora Core 13 (x86_64) + Linux Fedora Core 14 (x86_64) + Linux RedHat 9 (x86) + Linux Slackware 13 (x86_64) + Linux Ubuntu 6.06.1 (x86) + Linux Ubuntu 6.06.1 (x86_64) + Linux Ubuntu 10.04 (x86) + Linux Ubuntu 10.10 (x86_64) + Mac OS X 10.3.9 (Panther) (PowerPC) + Mac OS X 10.4.8 (Tiger) (PowerPC) + Mac OS X 10.4.8 (Tiger) (x86) + Mac OS X 10.5 (Leopard) (x86) + Mac OS X 10.6 (Snow Leopard) (x86) + Solaris 10 (x86_64) + Windows XP, Visual Studio 2003 (VC++ 7.1) (x86) + Windows XP, Visual Studio 2005 (VC++ 8) (x86) + Windows XP, Visual Studio 2005 (VC++ 9) (x86) + Windows XP, Visual Studio 2005 (VC++ 10) (x86) + Windows XP, MinGW 5.1.3 (x86) + Windows XP, Cygwin 5.1 (x86) + +It works in its full generality on the Linux systems +tested (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 cpu-profiler also works +fairly widely. However, the heap-profiler and heap-checker are not +yet as widely supported. In general, the 'configure' script will +detect what OS you are building for, and only build the components +that work on that OS. + +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. + +** FreeBSD: + + The following binaries build and run successfully (creating + libtcmalloc_minimal.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 profiler_unittest.sh + % ./tcmalloc_minimal_unittest # to run this test + % [etc] # to run other tests + + Three caveats: first, 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. + + Second, 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, the cpu profiler is entirely safe to use. + + Third, perftools depends on /proc to get shared library + information. If you are running a FreeBSD system without proc, + perftools will not be able to map addresses to functions. Some + unittests will fail as a result. + + Finally, the new test introduced in perftools-1.2, + profile_handler_unittest, fails on FreeBSD. It has something to do + with how the itimer works. The cpu profiler test passes, so I + believe the functionality is correct and the issue is with the test + somehow. If anybody is an expert on itimers and SIGPROF in + FreeBSD, and would like to debug this, I'd be glad to hear the + results! + + libtcmalloc.so successfully builds, and the "advanced" tcmalloc + functionality all works except for the leak-checker, which has + Linux-specific code: + % make heap-profiler_unittest.sh maybe_threads_unittest.sh \ + tcmalloc_unittest tcmalloc_both_unittest \ + tcmalloc_large_unittest # THESE WORK + % make -k heap-checker_unittest.sh \ + heap-checker-death_unittest.sh # THESE DO NOT + + Note that unless you specify --enable-heap-checker explicitly, + 'make' will not build the heap-checker unittests on a FreeBSD + system. + + I have not tested other *BSD systems, but they are probably similar. + +** Mac OS X: + + I've tested OS X 10.5 [Leopard], OS X 10.4 [Tiger] and OS X 10.3 + [Panther] on both intel (x86) and PowerPC systems. For Panther + systems, perftools does not work at all: it depends on a header + file, OSAtomic.h, which is new in 10.4. (It's possible to get the + code working for Panther/i386 without too much work; if you're + interested in exploring this, drop an e-mail.) + + For the other seven 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. + + In addition, it appears OS X regularly fails profiler_unittest.sh + in the "thread" test (in addition to occassionally failing in the + "fork" test). It looks like OS X often delivers the profiling + signal to the main thread, even when it's sleeping, rather than + spawned threads that are doing actual work. If anyone knows + details of how OS X handles SIGPROF (via setitimer()) events with + threads, and has insight into this problem, please send mail to + google-perftools@googlegroups.com. + +** Solaris 10 x86: + + I've only tested using the GNU C++ compiler, not the Sun C++ + compiler. Using g++ requires setting the PATH appropriately when + configuring. + + % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin ./configure + % PATH=${PATH}:/usr/sfw/bin/:/usr/ccs/bin make [...] + + Again, the binaries and libraries that successfully build are + exactly the same as for FreeBSD. (However, while libprofiler.so can + be used to generate 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.) See that + section for a list of binaries, and instructions on building them. + +** Windows (MSVC, Cygwin, and MinGW): + + Work on Windows is rather preliminary: only tcmalloc_minimal is + supported. + + We haven't found a good way to get stack traces in release mode on + windows (that is, when FPO is enabled), so the heap profiling may + not be reliable in that case. Also, heap-checking and CPU profiling + do not yet work at all. But as in other ports, the basic tcmalloc + library functionality, overriding malloc and new and such (and even + windows-specific functions like _aligned_malloc!), is working fine, + at least with VC++ 7.1 (Visual Studio 2003) through VC++ 10.0, + in both debug and release modes. See README.windows for + instructions on how to install on Windows using Visual Studio. + + Cygwin can compile some but not all of perftools. Furthermore, + there is a problem with exception-unwinding in cygwin (it can call + malloc, which can call the exception-unwinding-setup code, which + can lead to an infinite loop). I've comitted a workaround to the + exception unwinding problem, but it only works in debug mode and + when statically linking in tcmalloc. I hope to have a more proper + fix in a later release. To configure under cygwin, run + + ./configure --disable-shared CXXFLAGS=-g && make + + Most of cygwin will compile (cygwin doesn't allow weak symbols, so + the heap-checker and a few other pieces of functionality will not + compile). 'make' will compile those libraries and tests that can + be compiled. You can run 'make check' to make sure the basic + functionality is working. I've heard reports that some versions of + cygwin fail calls to pthread_join() with EINVAL, causing several + tests to fail. If you have any insight into this, please mail + google-perftools@googlegroups.com. + + This Windows functionality is also available using MinGW and Msys, + In this case, you can use the regular './configure && make' + process. 'make install' should also work. The Makefile will limit + itself to those libraries and binaries that work on windows. + + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +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. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + 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 +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +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'. + + 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. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' 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. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + 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 +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +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 +`--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: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +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 +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +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'. +`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. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + 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 +them in the `configure' command line, using `VAR=value'. For example: + + ./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). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/trunk/3rdparty/gperftools-2-fit/Makefile.am b/trunk/3rdparty/gperftools-2-fit/Makefile.am new file mode 100644 index 000000000..bc61f62ce --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/Makefile.am @@ -0,0 +1,1508 @@ +## Process this file with automake to produce Makefile.in + +# Note: for every library we create, we're explicit about what symbols +# we export. In order to avoid complications with C++ mangling, we always +# use the regexp for of specifying symbols. + +# Make sure that when we re-make ./configure, we get the macros we need +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +# This is so we can #include +AM_CPPFLAGS = -I$(top_srcdir)/src + +if !WITH_STACK_TRACE +AM_CPPFLAGS += -DNO_TCMALLOC_SAMPLES +endif !WITH_STACK_TRACE + +# 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 + +# On i386, -mmmx is needed for the mmx-based instructions in +# atomicops-internal-x86.h. Also as of gcc 4.6, -fomit-frame-pointer +# is the default. Since we must always have frame pointers for I386 +# in order to generate backtraces we now specify -fno-omit-frame-pointer +# by default. +if I386 +AM_CXXFLAGS += -mmmx +AM_CXXFLAGS += -fno-omit-frame-pointer +endif I386 +endif GCC +if HAVE_W_NO_UNUSED_RESULT +AM_CXXFLAGS += -Wno-unused-result +endif HAVE_W_NO_UNUSED_RESULT +if HAVE_SIZED_DEALLOCATION +AM_CXXFLAGS += -fsized-deallocation +endif HAVE_SIZED_DEALLOCATION +if HAVE_F_ALIGNED_NEW +AM_CXXFLAGS += -faligned-new +endif HAVE_F_ALIGNED_NEW + +# The -no-undefined flag allows libtool to generate shared libraries for +# Cygwin and MinGW. LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug. +AM_LDFLAGS = -no-undefined $(LIBSTDCXX_LA_LINKER_FLAG) + +# These are x86-specific, having to do with frame-pointers. In +# particular, some x86_64 systems do not insert frame pointers by +# default (all i386 systems that I know of, do. I don't know about +# non-x86 chips). We need to tell perftools what to do about that. +if OMIT_FP_BY_DEFAULT +if !ENABLE_FRAME_POINTERS +AM_CXXFLAGS += -DNO_FRAME_POINTER +endif !ENABLE_FRAME_POINTERS +endif OMIT_FP_BY_DEFAULT + +# respect --enable-frame-pointers regardless of architecture +if ENABLE_FRAME_POINTERS +AM_CXXFLAGS += -fno-omit-frame-pointer +endif ENABLE_FRAME_POINTERS + +# For windows systems (at least, mingw), we need to tell all our +# tests to link in libtcmalloc using -u. This is because libtcmalloc +# accomplishes its tasks via patching, leaving no work for the linker +# to identify, so the linker will ignore libtcmalloc by default unless +# we explicitly create a dependency via -u. +TCMALLOC_FLAGS = +if MINGW +TCMALLOC_FLAGS += -Wl,-u__tcmalloc +endif MINGW + +# If we have objcopy, make malloc/free/etc weak symbols. That way folks +# can override our malloc if they want to (they can still use tc_malloc). +# Note: the weird-looking symbols are the c++ memory functions: +# (in order) new, new(nothrow), new[], new[](nothrow), delete, delete[] +# In theory this will break if mangling changes, but that seems pretty +# unlikely at this point. Just in case, I throw in versions with an +# extra underscore as well, which may help on OS X. +if HAVE_OBJCOPY_WEAKEN +WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree \ + -W memalign -W posix_memalign -W valloc -W pvalloc \ + -W aligned_alloc \ + -W malloc_stats -W mallopt -W mallinfo -W nallocx \ + -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t \ + -W _ZdlPv -W _ZdaPv \ + -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \ + -W __ZdlPv -W __ZdaPv +else +WEAKEN = : +endif !HAVE_OBJCOPY_WEAKEN + +LIBS_TO_WEAKEN = + +perftoolsincludedir = $(includedir)/gperftools +# The .h files you want to install (that is, .h files that people +# who install this package can include in their own applications.) +# We'll add to this later, on a library-by-library basis +perftoolsinclude_HEADERS = +# tcmalloc.h is a special case, because it's a .h.in file +nodist_perftoolsinclude_HEADERS = src/gperftools/tcmalloc.h +noinst_HEADERS = src/gperftools/tcmalloc.h.in + +# This is provided for backwards compatibility. It is populated by +# files that just forward to the canonical location in +# perftoolsincludedir. +googleincludedir = $(includedir)/google +googleinclude_HEADERS = \ + src/google/heap-checker.h \ + src/google/heap-profiler.h \ + src/google/malloc_extension.h \ + src/google/malloc_extension_c.h \ + src/google/malloc_hook.h \ + src/google/malloc_hook_c.h \ + src/google/profiler.h \ + src/google/stacktrace.h \ + src/google/tcmalloc.h + +# This is for HTML and other documentation you want to install. +# Add your documentation files (in doc/) in addition to these +# top-level boilerplate files. Also add a TODO file if you have one. +# We'll add to this later, on a library-by-library basis +dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README README_windows.txt \ + TODO ChangeLog.old + +# The libraries (.so's) you want to install +# We'll add to this later, on a library-by-library basis +lib_LTLIBRARIES = +# This is for 'convenience libraries' -- basically just a container for sources +noinst_LTLIBRARIES = +## The location of the windows project file for each binary we make +WINDOWS_PROJECTS = gperftools.sln + +# unittests you want to run when people type 'make check'. +# Note: tests cannot take any arguments! +# In theory, unittests that are scripts should be added to check_SCRIPTS +# instead. But check_SCRIPTS is definitely a second-class testing mechanims: +# it don't get TESTS_ENVIRONMENT, and it doesn't get success/failure counting +# (in fact, a script failure aborts all the rest of the tests, even with -k). +# So, for scripts, we add the script to tests, and also put in an empty +# rule so automake doesn't try to build the script as a C binary. +TESTS = +# 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. +TESTS_ENVIRONMENT = +# All script tests should be added here +noinst_SCRIPTS = +# If your test calls another program that, like the test itself, shouldn't +# be installed, add it here. (Stuff in TESTS is automatically added later). +noinst_PROGRAMS = + +# Binaries we might build that should be installed +bin_PROGRAMS = + +# This is my own var, used for extra libraries I make that I need installed +EXTRA_INSTALL = + +## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS + +dist_doc_DATA += docs/index.html docs/designstyle.css + + +### ------- library routines, in src/base + +# This is a 'convenience library' -- it's not actually installed or anything +LOGGING_INCLUDES = src/base/logging.h \ + src/base/commandlineflags.h \ + src/base/basictypes.h \ + src/base/dynamic_annotations.h +noinst_LTLIBRARIES += liblogging.la +liblogging_la_SOURCES = src/base/logging.cc \ + src/base/dynamic_annotations.c \ + $(LOGGING_INCLUDES) + +SYSINFO_INCLUDES = src/base/sysinfo.h \ + src/getenv_safe.h \ + src/base/logging.h \ + src/base/commandlineflags.h \ + src/base/arm_instruction_set_select.h \ + src/base/basictypes.h +noinst_LTLIBRARIES += libsysinfo.la +libsysinfo_la_SOURCES = src/base/sysinfo.cc \ + $(SYSINFO_INCLUDES) +libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) + +noinst_LTLIBRARIES += libmaybe_threads.la +# .cc is conditionally added below +libmaybe_threads_la_SOURCES = src/maybe_threads.h + +# For MinGW, we use also have to use libwindows Luckily, we need the +# windows.a library in exactly the same place we need spinlock.a +# (pretty much everywhere), so we can use the same variable name for +# each. We can also optimize the MinGW rule a bit by leaving out +# files we know aren't used on windows, such as +# atomicops-internals-x86.cc. libwindows also obsoletes the need for +# other files like system_alloc.cc. +if MINGW +WINDOWS_INCLUDES = src/windows/port.h \ + src/windows/mingw.h \ + src/windows/mini_disassembler.h \ + src/windows/mini_disassembler_types.h \ + src/windows/preamble_patcher.h +noinst_LTLIBRARIES += libwindows.la +libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \ + src/windows/port.cc \ + src/windows/system-alloc.cc \ + src/windows/ia32_modrm_map.cc \ + src/windows/ia32_opcode_map.cc \ + src/windows/mini_disassembler.cc \ + src/windows/patch_functions.cc \ + src/windows/preamble_patcher.cc \ + src/windows/preamble_patcher_with_stub.cc +# patch_functions.cc uses Psapi.lib. MSVC has a #pragma for that, but not us. +libwindows_la_LIBADD = -lpsapi + +SPINLOCK_INCLUDES = src/base/spinlock.h \ + src/base/spinlock_internal.h \ + src/base/spinlock_win32-inl.h \ + src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-gcc.h \ + src/base/atomicops-internals-x86.h +noinst_LTLIBRARIES += libspinlock.la +libspinlock_la_SOURCES = src/base/spinlock.cc \ + src/base/spinlock_internal.cc \ + src/base/atomicops-internals-x86.cc \ + $(SPINLOCK_INCLUDES) + +LIBSPINLOCK = libwindows.la libspinlock.la libsysinfo.la liblogging.la + +# We also need to tell mingw that sysinfo.cc needs shlwapi.lib. +# (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. +if HAVE_PTHREAD_DESPITE_ASKING_FOR +libmaybe_threads_la_SOURCES += src/maybe_threads.cc +endif +SYSTEM_ALLOC_CC = +else !MINGW +# spinlock is the only code that uses atomicops. +SPINLOCK_INCLUDES = src/base/spinlock.h \ + src/base/spinlock_internal.h \ + src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h + +noinst_LTLIBRARIES += libspinlock.la +libspinlock_la_SOURCES = src/base/spinlock.cc \ + src/base/spinlock_internal.cc \ + src/base/atomicops-internals-x86.cc \ + $(SPINLOCK_INCLUDES) +libspinlock_la_LIBADD = $(NANOSLEEP_LIBS) +# spinlock also needs NumCPUs, from libsysinfo, which in turn needs liblogging +LIBSPINLOCK = libspinlock.la libsysinfo.la liblogging.la + +TCMALLOC_CC = src/tcmalloc.cc +libmaybe_threads_la_SOURCES += 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.vcxproj +# 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.vcxproj +LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \ + src/base/basictypes.h \ + src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ + $(SPINLOCK_INCLUDES) \ + $(LOGGING_INCLUDES) +low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \ + src/malloc_hook.cc \ + src/tests/low_level_alloc_unittest.cc \ + $(LOW_LEVEL_ALLOC_UNITTEST_INCLUDES) +# By default, MallocHook takes stack traces for use by the heap-checker. +# We don't need that functionality here, so we turn it off to reduce deps. +low_level_alloc_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES +low_level_alloc_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la + +TESTS += atomicops_unittest +ATOMICOPS_UNITTEST_INCLUDES = src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + $(LOGGING_INCLUDES) +atomicops_unittest_SOURCES = src/tests/atomicops_unittest.cc \ + $(ATOMICOPS_UNITTEST_INCLUDES) +atomicops_unittest_LDADD = $(LIBSPINLOCK) + + +### ------- stack trace + +if WITH_STACK_TRACE + +### The header files we use. We divide into categories based on directory +S_STACKTRACE_INCLUDES = src/stacktrace_impl_setup-inl.h \ + src/stacktrace_generic-inl.h \ + src/stacktrace_generic_fp-inl.h \ + src/stacktrace_libgcc-inl.h \ + src/stacktrace_libunwind-inl.h \ + src/stacktrace_arm-inl.h \ + src/stacktrace_powerpc-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h \ + src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h \ + src/stacktrace_instrument-inl.h \ + src/base/elf_mem_image.h \ + src/base/vdso_support.h + +SG_STACKTRACE_INCLUDES = src/gperftools/stacktrace.h +STACKTRACE_INCLUDES = $(S_STACKTRACE_INCLUDES) $(SG_STACKTRACE_INCLUDES) +perftoolsinclude_HEADERS += $(SG_STACKTRACE_INCLUDES) + +### Making the library +noinst_LTLIBRARIES += libstacktrace.la +libstacktrace_la_SOURCES = src/stacktrace.cc \ + src/base/elf_mem_image.cc \ + src/base/vdso_support.cc \ + $(STACKTRACE_INCLUDES) +libstacktrace_la_LIBADD = $(UNWIND_LIBS) $(LIBSPINLOCK) +STACKTRACE_SYMBOLS = '(GetStackTrace|GetStackFrames|GetStackTraceWithContext|GetStackFramesWithContext)' +libstacktrace_la_LDFLAGS = -export-symbols-regex $(STACKTRACE_SYMBOLS) $(AM_LDFLAGS) + +noinst_LTLIBRARIES += libfake_stacktrace_scope.la +libfake_stacktrace_scope_la_SOURCES = src/fake_stacktrace_scope.cc + +### Unittests +TESTS += stacktrace_unittest +STACKTRACE_UNITTEST_INCLUDES = src/config_for_unittests.h \ + src/base/commandlineflags.h \ + $(STACKTRACE_INCLUDES) \ + $(LOGGING_INCLUDES) +stacktrace_unittest_SOURCES = src/tests/stacktrace_unittest.cc \ + $(STACKTRACE_UNITTEST_INCLUDES) +stacktrace_unittest_LDADD = libstacktrace.la liblogging.la libfake_stacktrace_scope.la + +### Documentation +dist_doc_DATA += + +endif WITH_STACK_TRACE + +### ------- pprof + +# If we are not compiling with stacktrace support, pprof is worthless +if WITH_STACK_TRACE + +bin_SCRIPTS = pprof-symbolize + +pprof-symbolize : $(top_srcdir)/src/pprof + cp -p $(top_srcdir)/src/pprof $@ + +### Unittests + +check_SCRIPTS = pprof_unittest +pprof_unittest: $(top_srcdir)/src/pprof + $(top_srcdir)/src/pprof -test + +# Let unittests find pprof if they need to run it +TESTS_ENVIRONMENT += PPROF_PATH=$(top_srcdir)/src/pprof + +if INSTALL_PPROF +bin_SCRIPTS += src/pprof +dist_man_MANS = docs/pprof.1 +dist_doc_DATA += docs/pprof_remote_servers.html +endif INSTALL_PPROF + +### Documentation + +# On MSVC, we need our own versions of addr2line and nm to work with pprof. +WINDOWS_PROJECTS += vsprojects/nm-pdb/nm-pdb.vcxproj +WINDOWS_PROJECTS += vsprojects/addr2line-pdb/addr2line-pdb.vcxproj +# This is a slight abuse of WINDOWS_PROJECTS, but not much +WINDOWS_PROJECTS += src/windows/nm-pdb.c \ + src/windows/addr2line-pdb.c + +endif WITH_STACK_TRACE + +### ------- tcmalloc_minimal (thread-caching malloc) + +### The header files we use. We divide into categories based on directory +S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ + src/internal_logging.h \ + src/system-alloc.h \ + src/packed-cache-inl.h \ + $(SPINLOCK_INCLUDES) \ + src/tcmalloc_guard.h \ + src/base/commandlineflags.h \ + src/base/basictypes.h \ + src/pagemap.h \ + src/sampler.h \ + src/central_freelist.h \ + src/linked_list.h \ + src/libc_override.h \ + src/libc_override_gcc_and_weak.h \ + src/libc_override_glibc.h \ + src/libc_override_osx.h \ + src/libc_override_redefine.h \ + src/page_heap.h \ + src/page_heap_allocator.h \ + src/span.h \ + src/static_vars.h \ + src/symbolize.h \ + src/thread_cache.h \ + src/stack_trace_table.h \ + src/base/thread_annotations.h \ + src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h +SG_TCMALLOC_MINIMAL_INCLUDES = src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h \ + src/gperftools/nallocx.h +TCMALLOC_MINIMAL_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES) $(SG_STACKTRACE_INCLUDES) +perftoolsinclude_HEADERS += $(SG_TCMALLOC_MINIMAL_INCLUDES) + +### Making the library + +noinst_LTLIBRARIES += libtcmalloc_minimal_internal.la +libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \ + src/internal_logging.cc \ + $(SYSTEM_ALLOC_CC) \ + src/memfs_malloc.cc \ + src/central_freelist.cc \ + src/page_heap.cc \ + src/sampler.cc \ + src/span.cc \ + src/stack_trace_table.cc \ + src/static_vars.cc \ + src/symbolize.cc \ + src/thread_cache.cc \ + src/malloc_hook.cc \ + src/malloc_extension.cc \ + $(TCMALLOC_MINIMAL_INCLUDES) +# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal. +libtcmalloc_minimal_internal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \ + -DNO_HEAP_CHECK \ + -DNDEBUG \ + $(AM_CXXFLAGS) +libtcmalloc_minimal_internal_la_LDFLAGS = $(AM_LDFLAGS) +libtcmalloc_minimal_internal_la_LIBADD = $(LIBSPINLOCK) libmaybe_threads.la + +lib_LTLIBRARIES += libtcmalloc_minimal.la +WINDOWS_PROJECTS += vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj +libtcmalloc_minimal_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_MINIMAL_INCLUDES) +libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \ + $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS) +# -version-info gets passed to libtool +libtcmalloc_minimal_la_LDFLAGS = -version-info @TCMALLOC_SO_VERSION@ $(AM_LDFLAGS) +libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la + +# For windows, we're playing around with trying to do some stacktrace +# support even with libtcmalloc_minimal. For everyone else, though, +# we turn off all stack-trace activity for libtcmalloc_minimal. +# TODO(csilvers): when we're done experimenting, do something principled here +if MINGW +LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la libstacktrace.la +else !MINGW +LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la +endif !MINGW + +LIBS_TO_WEAKEN += libtcmalloc_minimal.la + +### Unittests + +# Commented out for the moment because malloc(very_big_num) is broken in +# standard libc! At least, in some situations, some of the time. +## TESTS += malloc_unittest +## MALLOC_UNITEST_INCLUDES = src/gperftools/malloc_extension.h \ +## src/gperftools/malloc_hook.h \ +## src/gperftools/malloc_hook_c.h \ +## src/malloc_hook-inl.h \ +## src/malloc_hook_mmap_linux.h \ +## src/malloc_hook_mmap_freebsd.h \ +## src/base/basictypes.h \ +## src/maybe_threads.h +## malloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ +## src/malloc_hook.cc \ +## src/malloc_extension.cc \ +## $(MAYBE_THREADS_CC) \ +## $(MALLOC_UNITTEST_INCLUDES) +## malloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +## malloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +## malloc_unittest_LDADD = $(PTHREAD_LIBS) + +TESTS += tcmalloc_minimal_unittest +WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj +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) $(AM_CXXFLAGS) +tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +tcmalloc_minimal_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) \ + liblogging.la $(PTHREAD_LIBS) + +# lets make sure we exerice ASSERTs in at least in statically linked +# configuration +TESTS += tcm_min_asserts_unittest +tcm_min_asserts_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + $(libtcmalloc_minimal_internal_la_SOURCES) \ + $(libtcmalloc_minimal_la_SOURCES) \ + $(TCMALLOC_UNITTEST_INCLUDES) +tcm_min_asserts_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES -DNO_HEAP_CHECK \ + $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcm_min_asserts_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcm_min_asserts_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la \ + liblogging.la $(PTHREAD_LIBS) + +TESTS += tcmalloc_minimal_large_unittest +WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj +tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc +tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += tcmalloc_minimal_large_heap_fragmentation_unittest +tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc +tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +# This tests it works to LD_PRELOAD libtcmalloc (tests maybe_threads.cc) +# In theory this should work under mingw, but mingw has trouble running +# shell scripts that end in .exe. And it doesn't seem to build shared +# libraries anyway (so can't be LD_PRELOADed) -- in fact, anybody who +# chooses not to build shared libraries won't be able to run this test. +# TODO(csilvers): figure out how to nix ".exe" or otherwise work under mingw +if !MINGW +if !ENABLE_STATIC +TESTS += maybe_threads_unittest.sh$(EXEEXT) +maybe_threads_unittest_sh_SOURCES = src/tests/maybe_threads_unittest.sh +noinst_SCRIPTS += $(maybe_threads_unittest_sh_SOURCES) +# This script preloads libtcmalloc, and calls two other binaries as well +# TODO(csilvers): replace by 'if ! cmp $^ $@ >/dev/null 2>&; then ...; fi' +maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) \ + $(LIBTCMALLOC_MINIMAL) \ + low_level_alloc_unittest + rm -f $@ + cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@ +endif !ENABLE_STATIC +endif !MINGW + +# These all tests components of tcmalloc_minimal + +TESTS += addressmap_unittest +WINDOWS_PROJECTS += vsprojects/addressmap_unittest/addressmap_unittest.vcxproj +ADDRESSMAP_UNITTEST_INCLUDES = src/addressmap-inl.h \ + src/base/commandlineflags.h \ + $(LOGGING_INCLUDES) +addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \ + $(ADDRESSMAP_UNITTEST_INCLUDES) +if MINGW +addressmap_unittest_SOURCES += src/windows/port.h src/windows/port.cc +endif MINGW +addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS) +addressmap_unittest_LDADD = liblogging.la + +WINDOWS_PROJECTS += vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj +if !MINGW +TESTS += system_alloc_unittest +system_alloc_unittest_SOURCES = src/config_for_unittests.h \ + src/tests/system-alloc_unittest.cc +system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +endif !MINGW + +TESTS += packed_cache_test +WINDOWS_PROJECTS += vsprojects/packed-cache_test/packed-cache_test.vcxproj +packed_cache_test_SOURCES = src/tests/packed-cache_test.cc +packed_cache_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +packed_cache_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +packed_cache_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += frag_unittest +WINDOWS_PROJECTS += vsprojects/frag_unittest/frag_unittest.vcxproj +frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h +frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +frag_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += markidle_unittest +WINDOWS_PROJECTS += vsprojects/markidle_unittest/markidle_unittest.vcxproj +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) $(AM_CXXFLAGS) +markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += current_allocated_bytes_test +WINDOWS_PROJECTS += vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj +current_allocated_bytes_test_SOURCES = src/tests/current_allocated_bytes_test.cc \ + src/config_for_unittests.h +current_allocated_bytes_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +current_allocated_bytes_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +current_allocated_bytes_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += malloc_hook_test +WINDOWS_PROJECTS += vsprojects/malloc_hook_test/malloc_hook_test.vcxproj +malloc_hook_test_SOURCES = src/tests/malloc_hook_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/gperftools/malloc_hook.h \ + src/tests/testutil.h src/tests/testutil.cc +malloc_hook_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_hook_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_hook_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += malloc_extension_test +WINDOWS_PROJECTS += vsprojects/malloc_extension_test/malloc_extension_test.vcxproj +malloc_extension_test_SOURCES = src/tests/malloc_extension_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h +malloc_extension_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_extension_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_extension_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +# This doesn't work with mingw, which links foo.a even though it +# doesn't set ENABLE_STATIC. TODO(csilvers): set enable_static=true +# in configure.ac:36? +if !MINGW +TESTS += malloc_extension_c_test +malloc_extension_c_test_SOURCES = src/tests/malloc_extension_c_test.c \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h +malloc_extension_c_test_CFLAGS = $(PTHREAD_CFLAGS) $(AM_CFLAGS) +# -ansi here is just to help ensure the code is bog-standard C. +if GCC +malloc_extension_c_test_CFLAGS += -ansi +endif GCC +malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) -lstdc++ -lm +endif !MINGW + +if !MINGW +if !OSX +TESTS += memalign_unittest +memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ + src/tcmalloc.h \ + src/config_for_unittests.h \ + src/tests/testutil.h src/tests/testutil.cc +memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +endif !OSX +endif !MINGW + +TESTS += page_heap_test +WINDOWS_PROJECTS += vsprojects/page_heap_test/page_heap_test.vcxproj +page_heap_test_SOURCES = src/tests/page_heap_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/common.h \ + src/page_heap.h +page_heap_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +page_heap_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +page_heap_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += pagemap_unittest +WINDOWS_PROJECTS += vsprojects/pagemap_unittest/pagemap_unittest.vcxproj +pagemap_unittest_SOURCES = src/tests/pagemap_unittest.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/pagemap.h +pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +pagemap_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +pagemap_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += realloc_unittest +WINDOWS_PROJECTS += vsprojects/realloc_unittest/realloc_unittest.vcxproj +realloc_unittest_SOURCES = src/tests/realloc_unittest.cc \ + src/config_for_unittests.h \ + src/base/logging.h +realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +realloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +realloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += stack_trace_table_test +WINDOWS_PROJECTS += vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj +stack_trace_table_test_SOURCES = src/tests/stack_trace_table_test.cc \ + src/config_for_unittests.h +stack_trace_table_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +stack_trace_table_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +stack_trace_table_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +TESTS += thread_dealloc_unittest +WINDOWS_PROJECTS += vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj +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) $(AM_CXXFLAGS) +thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) + +### Documentation +dist_doc_DATA += docs/tcmalloc.html \ + docs/overview.gif \ + docs/pageheap.gif \ + docs/spanmap.gif \ + docs/threadheap.gif \ + docs/t-test1.times.txt \ + docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \ + docs/tcmalloc-opspersec.vs.size.1.threads.png \ + docs/tcmalloc-opspersec.vs.size.12.threads.png \ + docs/tcmalloc-opspersec.vs.size.16.threads.png \ + docs/tcmalloc-opspersec.vs.size.2.threads.png \ + docs/tcmalloc-opspersec.vs.size.20.threads.png \ + docs/tcmalloc-opspersec.vs.size.3.threads.png \ + docs/tcmalloc-opspersec.vs.size.4.threads.png \ + docs/tcmalloc-opspersec.vs.size.5.threads.png \ + docs/tcmalloc-opspersec.vs.size.8.threads.png + +# I don't know how to say "distribute the .dot files but don't install them"; +# noinst doesn't seem to work with data. I separate them out anyway, in case +# one day we figure it out. Regardless, installing the dot files isn't the +# end of the world. +dist_doc_DATA += docs/overview.dot \ + docs/pageheap.dot \ + docs/spanmap.dot \ + docs/threadheap.dot + + +### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation) + +if WITH_DEBUGALLOC + +lib_LTLIBRARIES += libtcmalloc_minimal_debug.la +libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \ + $(TCMALLOC_MINIMAL_INCLUDES) +libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \ + -DTCMALLOC_FOR_DEBUGALLOCATION +# version_info gets passed to libtool +libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS) \ + -version-info @TCMALLOC_SO_VERSION@ +libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD) + +LIBS_TO_WEAKEN += libtcmalloc_minimal_debug.la + +### Unittests + +TESTS += tcmalloc_minimal_debug_unittest +tcmalloc_minimal_debug_unittest_SOURCES = $(tcmalloc_minimal_unittest_SOURCES) +tcmalloc_minimal_debug_unittest_CXXFLAGS = $(tcmalloc_minimal_unittest_CXXFLAGS) \ + -DDEBUGALLOCATION +tcmalloc_minimal_debug_unittest_LDFLAGS = $(tcmalloc_minimal_unittest_LDFLAGS) +tcmalloc_minimal_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) + +TESTS += malloc_extension_debug_test +malloc_extension_debug_test_SOURCES = $(malloc_extension_test_SOURCES) +malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS) +malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS) +malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) + +if !MINGW +if !OSX +TESTS += memalign_debug_unittest +memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES) +memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS) +memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS) +memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +endif !OSX +endif !MINGW + +TESTS += realloc_debug_unittest +realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES) +realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS) +realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS) +realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) + +# debugallocation_test checks that we print a proper stacktrace when +# debug-allocs fail, so we can't run it if we don't have stacktrace info. +if WITH_STACK_TRACE +TESTS += debugallocation_test.sh$(EXEEXT) +debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh +noinst_SCRIPTS += $(debugallocation_test_sh_SOURCES) +debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \ + debugallocation_test + rm -f $@ + cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@ + +# This is the sub-program used by debugallocation_test.sh +noinst_PROGRAMS += debugallocation_test +debugallocation_test_SOURCES = src/tests/debugallocation_test.cc +debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) +endif WITH_STACK_TRACE + +endif WITH_DEBUGALLOC + +if !MINGW +noinst_LTLIBRARIES += librun_benchmark.la +librun_benchmark_la_SOURCES = \ + benchmark/run_benchmark.c benchmark/run_benchmark.h + +noinst_PROGRAMS += malloc_bench malloc_bench_shared \ + binary_trees binary_trees_shared + +malloc_bench_SOURCES = benchmark/malloc_bench.cc +malloc_bench_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_bench_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +if ENABLE_STATIC +malloc_bench_LDFLAGS += -static +endif ENABLE_STATIC +malloc_bench_LDADD = librun_benchmark.la libtcmalloc_minimal.la $(PTHREAD_LIBS) + +malloc_bench_shared_SOURCES = benchmark/malloc_bench.cc +malloc_bench_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_bench_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_bench_shared_LDADD = librun_benchmark.la libtcmalloc_minimal.la $(PTHREAD_LIBS) + +if WITH_HEAP_PROFILER_OR_CHECKER + +noinst_PROGRAMS += malloc_bench_shared_full +malloc_bench_shared_full_SOURCES = benchmark/malloc_bench.cc +malloc_bench_shared_full_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_bench_shared_full_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_bench_shared_full_LDADD = librun_benchmark.la libtcmalloc.la $(PTHREAD_LIBS) + +endif WITH_HEAP_PROFILER_OR_CHECKER + +binary_trees_SOURCES = benchmark/binary_trees.cc +binary_trees_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +binary_trees_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +if ENABLE_STATIC +binary_trees_LDFLAGS += -static +endif ENABLE_STATIC +binary_trees_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) + +binary_trees_shared_SOURCES = benchmark/binary_trees.cc +binary_trees_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +binary_trees_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +binary_trees_shared_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) +endif !MINGW + +### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker) + +if WITH_HEAP_PROFILER_OR_CHECKER + +### The header files we use. We divide into categories based on directory +S_TCMALLOC_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) \ + $(LOGGING_INCLUDES) \ + src/addressmap-inl.h \ + src/raw_printer.h \ + src/base/elfcore.h \ + src/base/googleinit.h \ + src/base/linux_syscall_support.h \ + src/base/linuxthreads.h \ + src/base/stl_allocator.h \ + src/base/sysinfo.h \ + src/base/thread_lister.h \ + src/heap-profile-table.h \ + src/heap-profile-stats.h \ + src/maybe_emergency_malloc.h \ + src/emergency_malloc.h + +SG_TCMALLOC_INCLUDES = src/gperftools/heap-profiler.h \ + src/gperftools/heap-checker.h +TCMALLOC_INCLUDES = $(S_TCMALLOC_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES) \ + $(SG_TCMALLOC_INCLUDES) $(SG_STACKTRACE_INCLUDES) +perftoolsinclude_HEADERS += $(SG_TCMALLOC_INCLUDES) + +if BUILD_EMERGENCY_MALLOC +EMERGENCY_MALLOC_CC = src/emergency_malloc.cc src/emergency_malloc_for_stacktrace.cc +EMERGENCY_MALLOC_DEFINE = -DENABLE_EMERGENCY_MALLOC +else !BUILD_EMERGENCY_MALLOC +EMERGENCY_MALLOC_CC = src/fake_stacktrace_scope.cc +EMERGENCY_MALLOC_DEFINE = +endif !BUILD_EMERGENCY_MALLOC + +### Making the library + +if WITH_HEAP_CHECKER +# heap-checker-bcad is last, in hopes its global ctor will run first. +# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la, +# but that's ok; the internal/external distinction is only useful for +# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.) +HEAP_CHECKER_SOURCES = src/base/thread_lister.c \ + src/base/linuxthreads.cc \ + src/heap-checker.cc \ + src/heap-checker-bcad.cc +MAYBE_NO_HEAP_CHECK = +else !WITH_HEAP_CHECKER +HEAP_CHECKER_SOURCES = +MAYBE_NO_HEAP_CHECK = -DNO_HEAP_CHECK +endif !WITH_HEAP_CHECKER + +noinst_LTLIBRARIES += libtcmalloc_internal.la +libtcmalloc_internal_la_SOURCES = $(libtcmalloc_minimal_internal_la_SOURCES) \ + $(TCMALLOC_INCLUDES) \ + src/base/low_level_alloc.cc \ + src/heap-profile-table.cc \ + src/heap-profiler.cc \ + src/raw_printer.cc \ + $(EMERGENCY_MALLOC_CC) \ + src/memory_region_map.cc +libtcmalloc_internal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG \ + $(AM_CXXFLAGS) $(EMERGENCY_MALLOC_DEFINE) \ + $(MAYBE_NO_HEAP_CHECK) +libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS) +libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) + +lib_LTLIBRARIES += libtcmalloc.la +libtcmalloc_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_INCLUDES) \ + $(HEAP_CHECKER_SOURCES) +libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS) \ + $(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE) +libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@ +libtcmalloc_la_LIBADD = libtcmalloc_internal.la libmaybe_threads.la $(PTHREAD_LIBS) + +# same as above with without -DNDEBUG +noinst_LTLIBRARIES += libtcmalloc_internal_with_asserts.la +libtcmalloc_internal_with_asserts_la_SOURCES = $(libtcmalloc_internal_la_SOURCES) +libtcmalloc_internal_with_asserts_la_CXXFLAGS = $(PTHREAD_CFLAGS) \ + $(AM_CXXFLAGS) $(EMERGENCY_MALLOC_DEFINE) \ + $(MAYBE_NO_HEAP_CHECK) +libtcmalloc_internal_with_asserts_la_LDFLAGS = $(PTHREAD_CFLAGS) +libtcmalloc_internal_with_asserts_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) + +noinst_LTLIBRARIES += libtcmalloc_with_asserts.la +libtcmalloc_with_asserts_la_SOURCES = $(libtcmalloc_la_SOURCES) +libtcmalloc_with_asserts_la_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) \ + $(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE) +libtcmalloc_with_asserts_la_LDFLAGS = $(PTHREAD_CFLAGS) +libtcmalloc_with_asserts_la_LIBADD = libtcmalloc_internal_with_asserts.la libmaybe_threads.la $(PTHREAD_LIBS) + +LIBTCMALLOC = libtcmalloc.la + +LIBS_TO_WEAKEN += libtcmalloc.la + +### Unittests + +TESTS += tcmalloc_unittest.sh$(EXEEXT) +tcmalloc_unittest_sh_SOURCES = src/tests/tcmalloc_unittest.sh +noinst_SCRIPTS += $(tcmalloc_unittest_sh_SOURCES) +tcmalloc_unittest.sh$(EXEEXT): $(top_srcdir)/$(tcmalloc_unittest_sh_SOURCES) \ + tcmalloc_unittest + rm -f $@ + cp -p $(top_srcdir)/$(tcmalloc_unittest_sh_SOURCES) $@ + +noinst_PROGRAMS += tcmalloc_unittest +tcmalloc_unittest_INCLUDES = src/config_for_unittests.h \ + src/gperftools/malloc_extension.h +tcmalloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ + src/tcmalloc.h \ + src/tests/testutil.h src/tests/testutil.cc \ + $(TCMALLOC_UNITTEST_INCLUDES) +tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) + +TESTS += tcm_asserts_unittest +tcm_asserts_unittest_INCLUDES = src/config_for_unittests.h \ + src/gperftools/malloc_extension.h +tcm_asserts_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ + src/tcmalloc.h \ + src/tests/testutil.h src/tests/testutil.cc \ + $(TCMALLOC_UNITTEST_INCLUDES) +tcm_asserts_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcm_asserts_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcm_asserts_unittest_LDADD = libtcmalloc_with_asserts.la liblogging.la $(PTHREAD_LIBS) + +# This makes sure it's safe to link in both tcmalloc and +# tcmalloc_minimal. (One would never do this on purpose, but perhaps +# by accident...) When we can compile libprofiler, we also link it in +# to make sure that works too. NOTE: On OS X, it's *not* safe to +# link both in (we end up with two copies of every global var, and +# the code tends to pick one arbitrarily), so don't run the test there. +# (We define these outside the 'if' because they're reused below.) +tcmalloc_both_unittest_srcs = src/tests/tcmalloc_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + $(TCMALLOC_UNITTEST_INCLUDES) +tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +if WITH_CPU_PROFILER +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ + libprofiler.la liblogging.la $(PTHREAD_LIBS) +else +tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ + liblogging.la $(PTHREAD_LIBS) +endif !WITH_CPU_PROFILER +if !OSX +TESTS += tcmalloc_both_unittest +tcmalloc_both_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +tcmalloc_both_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +tcmalloc_both_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +tcmalloc_both_unittest_LDADD = $(tcmalloc_both_unittest_ladd) +endif !OSX + +TESTS += tcmalloc_large_unittest +tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc +tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) + +TESTS += tcmalloc_large_heap_fragmentation_unittest +tcmalloc_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc +tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) + +TESTS += raw_printer_test +raw_printer_test_SOURCES = src/tests/raw_printer_test.cc +raw_printer_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +raw_printer_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +raw_printer_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) + +# sampler_test and sampling_test both require sampling to be turned +# on, which it's not by default. Use the "standard" value of 2^19. +TESTS_ENVIRONMENT += TCMALLOC_SAMPLE_PARAMETER=524288 + +TESTS += sampler_test +WINDOWS_PROJECTS += vsprojects/sampler_test/sampler_test.vcxproj +sampler_test_SOURCES = src/tests/sampler_test.cc \ + src/config_for_unittests.h +sampler_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +sampler_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +sampler_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) -lm + + +# These unittests often need to run binaries. They're in the current dir +TESTS_ENVIRONMENT += BINDIR=. +TESTS_ENVIRONMENT += TMPDIR=/tmp/perftools + +TESTS += sampling_test.sh$(EXEEXT) +sampling_test_sh_SOURCES = src/tests/sampling_test.sh +noinst_SCRIPTS += $(sampling_test_sh_SOURCES) +sampling_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \ + sampling_test + rm -f $@ + cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@ + +# This is the sub-program used by sampling_test.sh +# The -g is so pprof can get symbol information. +noinst_PROGRAMS += sampling_test +SAMPLING_TEST_INCLUDES = src/config_for_unittests.h \ + src/base/logging.h \ + src/gperftools/malloc_extension.h +sampling_test_SOURCES = src/tests/sampling_test.cc \ + $(SAMPLING_TEST_INCLUDES) +sampling_test_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +sampling_test_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +sampling_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) + +endif WITH_HEAP_PROFILER_OR_CHECKER + +if WITH_HEAP_PROFILER + +TESTS += heap-profiler_unittest.sh$(EXEEXT) +heap_profiler_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh +noinst_SCRIPTS += $(heap_profiler_unittest_sh_SOURCES) +heap-profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \ + heap-profiler_unittest + rm -f $@ + cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@ + +# These are sub-programs used by heap-profiler_unittest.sh +noinst_PROGRAMS += heap-profiler_unittest +HEAP_PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \ + src/gperftools/heap-profiler.h +heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \ + $(HEAP_PROFILER_UNITTEST_INCLUDES) +heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) + +# Tests the compatibility include-headers in google/. Requires a function +# defined in the heap-profiler, which is why the test lives here. +TESTS += simple_compat_test +simple_compat_test_SOURCES = src/tests/simple_compat_test.cc \ + $(googleinclude_HEADERS) +simple_compat_test_LDFLAGS = $(TCMALLOC_FLAGS) +simple_compat_test_LDADD = $(LIBTCMALLOC) + +endif WITH_HEAP_PROFILER + +if WITH_HEAP_CHECKER + +TESTS += heap-checker_unittest.sh$(EXEEXT) +heap_checker_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh +noinst_SCRIPTS += $(heap_checker_unittest_sh_SOURCES) +heap-checker_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \ + heap-checker_unittest + rm -f $@ + cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@ + +TESTS += heap-checker-death_unittest.sh$(EXEEXT) +heap_checker_death_unittest_sh_SOURCES = src/tests/heap-checker-death_unittest.sh +noinst_SCRIPTS += $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) +heap-checker-death_unittest.sh$(EXEEXT): $(heap_checker_death_unittest_sh_SOURCES) \ + heap-checker_unittest + rm -f $@ + cp -p $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) $@ + +# These are sub-programs used by heap-checker_unittest.sh +noinst_PROGRAMS += heap-checker_unittest +HEAP_CHECKER_UNITTEST_INCLUDES = src/config_for_unittests.h \ + src/memory_region_map.h \ + src/base/commandlineflags.h \ + src/base/googleinit.h \ + src/gperftools/heap-checker.h \ + $(LOGGING_INCLUDES) +heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \ + $(HEAP_CHECKER_UNITTEST_INCLUDES) +heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +heap_checker_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) + +endif WITH_HEAP_CHECKER + +### Documentation (above and beyond tcmalloc_minimal documentation) +if WITH_HEAP_PROFILER +dist_doc_DATA += docs/heapprofile.html docs/heap-example1.png +endif WITH_HEAP_PROFILER + +if WITH_HEAP_CHECKER +dist_doc_DATA += docs/heap_checker.html +endif WITH_HEAP_CHECKER + + +### ------- tcmalloc with debugallocation + +if WITH_DEBUGALLOC +if WITH_HEAP_PROFILER_OR_CHECKER + +lib_LTLIBRARIES += libtcmalloc_debug.la +libtcmalloc_debug_la_SOURCES = src/debugallocation.cc $(HEAP_CHECKER_SOURCES) \ + $(TCMALLOC_INCLUDES) +libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \ + -DTCMALLOC_FOR_DEBUGALLOCATION +libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS) \ + -version-info @TCMALLOC_SO_VERSION@ +libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD) + +LIBS_TO_WEAKEN += libtcmalloc_debug.la + +### Unittests + +TESTS += tcmalloc_debug_unittest +tcmalloc_debug_unittest_SOURCES = $(tcmalloc_unittest_SOURCES) +tcmalloc_debug_unittest_CXXFLAGS = $(tcmalloc_unittest_CXXFLAGS) \ + -DDEBUGALLOCATION +tcmalloc_debug_unittest_LDFLAGS = $(tcmalloc_unittest_LDFLAGS) +tcmalloc_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) + +TESTS += sampler_debug_test +sampler_debug_test_SOURCES = $(sampler_test_SOURCES) +sampler_debug_test_CXXFLAGS = $(samples_test_CXXFLAGS) +sampler_debug_test_LDFLAGS = $(sampler_test_LDFLAGS) +sampler_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) -lm + +TESTS += sampling_debug_test.sh$(EXEEXT) +sampling_debug_test_sh_SOURCES = src/tests/sampling_test.sh +sampling_debug_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \ + sampling_debug_test + rm -f $@ + cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@ + +# This is the sub-program using by sampling_debug_test.sh +# The -g is so pprof can get symbol information. +noinst_PROGRAMS += sampling_debug_test +sampling_debug_test_SOURCES = $(sampling_test_SOURCES) +sampling_debug_test_CXXFLAGS = $(sampling_test_CXXFLAGS) +sampling_debug_test_LDFLAGS = $(sampling_test_LDFLAGS) +sampling_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) + +endif WITH_HEAP_PROFILER_OR_CHECKER + +if WITH_HEAP_PROFILER + +TESTS += heap-profiler_debug_unittest.sh$(EXEEXT) +heap_profiler_debug_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh +heap-profiler_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \ + heap-profiler_debug_unittest + rm -f $@ + cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@ + +# These are sub-programs used by heap-profiler_debug_unittest.sh +noinst_PROGRAMS += heap-profiler_debug_unittest +heap_profiler_debug_unittest_SOURCES = $(heap_profiler_unittest_SOURCES) +heap_profiler_debug_unittest_CXXFLAGS = $(heap_profiler_unittest_CXXFLAGS) +heap_profiler_debug_unittest_LDFLAGS = $(heap_profiler_unittest_LDFLAGS) +heap_profiler_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) + +endif WITH_HEAP_PROFILER + +if WITH_HEAP_CHECKER + +TESTS += heap-checker_debug_unittest.sh$(EXEEXT) +heap_checker_debug_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh +heap-checker_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \ + heap-checker_debug_unittest + rm -f $@ + cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@ + +# These are sub-programs used by heap-checker_debug_unittest.sh +noinst_PROGRAMS += heap-checker_debug_unittest +heap_checker_debug_unittest_SOURCES = $(heap_checker_unittest_SOURCES) +heap_checker_debug_unittest_CXXFLAGS = $(heap_checker_unittest_CXXFLAGS) +heap_checker_debug_unittest_LDFLAGS = $(heap_checker_unittest_LDFLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +heap_checker_debug_unittest_LDADD = libtcmalloc_debug.la liblogging.la \ + $(PTHREAD_LIBS) + +endif WITH_HEAP_CHECKER +endif WITH_DEBUGALLOC + + +### ------- CPU profiler + +if WITH_CPU_PROFILER + +### The header files we use. We divide into categories based on directory +S_CPU_PROFILER_INCLUDES = src/profiledata.h \ + src/profile-handler.h \ + src/getpc.h \ + src/base/basictypes.h \ + src/base/commandlineflags.h \ + src/base/googleinit.h \ + src/base/logging.h \ + src/base/simple_mutex.h \ + src/base/sysinfo.h \ + $(SPINLOCK_INCLUDES) \ + $(LOGGING_INCLUDES) +SG_CPU_PROFILER_INCLUDES = src/gperftools/profiler.h +CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_INCLUDES) \ + $(SG_STACKTRACE_INCLUDES) +perftoolsinclude_HEADERS += $(SG_CPU_PROFILER_INCLUDES) + +### Making the library +lib_LTLIBRARIES += libprofiler.la +libprofiler_la_SOURCES = src/profiler.cc \ + src/profile-handler.cc \ + src/profiledata.cc \ + $(CPU_PROFILER_INCLUDES) +libprofiler_la_LIBADD = libstacktrace.la libmaybe_threads.la libfake_stacktrace_scope.la +# We have to include ProfileData for profiledata_unittest +CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler|ProfilerGetStackTrace)' +libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS) \ + -version-info @PROFILER_SO_VERSION@ + +# 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.vcxproj +getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h + +TESTS += profiledata_unittest +#WINDOWS_PROJECTS += vsprojects/profiledata_unittest/profiledata_unittest.vcxproj +profiledata_unittest_SOURCES = src/tests/profiledata_unittest.cc \ + src/profiledata.h \ + src/base/commandlineflags.h \ + src/base/logging.h \ + src/base/basictypes.h +profiledata_unittest_LDADD = $(LIBPROFILER) + +TESTS += profile_handler_unittest +profile_handler_unittest_SOURCES = src/tests/profile-handler_unittest.cc \ + src/profile-handler.h +profile_handler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) +profile_handler_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +profile_handler_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS) + +TESTS += profiler_unittest.sh$(EXEEXT) +profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh +noinst_SCRIPTS += $(profiler_unittest_sh_SOURCES) +profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(profiler_unittest_sh_SOURCES) \ + profiler1_unittest profiler2_unittest \ + profiler3_unittest profiler4_unittest + rm -f $@ + cp -p $(top_srcdir)/$(profiler_unittest_sh_SOURCES) $@ + +# These are sub-programs used by profiler_unittest.sh +noinst_PROGRAMS += profiler1_unittest profiler2_unittest profiler3_unittest \ + profiler4_unittest +PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \ + src/gperftools/profiler.h +PROFILER_UNITTEST_SRCS = src/tests/profiler_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + $(PROFILER_UNITTEST_INCLUDES) +profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS) +profiler1_unittest_LDADD = $(LIBPROFILER) +profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +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) +profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS) +profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +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) + + +### Documentation +dist_doc_DATA += docs/cpuprofile.html \ + docs/cpuprofile-fileformat.html \ + docs/pprof-test-big.gif \ + docs/pprof-test.gif \ + docs/pprof-vsnprintf-big.gif \ + docs/pprof-vsnprintf.gif + +endif WITH_CPU_PROFILER + + +### ------- CPU profiler and heap checker, in one! + +# Ideally, folks who wanted to use both tcmalloc and libprofiler, +# could just link them both into their application. But while this +# works fine for .so files, it does not for .a files. The easiest way +# around this -- and I've tried a bunch of the hard ways -- is to just +# to create another set of libraries that has both functionality in it. + +if WITH_HEAP_PROFILER_OR_CHECKER +if WITH_CPU_PROFILER + +lib_LTLIBRARIES += libtcmalloc_and_profiler.la +libtcmalloc_and_profiler_la_SOURCES = $(libtcmalloc_la_SOURCES) $(libprofiler_la_SOURCES) +libtcmalloc_and_profiler_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) $(libprofiler_la_CXXFLAGS) +# Since this library is meant to be used as a .a, I don't worry as much +# about .so versioning. I just give the libtcmalloc version number. +# TODO(csilvers): use -export-symbols-regex? +libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS) \ + -version-info @TCMALLOC_AND_PROFILER_SO_VERSION@ +# We don't include libprofiler_la_LIBADD here because all it adds is +# libstacktrace.la, which we already get via libtcmalloc. Trying to +# specify it twice causes link-time duplicate-definition errors. :-( +libtcmalloc_and_profiler_la_LIBADD = $(libtcmalloc_la_LIBADD) + +TESTS += tcmalloc_and_profiler_unittest +tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +tcmalloc_and_profiler_unittest_LDADD = libtcmalloc_and_profiler.la + +LIBS_TO_WEAKEN += libtcmalloc_and_profiler.la + +endif WITH_CPU_PROFILER +endif WITH_HEAP_PROFILER_OR_CHECKER + +## ^^^^ END OF RULES TO MAKE YOUR LIBRARIES, BINARIES, AND UNITTESTS + + +# Do the weakening on some exported libtcmalloc symbols. +install-exec-local: all-local +all-local: $(LIBS_TO_WEAKEN) + for la in $(LIBS_TO_WEAKEN); do lib=".libs/`basename $$la .la`.a"; [ ! -f "$$lib" ] || $(WEAKEN) "$$lib"; done + + +# This should always include $(TESTS), but may also include other +# binaries that you compile but don't want automatically installed. +# We'll add to this later, on a library-by-library basis +noinst_PROGRAMS += $(TESTS) + +rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec + @cd packages && ./rpm.sh ${PACKAGE} ${VERSION} + +deb: dist-gzip packages/deb.sh packages/deb/* + @cd packages && ./deb.sh ${PACKAGE} ${VERSION} + +# http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libtcmalloc.pc libtcmalloc_minimal.pc \ + libtcmalloc_debug.pc libtcmalloc_minimal_debug.pc \ + libprofiler.pc +CLEANFILES = $(pkgconfig_DATA) + +# I get the description and URL lines from the rpm spec. I use sed to +# try to rewrite exec_prefix, libdir, and includedir in terms of +# prefix, if possible. +libtcmalloc.pc: Makefile packages/rpm/rpm.spec + echo 'prefix=$(prefix)' > "$@".tmp + echo 'exec_prefix='`echo '$(exec_prefix)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp + echo 'libdir='`echo '$(libdir)' | sed 's@^$(exec_prefix)@$${exec_prefix}@'` >> "$@".tmp + echo 'includedir='`echo '$(includedir)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp + echo '' >> "$@".tmp + echo 'Name: $(PACKAGE)' >> "$@".tmp + echo 'Version: $(VERSION)' >> "$@".tmp + -grep '^Summary:' $(top_srcdir)/packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp + -grep '^URL: ' $(top_srcdir)/packages/rpm/rpm.spec >> "$@".tmp + echo 'Requires:' >> "$@".tmp + echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp + echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp + echo 'Cflags: -I$${includedir}' >> "$@".tmp + mv -f "$@".tmp "$@" + +# The other versions are mostly the same. +libtcmalloc_minimal.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal/ > "$@" + +libtcmalloc_debug.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_debug/ > "$@" + +libtcmalloc_minimal_debug.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal_debug/ > "$@" + +libprofiler.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-lprofiler/ > "$@" + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +@GENERATE_CHANGELOG_RULES@ + +# Windows wants write permission to .vcxproj files and maybe even sln files. +dist-hook: dist-ChangeLog + 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/get_mangled_names.cc src/windows/override_functions.cc \ + src/windows/config.h src/windows/gperftools/tcmalloc.h \ + docs/pprof.see_also src/windows/TODO \ + $(WINDOWS_PROJECTS) \ + src/solaris/libstdc++.la diff --git a/trunk/3rdparty/gperftools-2-fit/Makefile.in b/trunk/3rdparty/gperftools-2-fit/Makefile.in new file mode 100644 index 000000000..88872dcc3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/Makefile.in @@ -0,0 +1,8288 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Note: for every library we create, we're explicit about what symbols +# we export. In order to avoid complications with C++ mangling, we always +# use the regexp for of specifying symbols. + + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_STACK_TRACE_FALSE@am__append_1 = -DNO_TCMALLOC_SAMPLES + +# These are good warnings to turn on by default. +@GCC_TRUE@am__append_2 = -Wall -Wwrite-strings -Woverloaded-virtual \ +@GCC_TRUE@ -Wno-sign-compare + + +# On i386, -mmmx is needed for the mmx-based instructions in +# atomicops-internal-x86.h. Also as of gcc 4.6, -fomit-frame-pointer +# is the default. Since we must always have frame pointers for I386 +# in order to generate backtraces we now specify -fno-omit-frame-pointer +# by default. +@GCC_TRUE@@I386_TRUE@am__append_3 = -mmmx -fno-omit-frame-pointer +@HAVE_W_NO_UNUSED_RESULT_TRUE@am__append_4 = -Wno-unused-result +@HAVE_SIZED_DEALLOCATION_TRUE@am__append_5 = -fsized-deallocation +@HAVE_F_ALIGNED_NEW_TRUE@am__append_6 = -faligned-new + +# These are x86-specific, having to do with frame-pointers. In +# particular, some x86_64 systems do not insert frame pointers by +# default (all i386 systems that I know of, do. I don't know about +# non-x86 chips). We need to tell perftools what to do about that. +@ENABLE_FRAME_POINTERS_FALSE@@OMIT_FP_BY_DEFAULT_TRUE@am__append_7 = -DNO_FRAME_POINTER + +# respect --enable-frame-pointers regardless of architecture +@ENABLE_FRAME_POINTERS_TRUE@am__append_8 = -fno-omit-frame-pointer +@MINGW_TRUE@am__append_9 = -Wl,-u__tcmalloc +TESTS = low_level_alloc_unittest$(EXEEXT) atomicops_unittest$(EXEEXT) \ + $(am__EXEEXT_11) tcmalloc_minimal_unittest$(EXEEXT) \ + tcm_min_asserts_unittest$(EXEEXT) \ + tcmalloc_minimal_large_unittest$(EXEEXT) \ + tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) \ + $(am__append_23) addressmap_unittest$(EXEEXT) $(am__EXEEXT_12) \ + packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \ + markidle_unittest$(EXEEXT) \ + current_allocated_bytes_test$(EXEEXT) \ + malloc_hook_test$(EXEEXT) malloc_extension_test$(EXEEXT) \ + $(am__EXEEXT_13) $(am__EXEEXT_14) page_heap_test$(EXEEXT) \ + pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \ + stack_trace_table_test$(EXEEXT) \ + thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_15) \ + $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__append_35) \ + $(am__EXEEXT_18) $(am__EXEEXT_19) $(am__EXEEXT_20) \ + $(am__EXEEXT_21) $(am__append_57) $(am__EXEEXT_22) \ + $(am__append_66) $(am__append_68) $(am__EXEEXT_23) \ + $(am__EXEEXT_24) +noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ + $(am__EXEEXT_10) $(am__EXEEXT_25) +bin_PROGRAMS = +@MINGW_TRUE@am__append_10 = libwindows.la libspinlock.la + +# We also need to tell mingw that sysinfo.cc needs shlwapi.lib. +# (We do this via a #pragma for msvc, but need to do it here for mingw). +@MINGW_TRUE@am__append_11 = -lshlwapi +# windows has its own system for threads and system memory allocation. +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@am__append_12 = src/maybe_threads.cc +@MINGW_FALSE@am__append_13 = libspinlock.la +@MINGW_FALSE@am__append_14 = src/maybe_threads.cc +@WITH_STACK_TRACE_TRUE@am__append_15 = $(SG_STACKTRACE_INCLUDES) + +### Making the library +@WITH_STACK_TRACE_TRUE@am__append_16 = libstacktrace.la \ +@WITH_STACK_TRACE_TRUE@ libfake_stacktrace_scope.la + +### Unittests +@WITH_STACK_TRACE_TRUE@am__append_17 = stacktrace_unittest + +### Documentation +@WITH_STACK_TRACE_TRUE@am__append_18 = + +# Let unittests find pprof if they need to run it +@WITH_STACK_TRACE_TRUE@am__append_19 = PPROF_PATH=$(top_srcdir)/src/pprof +@INSTALL_PPROF_TRUE@@WITH_STACK_TRACE_TRUE@am__append_20 = src/pprof +@INSTALL_PPROF_TRUE@@WITH_STACK_TRACE_TRUE@am__append_21 = docs/pprof_remote_servers.html + +### Documentation + +# On MSVC, we need our own versions of addr2line and nm to work with pprof. +# This is a slight abuse of WINDOWS_PROJECTS, but not much +@WITH_STACK_TRACE_TRUE@am__append_22 = \ +@WITH_STACK_TRACE_TRUE@ vsprojects/nm-pdb/nm-pdb.vcxproj \ +@WITH_STACK_TRACE_TRUE@ vsprojects/addr2line-pdb/addr2line-pdb.vcxproj \ +@WITH_STACK_TRACE_TRUE@ src/windows/nm-pdb.c \ +@WITH_STACK_TRACE_TRUE@ src/windows/addr2line-pdb.c + +# This tests it works to LD_PRELOAD libtcmalloc (tests maybe_threads.cc) +# In theory this should work under mingw, but mingw has trouble running +# shell scripts that end in .exe. And it doesn't seem to build shared +# libraries anyway (so can't be LD_PRELOADed) -- in fact, anybody who +# chooses not to build shared libraries won't be able to run this test. +# TODO(csilvers): figure out how to nix ".exe" or otherwise work under mingw +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_23 = maybe_threads_unittest.sh$(EXEEXT) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_24 = $(maybe_threads_unittest_sh_SOURCES) +@MINGW_TRUE@am__append_25 = src/windows/port.h src/windows/port.cc +@MINGW_FALSE@am__append_26 = system_alloc_unittest + +# This doesn't work with mingw, which links foo.a even though it +# doesn't set ENABLE_STATIC. TODO(csilvers): set enable_static=true +# in configure.ac:36? +@MINGW_FALSE@am__append_27 = malloc_extension_c_test +# -ansi here is just to help ensure the code is bog-standard C. +@GCC_TRUE@@MINGW_FALSE@am__append_28 = -ansi +@MINGW_FALSE@@OSX_FALSE@am__append_29 = memalign_unittest + +### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation) +@WITH_DEBUGALLOC_TRUE@am__append_30 = libtcmalloc_minimal_debug.la +@WITH_DEBUGALLOC_TRUE@am__append_31 = libtcmalloc_minimal_debug.la + +### Unittests +@WITH_DEBUGALLOC_TRUE@am__append_32 = tcmalloc_minimal_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__append_33 = memalign_debug_unittest +@WITH_DEBUGALLOC_TRUE@am__append_34 = realloc_debug_unittest + +# debugallocation_test checks that we print a proper stacktrace when +# debug-allocs fail, so we can't run it if we don't have stacktrace info. +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_35 = debugallocation_test.sh$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_36 = $(debugallocation_test_sh_SOURCES) + +# This is the sub-program used by debugallocation_test.sh +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_37 = debugallocation_test +@MINGW_FALSE@am__append_38 = librun_benchmark.la +@MINGW_FALSE@am__append_39 = malloc_bench malloc_bench_shared \ +@MINGW_FALSE@ binary_trees binary_trees_shared + +@ENABLE_STATIC_TRUE@@MINGW_FALSE@am__append_40 = -static +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_41 = malloc_bench_shared_full +@ENABLE_STATIC_TRUE@@MINGW_FALSE@am__append_42 = -static +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_43 = $(SG_TCMALLOC_INCLUDES) + +# same as above with without -DNDEBUG +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_with_asserts.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_with_asserts.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_45 = libtcmalloc.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_46 = libtcmalloc.la + +### Unittests +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_47 = tcmalloc_unittest.sh$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcm_asserts_unittest +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_48 = $(tcmalloc_unittest_sh_SOURCES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(sampling_test_sh_SOURCES) + +# This is the sub-program used by sampling_test.sh +# The -g is so pprof can get symbol information. +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_49 = tcmalloc_unittest \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_50 = tcmalloc_both_unittest +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_51 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_heap_fragmentation_unittest \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT) + +# sampler_test and sampling_test both require sampling to be turned +# on, which it's not by default. Use the "standard" value of 2^19. + +# These unittests often need to run binaries. They're in the current dir +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_52 = TCMALLOC_SAMPLE_PARAMETER=524288 \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ BINDIR=. \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ TMPDIR=/tmp/perftools +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_53 = vsprojects/sampler_test/sampler_test.vcxproj + +# Tests the compatibility include-headers in google/. Requires a function +# defined in the heap-profiler, which is why the test lives here. +@WITH_HEAP_PROFILER_TRUE@am__append_54 = \ +@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT) \ +@WITH_HEAP_PROFILER_TRUE@ simple_compat_test +@WITH_HEAP_PROFILER_TRUE@am__append_55 = $(heap_profiler_unittest_sh_SOURCES) + +# These are sub-programs used by heap-profiler_unittest.sh +@WITH_HEAP_PROFILER_TRUE@am__append_56 = heap-profiler_unittest +@WITH_HEAP_CHECKER_TRUE@am__append_57 = \ +@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \ +@WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT) +@WITH_HEAP_CHECKER_TRUE@am__append_58 = \ +@WITH_HEAP_CHECKER_TRUE@ $(heap_checker_unittest_sh_SOURCES) \ +@WITH_HEAP_CHECKER_TRUE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) + +# These are sub-programs used by heap-checker_unittest.sh +@WITH_HEAP_CHECKER_TRUE@am__append_59 = heap-checker_unittest + +### Documentation (above and beyond tcmalloc_minimal documentation) +@WITH_HEAP_PROFILER_TRUE@am__append_60 = docs/heapprofile.html docs/heap-example1.png +@WITH_HEAP_CHECKER_TRUE@am__append_61 = docs/heap_checker.html + +### ------- tcmalloc with debugallocation +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_62 = libtcmalloc_debug.la +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_63 = libtcmalloc_debug.la + +### Unittests +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_64 = tcmalloc_debug_unittest \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT) + +# This is the sub-program using by sampling_debug_test.sh +# The -g is so pprof can get symbol information. +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_65 = sampling_debug_test +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_66 = heap-profiler_debug_unittest.sh$(EXEEXT) + +# These are sub-programs used by heap-profiler_debug_unittest.sh +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_67 = heap-profiler_debug_unittest +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_68 = heap-checker_debug_unittest.sh$(EXEEXT) + +# These are sub-programs used by heap-checker_debug_unittest.sh +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_69 = heap-checker_debug_unittest +@WITH_CPU_PROFILER_TRUE@am__append_70 = $(SG_CPU_PROFILER_INCLUDES) + +### Making the library +@WITH_CPU_PROFILER_TRUE@am__append_71 = libprofiler.la + +### Unittests +@WITH_CPU_PROFILER_TRUE@am__append_72 = getpc_test \ +@WITH_CPU_PROFILER_TRUE@ profiledata_unittest \ +@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest \ +@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT) +@WITH_CPU_PROFILER_TRUE@am__append_73 = $(profiler_unittest_sh_SOURCES) + +# These are sub-programs used by profiler_unittest.sh +@WITH_CPU_PROFILER_TRUE@am__append_74 = profiler1_unittest profiler2_unittest profiler3_unittest \ +@WITH_CPU_PROFILER_TRUE@ profiler4_unittest + +@WITH_CPU_PROFILER_FALSE@profiler2_unittest_DEPENDENCIES = + +### Documentation +@WITH_CPU_PROFILER_TRUE@am__append_75 = docs/cpuprofile.html \ +@WITH_CPU_PROFILER_TRUE@ docs/cpuprofile-fileformat.html \ +@WITH_CPU_PROFILER_TRUE@ docs/pprof-test-big.gif \ +@WITH_CPU_PROFILER_TRUE@ docs/pprof-test.gif \ +@WITH_CPU_PROFILER_TRUE@ docs/pprof-vsnprintf-big.gif \ +@WITH_CPU_PROFILER_TRUE@ docs/pprof-vsnprintf.gif + + +### ------- CPU profiler and heap checker, in one! + +# Ideally, folks who wanted to use both tcmalloc and libprofiler, +# could just link them both into their application. But while this +# works fine for .so files, it does not for .a files. The easiest way +# around this -- and I've tried a bunch of the hard ways -- is to just +# to create another set of libraries that has both functionality in it. +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_76 = libtcmalloc_and_profiler.la +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_77 = tcmalloc_and_profiler_unittest +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_78 = libtcmalloc_and_profiler.la +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_have_attribute.m4 \ + $(top_srcdir)/m4/acx_nanosleep.m4 \ + $(top_srcdir)/m4/acx_pthread.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_generate_changelog.m4 \ + $(top_srcdir)/m4/install_prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pc_from_ucontext.m4 \ + $(top_srcdir)/m4/program_invocation_name.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__dist_doc_DATA_DIST) \ + $(googleinclude_HEADERS) $(noinst_HEADERS) \ + $(am__perftoolsinclude_HEADERS_DIST) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = src/gperftools/tcmalloc.h \ + src/windows/gperftools/tcmalloc.h +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ + "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(googleincludedir)" \ + "$(DESTDIR)$(perftoolsincludedir)" \ + "$(DESTDIR)$(perftoolsincludedir)" +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT) +@MINGW_FALSE@am__EXEEXT_2 = malloc_bench$(EXEEXT) \ +@MINGW_FALSE@ malloc_bench_shared$(EXEEXT) \ +@MINGW_FALSE@ binary_trees$(EXEEXT) \ +@MINGW_FALSE@ binary_trees_shared$(EXEEXT) +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_3 = malloc_bench_shared_full$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_4 = tcmalloc_unittest$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test$(EXEEXT) +@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_5 = \ +@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest$(EXEEXT) +@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_6 = heap-checker_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_7 = sampling_debug_test$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_8 = heap-profiler_debug_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_9 = heap-checker_debug_unittest$(EXEEXT) +@WITH_CPU_PROFILER_TRUE@am__EXEEXT_10 = profiler1_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profiler2_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profiler3_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profiler4_unittest$(EXEEXT) +@WITH_STACK_TRACE_TRUE@am__EXEEXT_11 = stacktrace_unittest$(EXEEXT) +@MINGW_FALSE@am__EXEEXT_12 = system_alloc_unittest$(EXEEXT) +@MINGW_FALSE@am__EXEEXT_13 = malloc_extension_c_test$(EXEEXT) +@MINGW_FALSE@@OSX_FALSE@am__EXEEXT_14 = memalign_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@am__EXEEXT_15 = tcmalloc_minimal_debug_unittest$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__EXEEXT_16 = memalign_debug_unittest$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@am__EXEEXT_17 = realloc_debug_unittest$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_18 = tcmalloc_unittest.sh$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcm_asserts_unittest$(EXEEXT) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_19 = tcmalloc_both_unittest$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_20 = tcmalloc_large_unittest$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_heap_fragmentation_unittest$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test$(EXEEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT) +@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_21 = \ +@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT) \ +@WITH_HEAP_PROFILER_TRUE@ simple_compat_test$(EXEEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_22 = tcmalloc_debug_unittest$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test$(EXEEXT) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT) +@WITH_CPU_PROFILER_TRUE@am__EXEEXT_23 = getpc_test$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profiledata_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest$(EXEEXT) \ +@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_24 = tcmalloc_and_profiler_unittest$(EXEEXT) +am__EXEEXT_25 = low_level_alloc_unittest$(EXEEXT) \ + atomicops_unittest$(EXEEXT) $(am__EXEEXT_11) \ + tcmalloc_minimal_unittest$(EXEEXT) \ + tcm_min_asserts_unittest$(EXEEXT) \ + tcmalloc_minimal_large_unittest$(EXEEXT) \ + tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) \ + $(am__append_23) addressmap_unittest$(EXEEXT) $(am__EXEEXT_12) \ + packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \ + markidle_unittest$(EXEEXT) \ + current_allocated_bytes_test$(EXEEXT) \ + malloc_hook_test$(EXEEXT) malloc_extension_test$(EXEEXT) \ + $(am__EXEEXT_13) $(am__EXEEXT_14) page_heap_test$(EXEEXT) \ + pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \ + stack_trace_table_test$(EXEEXT) \ + thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_15) \ + $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__append_35) \ + $(am__EXEEXT_18) $(am__EXEEXT_19) $(am__EXEEXT_20) \ + $(am__EXEEXT_21) $(am__append_57) $(am__EXEEXT_22) \ + $(am__append_66) $(am__append_68) $(am__EXEEXT_23) \ + $(am__EXEEXT_24) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +libfake_stacktrace_scope_la_LIBADD = +am__libfake_stacktrace_scope_la_SOURCES_DIST = \ + src/fake_stacktrace_scope.cc +am__dirstamp = $(am__leading_dot)dirstamp +@WITH_STACK_TRACE_TRUE@am_libfake_stacktrace_scope_la_OBJECTS = \ +@WITH_STACK_TRACE_TRUE@ src/fake_stacktrace_scope.lo +libfake_stacktrace_scope_la_OBJECTS = \ + $(am_libfake_stacktrace_scope_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +@WITH_STACK_TRACE_TRUE@am_libfake_stacktrace_scope_la_rpath = +liblogging_la_LIBADD = +am__objects_1 = +am_liblogging_la_OBJECTS = src/base/logging.lo \ + src/base/dynamic_annotations.lo $(am__objects_1) +liblogging_la_OBJECTS = $(am_liblogging_la_OBJECTS) +libmaybe_threads_la_LIBADD = +am__libmaybe_threads_la_SOURCES_DIST = src/maybe_threads.h \ + src/maybe_threads.cc +@HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE@@MINGW_TRUE@am__objects_2 = src/maybe_threads.lo +@MINGW_FALSE@am__objects_3 = src/maybe_threads.lo +am_libmaybe_threads_la_OBJECTS = $(am__objects_2) $(am__objects_3) +libmaybe_threads_la_OBJECTS = $(am_libmaybe_threads_la_OBJECTS) +@WITH_CPU_PROFILER_TRUE@libprofiler_la_DEPENDENCIES = \ +@WITH_CPU_PROFILER_TRUE@ libstacktrace.la libmaybe_threads.la \ +@WITH_CPU_PROFILER_TRUE@ libfake_stacktrace_scope.la +am__libprofiler_la_SOURCES_DIST = src/profiler.cc \ + src/profile-handler.cc src/profiledata.cc src/profiledata.h \ + src/profile-handler.h src/getpc.h src/base/basictypes.h \ + src/base/commandlineflags.h src/base/googleinit.h \ + src/base/logging.h src/base/simple_mutex.h src/base/sysinfo.h \ + src/base/spinlock.h src/base/spinlock_internal.h \ + src/base/atomicops.h src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h \ + src/base/dynamic_annotations.h src/gperftools/profiler.h \ + src/gperftools/stacktrace.h +@WITH_CPU_PROFILER_TRUE@am__objects_4 = $(am__objects_1) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am__objects_5 = $(am__objects_4) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am_libprofiler_la_OBJECTS = src/profiler.lo \ +@WITH_CPU_PROFILER_TRUE@ src/profile-handler.lo \ +@WITH_CPU_PROFILER_TRUE@ src/profiledata.lo $(am__objects_5) +libprofiler_la_OBJECTS = $(am_libprofiler_la_OBJECTS) +libprofiler_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libprofiler_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@WITH_CPU_PROFILER_TRUE@am_libprofiler_la_rpath = -rpath $(libdir) +librun_benchmark_la_LIBADD = +am__librun_benchmark_la_SOURCES_DIST = benchmark/run_benchmark.c \ + benchmark/run_benchmark.h +@MINGW_FALSE@am_librun_benchmark_la_OBJECTS = \ +@MINGW_FALSE@ benchmark/run_benchmark.lo +librun_benchmark_la_OBJECTS = $(am_librun_benchmark_la_OBJECTS) +@MINGW_FALSE@am_librun_benchmark_la_rpath = +am__DEPENDENCIES_1 = +@MINGW_FALSE@libspinlock_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__libspinlock_la_SOURCES_DIST = src/base/spinlock.cc \ + src/base/spinlock_internal.cc \ + src/base/atomicops-internals-x86.cc src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h +@MINGW_FALSE@am_libspinlock_la_OBJECTS = src/base/spinlock.lo \ +@MINGW_FALSE@ src/base/spinlock_internal.lo \ +@MINGW_FALSE@ src/base/atomicops-internals-x86.lo \ +@MINGW_FALSE@ $(am__objects_1) +@MINGW_TRUE@am_libspinlock_la_OBJECTS = src/base/spinlock.lo \ +@MINGW_TRUE@ src/base/spinlock_internal.lo \ +@MINGW_TRUE@ src/base/atomicops-internals-x86.lo \ +@MINGW_TRUE@ $(am__objects_1) +libspinlock_la_OBJECTS = $(am_libspinlock_la_OBJECTS) +@MINGW_FALSE@am_libspinlock_la_rpath = +@MINGW_TRUE@am_libspinlock_la_rpath = +@WITH_STACK_TRACE_TRUE@libstacktrace_la_DEPENDENCIES = \ +@WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_1) $(LIBSPINLOCK) +am__libstacktrace_la_SOURCES_DIST = src/stacktrace.cc \ + src/base/elf_mem_image.cc src/base/vdso_support.cc \ + src/stacktrace_impl_setup-inl.h src/stacktrace_generic-inl.h \ + src/stacktrace_generic_fp-inl.h src/stacktrace_libgcc-inl.h \ + src/stacktrace_libunwind-inl.h src/stacktrace_arm-inl.h \ + src/stacktrace_powerpc-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h src/stacktrace_instrument-inl.h \ + src/base/elf_mem_image.h src/base/vdso_support.h \ + src/gperftools/stacktrace.h +@WITH_STACK_TRACE_TRUE@am__objects_6 = $(am__objects_1) \ +@WITH_STACK_TRACE_TRUE@ $(am__objects_1) +@WITH_STACK_TRACE_TRUE@am_libstacktrace_la_OBJECTS = \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace.lo \ +@WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.lo \ +@WITH_STACK_TRACE_TRUE@ src/base/vdso_support.lo \ +@WITH_STACK_TRACE_TRUE@ $(am__objects_6) +libstacktrace_la_OBJECTS = $(am_libstacktrace_la_OBJECTS) +libstacktrace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libstacktrace_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@WITH_STACK_TRACE_TRUE@am_libstacktrace_la_rpath = +libsysinfo_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_libsysinfo_la_OBJECTS = src/base/sysinfo.lo $(am__objects_1) +libsysinfo_la_OBJECTS = $(am_libsysinfo_la_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libmaybe_threads.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +am__libtcmalloc_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/gperftools/stacktrace.h src/base/thread_lister.c \ + src/base/linuxthreads.cc src/heap-checker.cc \ + src/heap-checker-bcad.cc +@MINGW_FALSE@am__objects_7 = src/libtcmalloc_la-tcmalloc.lo +am__objects_8 = $(am__objects_1) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_9 = $(am__objects_8) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_10 = $(am__objects_9) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_11 = src/base/thread_lister.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_la-linuxthreads.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_la-heap-checker.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_la-heap-checker-bcad.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_la_OBJECTS = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_7) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_11) +libtcmalloc_la_OBJECTS = $(am_libtcmalloc_la_OBJECTS) +libtcmalloc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_la_rpath = -rpath \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_2 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libmaybe_threads.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__libtcmalloc_and_profiler_la_SOURCES_DIST = src/tcmalloc.cc \ + src/common.h src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/gperftools/stacktrace.h src/base/thread_lister.c \ + src/base/linuxthreads.cc src/heap-checker.cc \ + src/heap-checker-bcad.cc src/profiler.cc \ + src/profile-handler.cc src/profiledata.cc src/profiledata.h \ + src/profile-handler.h src/getpc.h src/base/simple_mutex.h \ + src/gperftools/profiler.h +@MINGW_FALSE@am__objects_12 = \ +@MINGW_FALSE@ src/libtcmalloc_and_profiler_la-tcmalloc.lo +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_13 = src/base/thread_lister.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_and_profiler_la-linuxthreads.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_and_profiler_la-heap-checker.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_14 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_12) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_13) +@WITH_CPU_PROFILER_TRUE@am__objects_15 = src/libtcmalloc_and_profiler_la-profiler.lo \ +@WITH_CPU_PROFILER_TRUE@ src/libtcmalloc_and_profiler_la-profile-handler.lo \ +@WITH_CPU_PROFILER_TRUE@ src/libtcmalloc_and_profiler_la-profiledata.lo \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_5) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_OBJECTS = $(am__objects_14) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_15) +libtcmalloc_and_profiler_la_OBJECTS = \ + $(am_libtcmalloc_and_profiler_la_OBJECTS) +libtcmalloc_and_profiler_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_and_profiler_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_rpath = -rpath \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__libtcmalloc_debug_la_SOURCES_DIST = src/debugallocation.cc \ + src/base/thread_lister.c src/base/linuxthreads.cc \ + src/heap-checker.cc src/heap-checker-bcad.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/gperftools/stacktrace.h +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_16 = src/base/thread_lister.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_debug_la-linuxthreads.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_debug_la-heap-checker.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_debug_la-heap-checker-bcad.lo +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_debug_la_OBJECTS = src/libtcmalloc_debug_la-debugallocation.lo \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_16) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) +libtcmalloc_debug_la_OBJECTS = $(am_libtcmalloc_debug_la_OBJECTS) +libtcmalloc_debug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_debug_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_debug_la_rpath = -rpath \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libstacktrace.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +am__libtcmalloc_internal_la_SOURCES_DIST = src/common.cc \ + src/internal_logging.cc src/system-alloc.cc \ + src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \ + src/sampler.cc src/span.cc src/stack_trace_table.cc \ + src/static_vars.cc src/symbolize.cc src/thread_cache.cc \ + src/malloc_hook.cc src/malloc_extension.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/heap-profiler.h \ + src/gperftools/heap-checker.h src/base/low_level_alloc.cc \ + src/heap-profile-table.cc src/heap-profiler.cc \ + src/raw_printer.cc src/fake_stacktrace_scope.cc \ + src/emergency_malloc.cc src/emergency_malloc_for_stacktrace.cc \ + src/memory_region_map.cc +@MINGW_FALSE@am__objects_17 = \ +@MINGW_FALSE@ src/libtcmalloc_internal_la-system-alloc.lo +am__objects_18 = $(am__objects_8) $(am__objects_1) $(am__objects_1) +am__objects_19 = src/libtcmalloc_internal_la-common.lo \ + src/libtcmalloc_internal_la-internal_logging.lo \ + $(am__objects_17) src/libtcmalloc_internal_la-memfs_malloc.lo \ + src/libtcmalloc_internal_la-central_freelist.lo \ + src/libtcmalloc_internal_la-page_heap.lo \ + src/libtcmalloc_internal_la-sampler.lo \ + src/libtcmalloc_internal_la-span.lo \ + src/libtcmalloc_internal_la-stack_trace_table.lo \ + src/libtcmalloc_internal_la-static_vars.lo \ + src/libtcmalloc_internal_la-symbolize.lo \ + src/libtcmalloc_internal_la-thread_cache.lo \ + src/libtcmalloc_internal_la-malloc_hook.lo \ + src/libtcmalloc_internal_la-malloc_extension.lo \ + $(am__objects_18) +@BUILD_EMERGENCY_MALLOC_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_20 = src/libtcmalloc_internal_la-fake_stacktrace_scope.lo +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_20 = src/libtcmalloc_internal_la-emergency_malloc.lo \ +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_la_OBJECTS = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_19) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_internal_la-low_level_alloc.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_la-heap-profile-table.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_la-heap-profiler.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_la-raw_printer.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_20) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_la-memory_region_map.lo +libtcmalloc_internal_la_OBJECTS = \ + $(am_libtcmalloc_internal_la_OBJECTS) +libtcmalloc_internal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_internal_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_la_rpath = +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_with_asserts_la_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libstacktrace.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +am__libtcmalloc_internal_with_asserts_la_SOURCES_DIST = src/common.cc \ + src/internal_logging.cc src/system-alloc.cc \ + src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \ + src/sampler.cc src/span.cc src/stack_trace_table.cc \ + src/static_vars.cc src/symbolize.cc src/thread_cache.cc \ + src/malloc_hook.cc src/malloc_extension.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/heap-profiler.h \ + src/gperftools/heap-checker.h src/base/low_level_alloc.cc \ + src/heap-profile-table.cc src/heap-profiler.cc \ + src/raw_printer.cc src/fake_stacktrace_scope.cc \ + src/emergency_malloc.cc src/emergency_malloc_for_stacktrace.cc \ + src/memory_region_map.cc +@MINGW_FALSE@am__objects_21 = src/libtcmalloc_internal_with_asserts_la-system-alloc.lo +am__objects_22 = src/libtcmalloc_internal_with_asserts_la-common.lo \ + src/libtcmalloc_internal_with_asserts_la-internal_logging.lo \ + $(am__objects_21) \ + src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo \ + src/libtcmalloc_internal_with_asserts_la-central_freelist.lo \ + src/libtcmalloc_internal_with_asserts_la-page_heap.lo \ + src/libtcmalloc_internal_with_asserts_la-sampler.lo \ + src/libtcmalloc_internal_with_asserts_la-span.lo \ + src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo \ + src/libtcmalloc_internal_with_asserts_la-static_vars.lo \ + src/libtcmalloc_internal_with_asserts_la-symbolize.lo \ + src/libtcmalloc_internal_with_asserts_la-thread_cache.lo \ + src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo \ + src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo \ + $(am__objects_18) +@BUILD_EMERGENCY_MALLOC_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_23 = src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_23 = src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo \ +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_24 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_22) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_with_asserts_la-raw_printer.lo \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_23) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_with_asserts_la_OBJECTS = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_24) +libtcmalloc_internal_with_asserts_la_OBJECTS = \ + $(am_libtcmalloc_internal_with_asserts_la_OBJECTS) +libtcmalloc_internal_with_asserts_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CXXLD) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) \ + $(CXXFLAGS) $(libtcmalloc_internal_with_asserts_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_with_asserts_la_rpath = +libtcmalloc_minimal_la_DEPENDENCIES = libtcmalloc_minimal_internal.la +am__libtcmalloc_minimal_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h +@MINGW_FALSE@am__objects_25 = src/libtcmalloc_minimal_la-tcmalloc.lo +am_libtcmalloc_minimal_la_OBJECTS = $(am__objects_25) \ + $(am__objects_18) +libtcmalloc_minimal_la_OBJECTS = $(am_libtcmalloc_minimal_la_OBJECTS) +libtcmalloc_minimal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_minimal_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_DEPENDENCIES = \ +@WITH_DEBUGALLOC_TRUE@ $(libtcmalloc_minimal_la_LIBADD) +am__libtcmalloc_minimal_debug_la_SOURCES_DIST = \ + src/debugallocation.cc src/common.h src/internal_logging.h \ + src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h +@WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_OBJECTS = src/libtcmalloc_minimal_debug_la-debugallocation.lo \ +@WITH_DEBUGALLOC_TRUE@ $(am__objects_18) +libtcmalloc_minimal_debug_la_OBJECTS = \ + $(am_libtcmalloc_minimal_debug_la_OBJECTS) +libtcmalloc_minimal_debug_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_minimal_debug_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_rpath = -rpath \ +@WITH_DEBUGALLOC_TRUE@ $(libdir) +libtcmalloc_minimal_internal_la_DEPENDENCIES = $(LIBSPINLOCK) \ + libmaybe_threads.la +am__libtcmalloc_minimal_internal_la_SOURCES_DIST = src/common.cc \ + src/internal_logging.cc src/system-alloc.cc \ + src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \ + src/sampler.cc src/span.cc src/stack_trace_table.cc \ + src/static_vars.cc src/symbolize.cc src/thread_cache.cc \ + src/malloc_hook.cc src/malloc_extension.cc src/common.h \ + src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h +@MINGW_FALSE@am__objects_26 = src/libtcmalloc_minimal_internal_la-system-alloc.lo +am_libtcmalloc_minimal_internal_la_OBJECTS = \ + src/libtcmalloc_minimal_internal_la-common.lo \ + src/libtcmalloc_minimal_internal_la-internal_logging.lo \ + $(am__objects_26) \ + src/libtcmalloc_minimal_internal_la-memfs_malloc.lo \ + src/libtcmalloc_minimal_internal_la-central_freelist.lo \ + src/libtcmalloc_minimal_internal_la-page_heap.lo \ + src/libtcmalloc_minimal_internal_la-sampler.lo \ + src/libtcmalloc_minimal_internal_la-span.lo \ + src/libtcmalloc_minimal_internal_la-stack_trace_table.lo \ + src/libtcmalloc_minimal_internal_la-static_vars.lo \ + src/libtcmalloc_minimal_internal_la-symbolize.lo \ + src/libtcmalloc_minimal_internal_la-thread_cache.lo \ + src/libtcmalloc_minimal_internal_la-malloc_hook.lo \ + src/libtcmalloc_minimal_internal_la-malloc_extension.lo \ + $(am__objects_18) +libtcmalloc_minimal_internal_la_OBJECTS = \ + $(am_libtcmalloc_minimal_internal_la_OBJECTS) +libtcmalloc_minimal_internal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_minimal_internal_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_with_asserts_la_DEPENDENCIES = libtcmalloc_internal_with_asserts.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libmaybe_threads.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +am__libtcmalloc_with_asserts_la_SOURCES_DIST = src/tcmalloc.cc \ + src/common.h src/internal_logging.h src/system-alloc.h \ + src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/logging.h \ + src/base/dynamic_annotations.h src/addressmap-inl.h \ + src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \ + src/base/linux_syscall_support.h src/base/linuxthreads.h \ + src/base/stl_allocator.h src/base/sysinfo.h \ + src/base/thread_lister.h src/heap-profile-table.h \ + src/heap-profile-stats.h src/maybe_emergency_malloc.h \ + src/emergency_malloc.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/gperftools/stacktrace.h src/base/thread_lister.c \ + src/base/linuxthreads.cc src/heap-checker.cc \ + src/heap-checker-bcad.cc +@MINGW_FALSE@am__objects_27 = \ +@MINGW_FALSE@ src/libtcmalloc_with_asserts_la-tcmalloc.lo +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_28 = src/base/thread_lister.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/libtcmalloc_with_asserts_la-linuxthreads.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_with_asserts_la-heap-checker.lo \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_29 = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_27) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_28) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_with_asserts_la_OBJECTS = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_29) +libtcmalloc_with_asserts_la_OBJECTS = \ + $(am_libtcmalloc_with_asserts_la_OBJECTS) +libtcmalloc_with_asserts_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) \ + $(libtcmalloc_with_asserts_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_with_asserts_la_rpath = +libwindows_la_DEPENDENCIES = +am__libwindows_la_SOURCES_DIST = src/windows/port.h \ + src/windows/mingw.h src/windows/mini_disassembler.h \ + src/windows/mini_disassembler_types.h \ + src/windows/preamble_patcher.h src/windows/port.cc \ + src/windows/system-alloc.cc src/windows/ia32_modrm_map.cc \ + src/windows/ia32_opcode_map.cc \ + src/windows/mini_disassembler.cc \ + src/windows/patch_functions.cc src/windows/preamble_patcher.cc \ + src/windows/preamble_patcher_with_stub.cc +@MINGW_TRUE@am_libwindows_la_OBJECTS = $(am__objects_1) \ +@MINGW_TRUE@ src/windows/port.lo src/windows/system-alloc.lo \ +@MINGW_TRUE@ src/windows/ia32_modrm_map.lo \ +@MINGW_TRUE@ src/windows/ia32_opcode_map.lo \ +@MINGW_TRUE@ src/windows/mini_disassembler.lo \ +@MINGW_TRUE@ src/windows/patch_functions.lo \ +@MINGW_TRUE@ src/windows/preamble_patcher.lo \ +@MINGW_TRUE@ src/windows/preamble_patcher_with_stub.lo +libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS) +@MINGW_TRUE@am_libwindows_la_rpath = +am__addressmap_unittest_SOURCES_DIST = \ + src/tests/addressmap_unittest.cc src/addressmap-inl.h \ + src/base/commandlineflags.h src/base/logging.h \ + src/base/basictypes.h src/base/dynamic_annotations.h \ + src/windows/port.h src/windows/port.cc +@MINGW_TRUE@am__objects_30 = \ +@MINGW_TRUE@ src/windows/addressmap_unittest-port.$(OBJEXT) +am_addressmap_unittest_OBJECTS = \ + src/tests/addressmap_unittest-addressmap_unittest.$(OBJEXT) \ + $(am__objects_8) $(am__objects_30) +addressmap_unittest_OBJECTS = $(am_addressmap_unittest_OBJECTS) +addressmap_unittest_DEPENDENCIES = liblogging.la +addressmap_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_atomicops_unittest_OBJECTS = \ + src/tests/atomicops_unittest.$(OBJEXT) $(am__objects_8) +atomicops_unittest_OBJECTS = $(am_atomicops_unittest_OBJECTS) +atomicops_unittest_DEPENDENCIES = $(LIBSPINLOCK) +am__binary_trees_SOURCES_DIST = benchmark/binary_trees.cc +@MINGW_FALSE@am_binary_trees_OBJECTS = \ +@MINGW_FALSE@ benchmark/binary_trees-binary_trees.$(OBJEXT) +binary_trees_OBJECTS = $(am_binary_trees_OBJECTS) +@MINGW_FALSE@binary_trees_DEPENDENCIES = libtcmalloc_minimal.la \ +@MINGW_FALSE@ $(am__DEPENDENCIES_1) +binary_trees_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(binary_trees_CXXFLAGS) \ + $(CXXFLAGS) $(binary_trees_LDFLAGS) $(LDFLAGS) -o $@ +am__binary_trees_shared_SOURCES_DIST = benchmark/binary_trees.cc +@MINGW_FALSE@am_binary_trees_shared_OBJECTS = benchmark/binary_trees_shared-binary_trees.$(OBJEXT) +binary_trees_shared_OBJECTS = $(am_binary_trees_shared_OBJECTS) +@MINGW_FALSE@binary_trees_shared_DEPENDENCIES = \ +@MINGW_FALSE@ libtcmalloc_minimal.la $(am__DEPENDENCIES_1) +binary_trees_shared_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(binary_trees_shared_CXXFLAGS) $(CXXFLAGS) \ + $(binary_trees_shared_LDFLAGS) $(LDFLAGS) -o $@ +am_current_allocated_bytes_test_OBJECTS = src/tests/current_allocated_bytes_test-current_allocated_bytes_test.$(OBJEXT) +current_allocated_bytes_test_OBJECTS = \ + $(am_current_allocated_bytes_test_OBJECTS) +current_allocated_bytes_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +current_allocated_bytes_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) \ + $(current_allocated_bytes_test_LDFLAGS) $(LDFLAGS) -o $@ +am__debugallocation_test_SOURCES_DIST = \ + src/tests/debugallocation_test.cc +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am_debugallocation_test_OBJECTS = src/tests/debugallocation_test-debugallocation_test.$(OBJEXT) +debugallocation_test_OBJECTS = $(am_debugallocation_test_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ $(am__DEPENDENCIES_1) +debugallocation_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) \ + $(debugallocation_test_LDFLAGS) $(LDFLAGS) -o $@ +am__debugallocation_test_sh_SOURCES_DIST = \ + src/tests/debugallocation_test.sh +am_debugallocation_test_sh_OBJECTS = +debugallocation_test_sh_OBJECTS = \ + $(am_debugallocation_test_sh_OBJECTS) +debugallocation_test_sh_LDADD = $(LDADD) +am_frag_unittest_OBJECTS = \ + src/tests/frag_unittest-frag_unittest.$(OBJEXT) +frag_unittest_OBJECTS = $(am_frag_unittest_OBJECTS) +frag_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +frag_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(frag_unittest_CXXFLAGS) $(CXXFLAGS) $(frag_unittest_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__getpc_test_SOURCES_DIST = src/tests/getpc_test.cc src/getpc.h +@WITH_CPU_PROFILER_TRUE@am_getpc_test_OBJECTS = \ +@WITH_CPU_PROFILER_TRUE@ src/tests/getpc_test.$(OBJEXT) +getpc_test_OBJECTS = $(am_getpc_test_OBJECTS) +getpc_test_LDADD = $(LDADD) +am__heap_checker_death_unittest_sh_SOURCES_DIST = \ + src/tests/heap-checker-death_unittest.sh +am_heap_checker_death_unittest_sh_OBJECTS = +heap_checker_death_unittest_sh_OBJECTS = \ + $(am_heap_checker_death_unittest_sh_OBJECTS) +heap_checker_death_unittest_sh_LDADD = $(LDADD) +am__heap_checker_debug_unittest_SOURCES_DIST = \ + src/tests/heap-checker_unittest.cc src/config_for_unittests.h \ + src/memory_region_map.h src/base/commandlineflags.h \ + src/base/googleinit.h src/gperftools/heap-checker.h \ + src/base/logging.h src/base/basictypes.h \ + src/base/dynamic_annotations.h +@WITH_HEAP_CHECKER_TRUE@am__objects_31 = $(am__objects_1) +@WITH_HEAP_CHECKER_TRUE@am__objects_32 = src/tests/heap_checker_debug_unittest-heap-checker_unittest.$(OBJEXT) \ +@WITH_HEAP_CHECKER_TRUE@ $(am__objects_31) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am_heap_checker_debug_unittest_OBJECTS = $(am__objects_32) +heap_checker_debug_unittest_OBJECTS = \ + $(am_heap_checker_debug_unittest_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ liblogging.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +heap_checker_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(heap_checker_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__heap_checker_debug_unittest_sh_SOURCES_DIST = \ + src/tests/heap-checker_unittest.sh +am_heap_checker_debug_unittest_sh_OBJECTS = +heap_checker_debug_unittest_sh_OBJECTS = \ + $(am_heap_checker_debug_unittest_sh_OBJECTS) +heap_checker_debug_unittest_sh_LDADD = $(LDADD) +am__heap_checker_unittest_SOURCES_DIST = \ + src/tests/heap-checker_unittest.cc src/config_for_unittests.h \ + src/memory_region_map.h src/base/commandlineflags.h \ + src/base/googleinit.h src/gperftools/heap-checker.h \ + src/base/logging.h src/base/basictypes.h \ + src/base/dynamic_annotations.h +@WITH_HEAP_CHECKER_TRUE@am_heap_checker_unittest_OBJECTS = src/tests/heap_checker_unittest-heap-checker_unittest.$(OBJEXT) \ +@WITH_HEAP_CHECKER_TRUE@ $(am__objects_31) +heap_checker_unittest_OBJECTS = $(am_heap_checker_unittest_OBJECTS) +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_DEPENDENCIES = \ +@WITH_HEAP_CHECKER_TRUE@ $(LIBTCMALLOC) liblogging.la \ +@WITH_HEAP_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +heap_checker_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(heap_checker_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__heap_checker_unittest_sh_SOURCES_DIST = \ + src/tests/heap-checker_unittest.sh +am_heap_checker_unittest_sh_OBJECTS = +heap_checker_unittest_sh_OBJECTS = \ + $(am_heap_checker_unittest_sh_OBJECTS) +heap_checker_unittest_sh_LDADD = $(LDADD) +am__heap_profiler_debug_unittest_SOURCES_DIST = \ + src/tests/heap-profiler_unittest.cc src/config_for_unittests.h \ + src/gperftools/heap-profiler.h +@WITH_HEAP_PROFILER_TRUE@am__objects_33 = src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_TRUE@ $(am__objects_1) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am_heap_profiler_debug_unittest_OBJECTS = $(am__objects_33) +heap_profiler_debug_unittest_OBJECTS = \ + $(am_heap_profiler_debug_unittest_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ $(am__DEPENDENCIES_1) +heap_profiler_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(heap_profiler_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__heap_profiler_debug_unittest_sh_SOURCES_DIST = \ + src/tests/heap-profiler_unittest.sh +am_heap_profiler_debug_unittest_sh_OBJECTS = +heap_profiler_debug_unittest_sh_OBJECTS = \ + $(am_heap_profiler_debug_unittest_sh_OBJECTS) +heap_profiler_debug_unittest_sh_LDADD = $(LDADD) +am__heap_profiler_unittest_SOURCES_DIST = \ + src/tests/heap-profiler_unittest.cc src/config_for_unittests.h \ + src/gperftools/heap-profiler.h +@WITH_HEAP_PROFILER_TRUE@am_heap_profiler_unittest_OBJECTS = src/tests/heap_profiler_unittest-heap-profiler_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_TRUE@ $(am__objects_1) +heap_profiler_unittest_OBJECTS = $(am_heap_profiler_unittest_OBJECTS) +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_TRUE@ $(LIBTCMALLOC) $(am__DEPENDENCIES_1) +heap_profiler_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(heap_profiler_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__heap_profiler_unittest_sh_SOURCES_DIST = \ + src/tests/heap-profiler_unittest.sh +am_heap_profiler_unittest_sh_OBJECTS = +heap_profiler_unittest_sh_OBJECTS = \ + $(am_heap_profiler_unittest_sh_OBJECTS) +heap_profiler_unittest_sh_LDADD = $(LDADD) +am__low_level_alloc_unittest_SOURCES_DIST = \ + src/base/low_level_alloc.cc src/malloc_hook.cc \ + src/tests/low_level_alloc_unittest.cc \ + src/base/low_level_alloc.h src/base/basictypes.h \ + src/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/base/logging.h \ + src/base/commandlineflags.h src/base/dynamic_annotations.h +am__objects_34 = $(am__objects_1) $(am__objects_1) +am_low_level_alloc_unittest_OBJECTS = \ + src/base/low_level_alloc_unittest-low_level_alloc.$(OBJEXT) \ + src/low_level_alloc_unittest-malloc_hook.$(OBJEXT) \ + src/tests/low_level_alloc_unittest-low_level_alloc_unittest.$(OBJEXT) \ + $(am__objects_34) +low_level_alloc_unittest_OBJECTS = \ + $(am_low_level_alloc_unittest_OBJECTS) +low_level_alloc_unittest_DEPENDENCIES = $(LIBSPINLOCK) \ + libmaybe_threads.la +low_level_alloc_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__malloc_bench_SOURCES_DIST = benchmark/malloc_bench.cc +@MINGW_FALSE@am_malloc_bench_OBJECTS = \ +@MINGW_FALSE@ benchmark/malloc_bench-malloc_bench.$(OBJEXT) +malloc_bench_OBJECTS = $(am_malloc_bench_OBJECTS) +@MINGW_FALSE@malloc_bench_DEPENDENCIES = librun_benchmark.la \ +@MINGW_FALSE@ libtcmalloc_minimal.la $(am__DEPENDENCIES_1) +malloc_bench_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(malloc_bench_CXXFLAGS) \ + $(CXXFLAGS) $(malloc_bench_LDFLAGS) $(LDFLAGS) -o $@ +am__malloc_bench_shared_SOURCES_DIST = benchmark/malloc_bench.cc +@MINGW_FALSE@am_malloc_bench_shared_OBJECTS = benchmark/malloc_bench_shared-malloc_bench.$(OBJEXT) +malloc_bench_shared_OBJECTS = $(am_malloc_bench_shared_OBJECTS) +@MINGW_FALSE@malloc_bench_shared_DEPENDENCIES = librun_benchmark.la \ +@MINGW_FALSE@ libtcmalloc_minimal.la $(am__DEPENDENCIES_1) +malloc_bench_shared_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(malloc_bench_shared_CXXFLAGS) $(CXXFLAGS) \ + $(malloc_bench_shared_LDFLAGS) $(LDFLAGS) -o $@ +am__malloc_bench_shared_full_SOURCES_DIST = benchmark/malloc_bench.cc +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_malloc_bench_shared_full_OBJECTS = benchmark/malloc_bench_shared_full-malloc_bench.$(OBJEXT) +malloc_bench_shared_full_OBJECTS = \ + $(am_malloc_bench_shared_full_OBJECTS) +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@malloc_bench_shared_full_DEPENDENCIES = librun_benchmark.la \ +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc.la \ +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +malloc_bench_shared_full_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(malloc_bench_shared_full_CXXFLAGS) $(CXXFLAGS) \ + $(malloc_bench_shared_full_LDFLAGS) $(LDFLAGS) -o $@ +am__malloc_extension_c_test_SOURCES_DIST = \ + src/tests/malloc_extension_c_test.c \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h +@MINGW_FALSE@am_malloc_extension_c_test_OBJECTS = src/tests/malloc_extension_c_test-malloc_extension_c_test.$(OBJEXT) +malloc_extension_c_test_OBJECTS = \ + $(am_malloc_extension_c_test_OBJECTS) +@MINGW_FALSE@malloc_extension_c_test_DEPENDENCIES = \ +@MINGW_FALSE@ $(LIBTCMALLOC_MINIMAL) $(am__DEPENDENCIES_1) +malloc_extension_c_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(malloc_extension_c_test_CFLAGS) $(CFLAGS) \ + $(malloc_extension_c_test_LDFLAGS) $(LDFLAGS) -o $@ +am__malloc_extension_debug_test_SOURCES_DIST = \ + src/tests/malloc_extension_test.cc src/config_for_unittests.h \ + src/base/logging.h src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h +am__objects_35 = src/tests/malloc_extension_debug_test-malloc_extension_test.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@am_malloc_extension_debug_test_OBJECTS = \ +@WITH_DEBUGALLOC_TRUE@ $(am__objects_35) +malloc_extension_debug_test_OBJECTS = \ + $(am_malloc_extension_debug_test_OBJECTS) +@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_DEPENDENCIES = \ +@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \ +@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) +malloc_extension_debug_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) \ + $(malloc_extension_debug_test_LDFLAGS) $(LDFLAGS) -o $@ +am_malloc_extension_test_OBJECTS = src/tests/malloc_extension_test-malloc_extension_test.$(OBJEXT) +malloc_extension_test_OBJECTS = $(am_malloc_extension_test_OBJECTS) +malloc_extension_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +malloc_extension_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) \ + $(malloc_extension_test_LDFLAGS) $(LDFLAGS) -o $@ +am_malloc_hook_test_OBJECTS = \ + src/tests/malloc_hook_test-malloc_hook_test.$(OBJEXT) \ + src/tests/malloc_hook_test-testutil.$(OBJEXT) +malloc_hook_test_OBJECTS = $(am_malloc_hook_test_OBJECTS) +malloc_hook_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +malloc_hook_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) \ + $(malloc_hook_test_LDFLAGS) $(LDFLAGS) -o $@ +am_markidle_unittest_OBJECTS = \ + src/tests/markidle_unittest-markidle_unittest.$(OBJEXT) \ + src/tests/markidle_unittest-testutil.$(OBJEXT) +markidle_unittest_OBJECTS = $(am_markidle_unittest_OBJECTS) +markidle_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +markidle_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(markidle_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__maybe_threads_unittest_sh_SOURCES_DIST = \ + src/tests/maybe_threads_unittest.sh +am_maybe_threads_unittest_sh_OBJECTS = +maybe_threads_unittest_sh_OBJECTS = \ + $(am_maybe_threads_unittest_sh_OBJECTS) +maybe_threads_unittest_sh_LDADD = $(LDADD) +am__memalign_debug_unittest_SOURCES_DIST = \ + src/tests/memalign_unittest.cc src/tcmalloc.h \ + src/config_for_unittests.h src/tests/testutil.h \ + src/tests/testutil.cc +@MINGW_FALSE@@OSX_FALSE@am__objects_36 = src/tests/memalign_debug_unittest-memalign_unittest.$(OBJEXT) \ +@MINGW_FALSE@@OSX_FALSE@ src/tests/memalign_debug_unittest-testutil.$(OBJEXT) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am_memalign_debug_unittest_OBJECTS = $(am__objects_36) +memalign_debug_unittest_OBJECTS = \ + $(am_memalign_debug_unittest_OBJECTS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_DEPENDENCIES = libtcmalloc_minimal_debug.la \ +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) +memalign_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(memalign_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__memalign_unittest_SOURCES_DIST = src/tests/memalign_unittest.cc \ + src/tcmalloc.h src/config_for_unittests.h src/tests/testutil.h \ + src/tests/testutil.cc +@MINGW_FALSE@@OSX_FALSE@am_memalign_unittest_OBJECTS = src/tests/memalign_unittest-memalign_unittest.$(OBJEXT) \ +@MINGW_FALSE@@OSX_FALSE@ src/tests/memalign_unittest-testutil.$(OBJEXT) +memalign_unittest_OBJECTS = $(am_memalign_unittest_OBJECTS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_DEPENDENCIES = \ +@MINGW_FALSE@@OSX_FALSE@ $(LIBTCMALLOC_MINIMAL) \ +@MINGW_FALSE@@OSX_FALSE@ $(am__DEPENDENCIES_1) +memalign_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(memalign_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am_packed_cache_test_OBJECTS = \ + src/tests/packed_cache_test-packed-cache_test.$(OBJEXT) +packed_cache_test_OBJECTS = $(am_packed_cache_test_OBJECTS) +packed_cache_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +packed_cache_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) \ + $(packed_cache_test_LDFLAGS) $(LDFLAGS) -o $@ +am_page_heap_test_OBJECTS = \ + src/tests/page_heap_test-page_heap_test.$(OBJEXT) +page_heap_test_OBJECTS = $(am_page_heap_test_OBJECTS) +page_heap_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +page_heap_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(page_heap_test_CXXFLAGS) $(CXXFLAGS) \ + $(page_heap_test_LDFLAGS) $(LDFLAGS) -o $@ +am_pagemap_unittest_OBJECTS = \ + src/tests/pagemap_unittest-pagemap_unittest.$(OBJEXT) +pagemap_unittest_OBJECTS = $(am_pagemap_unittest_OBJECTS) +pagemap_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +pagemap_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(pagemap_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__profile_handler_unittest_SOURCES_DIST = \ + src/tests/profile-handler_unittest.cc src/profile-handler.h +@WITH_CPU_PROFILER_TRUE@am_profile_handler_unittest_OBJECTS = src/tests/profile_handler_unittest-profile-handler_unittest.$(OBJEXT) +profile_handler_unittest_OBJECTS = \ + $(am_profile_handler_unittest_OBJECTS) +@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_DEPENDENCIES = \ +@WITH_CPU_PROFILER_TRUE@ $(LIBPROFILER) $(am__DEPENDENCIES_1) +profile_handler_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(profile_handler_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__profiledata_unittest_SOURCES_DIST = \ + src/tests/profiledata_unittest.cc src/profiledata.h \ + src/base/commandlineflags.h src/base/logging.h \ + src/base/basictypes.h +@WITH_CPU_PROFILER_TRUE@am_profiledata_unittest_OBJECTS = src/tests/profiledata_unittest.$(OBJEXT) +profiledata_unittest_OBJECTS = $(am_profiledata_unittest_OBJECTS) +@WITH_CPU_PROFILER_TRUE@profiledata_unittest_DEPENDENCIES = \ +@WITH_CPU_PROFILER_TRUE@ $(LIBPROFILER) +am__profiler1_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + src/config_for_unittests.h src/gperftools/profiler.h +@WITH_CPU_PROFILER_TRUE@am__objects_37 = src/tests/profiler1_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ src/tests/profiler1_unittest-testutil.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am_profiler1_unittest_OBJECTS = \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_37) +profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS) +@WITH_CPU_PROFILER_TRUE@profiler1_unittest_DEPENDENCIES = \ +@WITH_CPU_PROFILER_TRUE@ $(LIBPROFILER) +profiler1_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__profiler2_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + src/config_for_unittests.h src/gperftools/profiler.h +@WITH_CPU_PROFILER_TRUE@am__objects_38 = src/tests/profiler2_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ src/tests/profiler2_unittest-testutil.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am_profiler2_unittest_OBJECTS = \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_38) +profiler2_unittest_OBJECTS = $(am_profiler2_unittest_OBJECTS) +profiler2_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__profiler3_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + src/config_for_unittests.h src/gperftools/profiler.h +@WITH_CPU_PROFILER_TRUE@am__objects_39 = src/tests/profiler3_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ src/tests/profiler3_unittest-testutil.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am_profiler3_unittest_OBJECTS = \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_39) +profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS) +@WITH_CPU_PROFILER_TRUE@profiler3_unittest_DEPENDENCIES = \ +@WITH_CPU_PROFILER_TRUE@ $(LIBPROFILER) $(am__DEPENDENCIES_1) +profiler3_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(profiler3_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__profiler4_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + src/config_for_unittests.h src/gperftools/profiler.h +@WITH_CPU_PROFILER_TRUE@am__objects_40 = src/tests/profiler4_unittest-profiler_unittest.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ src/tests/profiler4_unittest-testutil.$(OBJEXT) \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_1) +@WITH_CPU_PROFILER_TRUE@am_profiler4_unittest_OBJECTS = \ +@WITH_CPU_PROFILER_TRUE@ $(am__objects_40) +profiler4_unittest_OBJECTS = $(am_profiler4_unittest_OBJECTS) +profiler4_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(profiler4_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__profiler_unittest_sh_SOURCES_DIST = \ + src/tests/profiler_unittest.sh +am_profiler_unittest_sh_OBJECTS = +profiler_unittest_sh_OBJECTS = $(am_profiler_unittest_sh_OBJECTS) +profiler_unittest_sh_LDADD = $(LDADD) +am__raw_printer_test_SOURCES_DIST = src/tests/raw_printer_test.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_raw_printer_test_OBJECTS = src/tests/raw_printer_test-raw_printer_test.$(OBJEXT) +raw_printer_test_OBJECTS = $(am_raw_printer_test_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +raw_printer_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) \ + $(raw_printer_test_LDFLAGS) $(LDFLAGS) -o $@ +am__realloc_debug_unittest_SOURCES_DIST = \ + src/tests/realloc_unittest.cc src/config_for_unittests.h \ + src/base/logging.h +am__objects_41 = \ + src/tests/realloc_debug_unittest-realloc_unittest.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@am_realloc_debug_unittest_OBJECTS = \ +@WITH_DEBUGALLOC_TRUE@ $(am__objects_41) +realloc_debug_unittest_OBJECTS = $(am_realloc_debug_unittest_OBJECTS) +@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_DEPENDENCIES = \ +@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \ +@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) +realloc_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(realloc_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am_realloc_unittest_OBJECTS = \ + src/tests/realloc_unittest-realloc_unittest.$(OBJEXT) +realloc_unittest_OBJECTS = $(am_realloc_unittest_OBJECTS) +realloc_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +realloc_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(realloc_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__sampler_debug_test_SOURCES_DIST = src/tests/sampler_test.cc \ + src/config_for_unittests.h +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_42 = src/tests/sampler_debug_test-sampler_test.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_debug_test_OBJECTS = $(am__objects_42) +sampler_debug_test_OBJECTS = $(am_sampler_debug_test_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +sampler_debug_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) \ + $(sampler_debug_test_LDFLAGS) $(LDFLAGS) -o $@ +am__sampler_test_SOURCES_DIST = src/tests/sampler_test.cc \ + src/config_for_unittests.h +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_test_OBJECTS = src/tests/sampler_test-sampler_test.$(OBJEXT) +sampler_test_OBJECTS = $(am_sampler_test_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +sampler_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(sampler_test_CXXFLAGS) \ + $(CXXFLAGS) $(sampler_test_LDFLAGS) $(LDFLAGS) -o $@ +am__sampling_debug_test_SOURCES_DIST = src/tests/sampling_test.cc \ + src/config_for_unittests.h src/base/logging.h \ + src/gperftools/malloc_extension.h +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_43 = src/tests/sampling_debug_test-sampling_test.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampling_debug_test_OBJECTS = $(am__objects_43) +sampling_debug_test_OBJECTS = $(am_sampling_debug_test_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +sampling_debug_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) \ + $(sampling_debug_test_LDFLAGS) $(LDFLAGS) -o $@ +am__sampling_debug_test_sh_SOURCES_DIST = src/tests/sampling_test.sh +am_sampling_debug_test_sh_OBJECTS = +sampling_debug_test_sh_OBJECTS = $(am_sampling_debug_test_sh_OBJECTS) +sampling_debug_test_sh_LDADD = $(LDADD) +am__sampling_test_SOURCES_DIST = src/tests/sampling_test.cc \ + src/config_for_unittests.h src/base/logging.h \ + src/gperftools/malloc_extension.h +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampling_test_OBJECTS = src/tests/sampling_test-sampling_test.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1) +sampling_test_OBJECTS = $(am_sampling_test_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +sampling_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(sampling_test_CXXFLAGS) $(CXXFLAGS) $(sampling_test_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__sampling_test_sh_SOURCES_DIST = src/tests/sampling_test.sh +am_sampling_test_sh_OBJECTS = +sampling_test_sh_OBJECTS = $(am_sampling_test_sh_OBJECTS) +sampling_test_sh_LDADD = $(LDADD) +am__simple_compat_test_SOURCES_DIST = src/tests/simple_compat_test.cc \ + src/google/heap-checker.h src/google/heap-profiler.h \ + src/google/malloc_extension.h src/google/malloc_extension_c.h \ + src/google/malloc_hook.h src/google/malloc_hook_c.h \ + src/google/profiler.h src/google/stacktrace.h \ + src/google/tcmalloc.h +@WITH_HEAP_PROFILER_TRUE@am_simple_compat_test_OBJECTS = src/tests/simple_compat_test.$(OBJEXT) \ +@WITH_HEAP_PROFILER_TRUE@ $(am__objects_1) +simple_compat_test_OBJECTS = $(am_simple_compat_test_OBJECTS) +@WITH_HEAP_PROFILER_TRUE@simple_compat_test_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_TRUE@ $(LIBTCMALLOC) +simple_compat_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(simple_compat_test_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_stack_trace_table_test_OBJECTS = src/tests/stack_trace_table_test-stack_trace_table_test.$(OBJEXT) +stack_trace_table_test_OBJECTS = $(am_stack_trace_table_test_OBJECTS) +stack_trace_table_test_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +stack_trace_table_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) \ + $(stack_trace_table_test_LDFLAGS) $(LDFLAGS) -o $@ +am__stacktrace_unittest_SOURCES_DIST = \ + src/tests/stacktrace_unittest.cc src/config_for_unittests.h \ + src/base/commandlineflags.h src/stacktrace_impl_setup-inl.h \ + src/stacktrace_generic-inl.h src/stacktrace_generic_fp-inl.h \ + src/stacktrace_libgcc-inl.h src/stacktrace_libunwind-inl.h \ + src/stacktrace_arm-inl.h src/stacktrace_powerpc-inl.h \ + src/stacktrace_powerpc-darwin-inl.h \ + src/stacktrace_powerpc-linux-inl.h src/stacktrace_x86-inl.h \ + src/stacktrace_win32-inl.h src/stacktrace_instrument-inl.h \ + src/base/elf_mem_image.h src/base/vdso_support.h \ + src/gperftools/stacktrace.h src/base/logging.h \ + src/base/basictypes.h src/base/dynamic_annotations.h +@WITH_STACK_TRACE_TRUE@am__objects_44 = $(am__objects_6) \ +@WITH_STACK_TRACE_TRUE@ $(am__objects_1) +@WITH_STACK_TRACE_TRUE@am_stacktrace_unittest_OBJECTS = src/tests/stacktrace_unittest.$(OBJEXT) \ +@WITH_STACK_TRACE_TRUE@ $(am__objects_44) +stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS) +@WITH_STACK_TRACE_TRUE@stacktrace_unittest_DEPENDENCIES = \ +@WITH_STACK_TRACE_TRUE@ libstacktrace.la liblogging.la \ +@WITH_STACK_TRACE_TRUE@ libfake_stacktrace_scope.la +am__system_alloc_unittest_SOURCES_DIST = src/config_for_unittests.h \ + src/tests/system-alloc_unittest.cc +@MINGW_FALSE@am_system_alloc_unittest_OBJECTS = src/tests/system_alloc_unittest-system-alloc_unittest.$(OBJEXT) +system_alloc_unittest_OBJECTS = $(am_system_alloc_unittest_OBJECTS) +@MINGW_FALSE@system_alloc_unittest_DEPENDENCIES = \ +@MINGW_FALSE@ $(LIBTCMALLOC_MINIMAL) $(am__DEPENDENCIES_1) +system_alloc_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(system_alloc_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcm_asserts_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tcmalloc.h \ + src/tests/testutil.h src/tests/testutil.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcm_asserts_unittest_OBJECTS = src/tests/tcm_asserts_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/tcm_asserts_unittest-testutil.$(OBJEXT) +tcm_asserts_unittest_OBJECTS = $(am_tcm_asserts_unittest_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_DEPENDENCIES = libtcmalloc_with_asserts.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +tcm_asserts_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcm_asserts_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcm_min_asserts_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ + src/tests/testutil.cc src/common.cc src/internal_logging.cc \ + src/system-alloc.cc src/memfs_malloc.cc \ + src/central_freelist.cc src/page_heap.cc src/sampler.cc \ + src/span.cc src/stack_trace_table.cc src/static_vars.cc \ + src/symbolize.cc src/thread_cache.cc src/malloc_hook.cc \ + src/malloc_extension.cc src/common.h src/internal_logging.h \ + src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \ + src/base/spinlock_internal.h src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-linuxppc.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \ + src/base/spinlock_posix-inl.h \ + src/base/atomicops-internals-arm-generic.h \ + src/base/atomicops-internals-arm-v6plus.h \ + src/base/atomicops-internals-mips.h \ + src/base/atomicops-internals-gcc.h src/tcmalloc_guard.h \ + src/base/commandlineflags.h src/base/basictypes.h \ + src/pagemap.h src/sampler.h src/central_freelist.h \ + src/linked_list.h src/libc_override.h \ + src/libc_override_gcc_and_weak.h src/libc_override_glibc.h \ + src/libc_override_osx.h src/libc_override_redefine.h \ + src/page_heap.h src/page_heap_allocator.h src/span.h \ + src/static_vars.h src/symbolize.h src/thread_cache.h \ + src/stack_trace_table.h src/base/thread_annotations.h \ + src/malloc_hook-inl.h src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/stacktrace.h src/tcmalloc.cc +@MINGW_FALSE@am__objects_45 = src/tcm_min_asserts_unittest-system-alloc.$(OBJEXT) +am__objects_46 = src/tcm_min_asserts_unittest-common.$(OBJEXT) \ + src/tcm_min_asserts_unittest-internal_logging.$(OBJEXT) \ + $(am__objects_45) \ + src/tcm_min_asserts_unittest-memfs_malloc.$(OBJEXT) \ + src/tcm_min_asserts_unittest-central_freelist.$(OBJEXT) \ + src/tcm_min_asserts_unittest-page_heap.$(OBJEXT) \ + src/tcm_min_asserts_unittest-sampler.$(OBJEXT) \ + src/tcm_min_asserts_unittest-span.$(OBJEXT) \ + src/tcm_min_asserts_unittest-stack_trace_table.$(OBJEXT) \ + src/tcm_min_asserts_unittest-static_vars.$(OBJEXT) \ + src/tcm_min_asserts_unittest-symbolize.$(OBJEXT) \ + src/tcm_min_asserts_unittest-thread_cache.$(OBJEXT) \ + src/tcm_min_asserts_unittest-malloc_hook.$(OBJEXT) \ + src/tcm_min_asserts_unittest-malloc_extension.$(OBJEXT) \ + $(am__objects_18) +@MINGW_FALSE@am__objects_47 = \ +@MINGW_FALSE@ src/tcm_min_asserts_unittest-tcmalloc.$(OBJEXT) +am__objects_48 = $(am__objects_47) $(am__objects_18) +am_tcm_min_asserts_unittest_OBJECTS = src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.$(OBJEXT) \ + src/tests/tcm_min_asserts_unittest-testutil.$(OBJEXT) \ + $(am__objects_46) $(am__objects_48) +tcm_min_asserts_unittest_OBJECTS = \ + $(am_tcm_min_asserts_unittest_OBJECTS) +tcm_min_asserts_unittest_DEPENDENCIES = $(LIBSPINLOCK) \ + libmaybe_threads.la liblogging.la $(am__DEPENDENCIES_1) +tcm_min_asserts_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcm_min_asserts_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_and_profiler_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ + src/tests/testutil.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_49 = src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/tcmalloc_and_profiler_unittest-testutil.$(OBJEXT) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_49) +tcmalloc_and_profiler_unittest_OBJECTS = \ + $(am_tcmalloc_and_profiler_unittest_OBJECTS) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_DEPENDENCIES = libtcmalloc_and_profiler.la +tcmalloc_and_profiler_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_and_profiler_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_both_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ + src/tests/testutil.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_50 = src/tests/tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/tcmalloc_both_unittest-testutil.$(OBJEXT) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_both_unittest_OBJECTS = $(am__objects_50) +tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS) +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_3 = $(LIBTCMALLOC) \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_3 = $(LIBTCMALLOC) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_3) +tcmalloc_both_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_both_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_debug_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tcmalloc.h \ + src/tests/testutil.h src/tests/testutil.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_51 = src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/tcmalloc_debug_unittest-testutil.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_debug_unittest_OBJECTS = $(am__objects_51) +tcmalloc_debug_unittest_OBJECTS = \ + $(am_tcmalloc_debug_unittest_OBJECTS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +tcmalloc_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_large_heap_fragmentation_unittest_SOURCES_DIST = \ + src/tests/large_heap_fragmentation_unittest.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_large_heap_fragmentation_unittest_OBJECTS = src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.$(OBJEXT) +tcmalloc_large_heap_fragmentation_unittest_OBJECTS = \ + $(am_tcmalloc_large_heap_fragmentation_unittest_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +tcmalloc_large_heap_fragmentation_unittest_LINK = $(LIBTOOL) \ + $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) \ + $(tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS) \ + $(CXXFLAGS) \ + $(tcmalloc_large_heap_fragmentation_unittest_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__tcmalloc_large_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_large_unittest.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_large_unittest_OBJECTS = src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.$(OBJEXT) +tcmalloc_large_unittest_OBJECTS = \ + $(am_tcmalloc_large_unittest_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +tcmalloc_large_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_large_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_minimal_debug_unittest_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.cc src/tests/testutil.h \ + src/tests/testutil.cc +am__objects_52 = src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.$(OBJEXT) \ + src/tests/tcmalloc_minimal_debug_unittest-testutil.$(OBJEXT) +@WITH_DEBUGALLOC_TRUE@am_tcmalloc_minimal_debug_unittest_OBJECTS = \ +@WITH_DEBUGALLOC_TRUE@ $(am__objects_52) +tcmalloc_minimal_debug_unittest_OBJECTS = \ + $(am_tcmalloc_minimal_debug_unittest_OBJECTS) +@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_DEPENDENCIES = \ +@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \ +@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1) +tcmalloc_minimal_debug_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_minimal_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am_tcmalloc_minimal_large_heap_fragmentation_unittest_OBJECTS = src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.$(OBJEXT) +tcmalloc_minimal_large_heap_fragmentation_unittest_OBJECTS = $(am_tcmalloc_minimal_large_heap_fragmentation_unittest_OBJECTS) +tcmalloc_minimal_large_heap_fragmentation_unittest_DEPENDENCIES = \ + $(LIBTCMALLOC_MINIMAL) $(am__DEPENDENCIES_1) +tcmalloc_minimal_large_heap_fragmentation_unittest_LINK = $(LIBTOOL) \ + $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) \ + $(tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS) \ + $(CXXFLAGS) \ + $(tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_tcmalloc_minimal_large_unittest_OBJECTS = src/tests/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) \ + $(am__DEPENDENCIES_1) +tcmalloc_minimal_large_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_minimal_large_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am_tcmalloc_minimal_unittest_OBJECTS = src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.$(OBJEXT) \ + src/tests/tcmalloc_minimal_unittest-testutil.$(OBJEXT) +tcmalloc_minimal_unittest_OBJECTS = \ + $(am_tcmalloc_minimal_unittest_OBJECTS) +tcmalloc_minimal_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + liblogging.la $(am__DEPENDENCIES_1) +tcmalloc_minimal_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_minimal_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_unittest_SOURCES_DIST = src/tests/tcmalloc_unittest.cc \ + src/tcmalloc.h src/tests/testutil.h src/tests/testutil.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_unittest_OBJECTS = src/tests/tcmalloc_unittest-tcmalloc_unittest.$(OBJEXT) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/tcmalloc_unittest-testutil.$(OBJEXT) +tcmalloc_unittest_OBJECTS = $(am_tcmalloc_unittest_OBJECTS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_DEPENDENCIES = \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LIBTCMALLOC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) +tcmalloc_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(tcmalloc_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am__tcmalloc_unittest_sh_SOURCES_DIST = \ + src/tests/tcmalloc_unittest.sh +am_tcmalloc_unittest_sh_OBJECTS = +tcmalloc_unittest_sh_OBJECTS = $(am_tcmalloc_unittest_sh_OBJECTS) +tcmalloc_unittest_sh_LDADD = $(LDADD) +am_thread_dealloc_unittest_OBJECTS = src/tests/thread_dealloc_unittest-thread_dealloc_unittest.$(OBJEXT) \ + src/tests/thread_dealloc_unittest-testutil.$(OBJEXT) +thread_dealloc_unittest_OBJECTS = \ + $(am_thread_dealloc_unittest_OBJECTS) +thread_dealloc_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \ + $(am__DEPENDENCIES_1) +thread_dealloc_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(thread_dealloc_unittest_LDFLAGS) $(LDFLAGS) -o $@ +SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + benchmark/$(DEPDIR)/binary_trees-binary_trees.Po \ + benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po \ + benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po \ + benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po \ + benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po \ + benchmark/$(DEPDIR)/run_benchmark.Plo \ + src/$(DEPDIR)/fake_stacktrace_scope.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo \ + src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo \ + src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo \ + src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo \ + src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-common.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-span.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Plo \ + src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Plo \ + src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo \ + src/$(DEPDIR)/libtcmalloc_la-heap-checker.Plo \ + src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo \ + src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo \ + src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Plo \ + src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Plo \ + src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Plo \ + src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po \ + src/$(DEPDIR)/maybe_threads.Plo \ + src/$(DEPDIR)/profile-handler.Plo \ + src/$(DEPDIR)/profiledata.Plo src/$(DEPDIR)/profiler.Plo \ + src/$(DEPDIR)/stacktrace.Plo \ + src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po \ + src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po \ + src/base/$(DEPDIR)/atomicops-internals-x86.Plo \ + src/base/$(DEPDIR)/dynamic_annotations.Plo \ + src/base/$(DEPDIR)/elf_mem_image.Plo \ + src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo \ + src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo \ + src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo \ + src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Plo \ + src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo \ + src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Plo \ + src/base/$(DEPDIR)/logging.Plo \ + src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po \ + src/base/$(DEPDIR)/spinlock.Plo \ + src/base/$(DEPDIR)/spinlock_internal.Plo \ + src/base/$(DEPDIR)/sysinfo.Plo \ + src/base/$(DEPDIR)/thread_lister.Plo \ + src/base/$(DEPDIR)/vdso_support.Plo \ + src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po \ + src/tests/$(DEPDIR)/atomicops_unittest.Po \ + src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po \ + src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po \ + src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po \ + src/tests/$(DEPDIR)/getpc_test.Po \ + src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po \ + src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po \ + src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po \ + src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po \ + src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po \ + src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po \ + src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po \ + src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po \ + src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po \ + src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po \ + src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po \ + src/tests/$(DEPDIR)/markidle_unittest-testutil.Po \ + src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po \ + src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po \ + src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po \ + src/tests/$(DEPDIR)/memalign_unittest-testutil.Po \ + src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po \ + src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po \ + src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po \ + src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po \ + src/tests/$(DEPDIR)/profiledata_unittest.Po \ + src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po \ + src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po \ + src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po \ + src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po \ + src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po \ + src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po \ + src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po \ + src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po \ + src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po \ + src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po \ + src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po \ + src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po \ + src/tests/$(DEPDIR)/sampler_test-sampler_test.Po \ + src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po \ + src/tests/$(DEPDIR)/sampling_test-sampling_test.Po \ + src/tests/$(DEPDIR)/simple_compat_test.Po \ + src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po \ + src/tests/$(DEPDIR)/stacktrace_unittest.Po \ + src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po \ + src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po \ + src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po \ + src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po \ + src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po \ + src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po \ + src/windows/$(DEPDIR)/addressmap_unittest-port.Po \ + src/windows/$(DEPDIR)/ia32_modrm_map.Plo \ + src/windows/$(DEPDIR)/ia32_opcode_map.Plo \ + src/windows/$(DEPDIR)/mini_disassembler.Plo \ + src/windows/$(DEPDIR)/patch_functions.Plo \ + src/windows/$(DEPDIR)/port.Plo \ + src/windows/$(DEPDIR)/preamble_patcher.Plo \ + src/windows/$(DEPDIR)/preamble_patcher_with_stub.Plo \ + src/windows/$(DEPDIR)/system-alloc.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(libfake_stacktrace_scope_la_SOURCES) \ + $(liblogging_la_SOURCES) $(libmaybe_threads_la_SOURCES) \ + $(libprofiler_la_SOURCES) $(librun_benchmark_la_SOURCES) \ + $(libspinlock_la_SOURCES) $(libstacktrace_la_SOURCES) \ + $(libsysinfo_la_SOURCES) $(libtcmalloc_la_SOURCES) \ + $(libtcmalloc_and_profiler_la_SOURCES) \ + $(libtcmalloc_debug_la_SOURCES) \ + $(libtcmalloc_internal_la_SOURCES) \ + $(libtcmalloc_internal_with_asserts_la_SOURCES) \ + $(libtcmalloc_minimal_la_SOURCES) \ + $(libtcmalloc_minimal_debug_la_SOURCES) \ + $(libtcmalloc_minimal_internal_la_SOURCES) \ + $(libtcmalloc_with_asserts_la_SOURCES) \ + $(libwindows_la_SOURCES) $(addressmap_unittest_SOURCES) \ + $(atomicops_unittest_SOURCES) $(binary_trees_SOURCES) \ + $(binary_trees_shared_SOURCES) \ + $(current_allocated_bytes_test_SOURCES) \ + $(debugallocation_test_SOURCES) \ + $(debugallocation_test_sh_SOURCES) $(frag_unittest_SOURCES) \ + $(getpc_test_SOURCES) \ + $(heap_checker_death_unittest_sh_SOURCES) \ + $(heap_checker_debug_unittest_SOURCES) \ + $(heap_checker_debug_unittest_sh_SOURCES) \ + $(heap_checker_unittest_SOURCES) \ + $(heap_checker_unittest_sh_SOURCES) \ + $(heap_profiler_debug_unittest_SOURCES) \ + $(heap_profiler_debug_unittest_sh_SOURCES) \ + $(heap_profiler_unittest_SOURCES) \ + $(heap_profiler_unittest_sh_SOURCES) \ + $(low_level_alloc_unittest_SOURCES) $(malloc_bench_SOURCES) \ + $(malloc_bench_shared_SOURCES) \ + $(malloc_bench_shared_full_SOURCES) \ + $(malloc_extension_c_test_SOURCES) \ + $(malloc_extension_debug_test_SOURCES) \ + $(malloc_extension_test_SOURCES) $(malloc_hook_test_SOURCES) \ + $(markidle_unittest_SOURCES) \ + $(maybe_threads_unittest_sh_SOURCES) \ + $(memalign_debug_unittest_SOURCES) \ + $(memalign_unittest_SOURCES) $(packed_cache_test_SOURCES) \ + $(page_heap_test_SOURCES) $(pagemap_unittest_SOURCES) \ + $(profile_handler_unittest_SOURCES) \ + $(profiledata_unittest_SOURCES) $(profiler1_unittest_SOURCES) \ + $(profiler2_unittest_SOURCES) $(profiler3_unittest_SOURCES) \ + $(profiler4_unittest_SOURCES) $(profiler_unittest_sh_SOURCES) \ + $(raw_printer_test_SOURCES) $(realloc_debug_unittest_SOURCES) \ + $(realloc_unittest_SOURCES) $(sampler_debug_test_SOURCES) \ + $(sampler_test_SOURCES) $(sampling_debug_test_SOURCES) \ + $(sampling_debug_test_sh_SOURCES) $(sampling_test_SOURCES) \ + $(sampling_test_sh_SOURCES) $(simple_compat_test_SOURCES) \ + $(stack_trace_table_test_SOURCES) \ + $(stacktrace_unittest_SOURCES) \ + $(system_alloc_unittest_SOURCES) \ + $(tcm_asserts_unittest_SOURCES) \ + $(tcm_min_asserts_unittest_SOURCES) \ + $(tcmalloc_and_profiler_unittest_SOURCES) \ + $(tcmalloc_both_unittest_SOURCES) \ + $(tcmalloc_debug_unittest_SOURCES) \ + $(tcmalloc_large_heap_fragmentation_unittest_SOURCES) \ + $(tcmalloc_large_unittest_SOURCES) \ + $(tcmalloc_minimal_debug_unittest_SOURCES) \ + $(tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES) \ + $(tcmalloc_minimal_large_unittest_SOURCES) \ + $(tcmalloc_minimal_unittest_SOURCES) \ + $(tcmalloc_unittest_SOURCES) $(tcmalloc_unittest_sh_SOURCES) \ + $(thread_dealloc_unittest_SOURCES) +DIST_SOURCES = $(am__libfake_stacktrace_scope_la_SOURCES_DIST) \ + $(liblogging_la_SOURCES) \ + $(am__libmaybe_threads_la_SOURCES_DIST) \ + $(am__libprofiler_la_SOURCES_DIST) \ + $(am__librun_benchmark_la_SOURCES_DIST) \ + $(am__libspinlock_la_SOURCES_DIST) \ + $(am__libstacktrace_la_SOURCES_DIST) $(libsysinfo_la_SOURCES) \ + $(am__libtcmalloc_la_SOURCES_DIST) \ + $(am__libtcmalloc_and_profiler_la_SOURCES_DIST) \ + $(am__libtcmalloc_debug_la_SOURCES_DIST) \ + $(am__libtcmalloc_internal_la_SOURCES_DIST) \ + $(am__libtcmalloc_internal_with_asserts_la_SOURCES_DIST) \ + $(am__libtcmalloc_minimal_la_SOURCES_DIST) \ + $(am__libtcmalloc_minimal_debug_la_SOURCES_DIST) \ + $(am__libtcmalloc_minimal_internal_la_SOURCES_DIST) \ + $(am__libtcmalloc_with_asserts_la_SOURCES_DIST) \ + $(am__libwindows_la_SOURCES_DIST) \ + $(am__addressmap_unittest_SOURCES_DIST) \ + $(atomicops_unittest_SOURCES) $(am__binary_trees_SOURCES_DIST) \ + $(am__binary_trees_shared_SOURCES_DIST) \ + $(current_allocated_bytes_test_SOURCES) \ + $(am__debugallocation_test_SOURCES_DIST) \ + $(am__debugallocation_test_sh_SOURCES_DIST) \ + $(frag_unittest_SOURCES) $(am__getpc_test_SOURCES_DIST) \ + $(am__heap_checker_death_unittest_sh_SOURCES_DIST) \ + $(am__heap_checker_debug_unittest_SOURCES_DIST) \ + $(am__heap_checker_debug_unittest_sh_SOURCES_DIST) \ + $(am__heap_checker_unittest_SOURCES_DIST) \ + $(am__heap_checker_unittest_sh_SOURCES_DIST) \ + $(am__heap_profiler_debug_unittest_SOURCES_DIST) \ + $(am__heap_profiler_debug_unittest_sh_SOURCES_DIST) \ + $(am__heap_profiler_unittest_SOURCES_DIST) \ + $(am__heap_profiler_unittest_sh_SOURCES_DIST) \ + $(am__low_level_alloc_unittest_SOURCES_DIST) \ + $(am__malloc_bench_SOURCES_DIST) \ + $(am__malloc_bench_shared_SOURCES_DIST) \ + $(am__malloc_bench_shared_full_SOURCES_DIST) \ + $(am__malloc_extension_c_test_SOURCES_DIST) \ + $(am__malloc_extension_debug_test_SOURCES_DIST) \ + $(malloc_extension_test_SOURCES) $(malloc_hook_test_SOURCES) \ + $(markidle_unittest_SOURCES) \ + $(am__maybe_threads_unittest_sh_SOURCES_DIST) \ + $(am__memalign_debug_unittest_SOURCES_DIST) \ + $(am__memalign_unittest_SOURCES_DIST) \ + $(packed_cache_test_SOURCES) $(page_heap_test_SOURCES) \ + $(pagemap_unittest_SOURCES) \ + $(am__profile_handler_unittest_SOURCES_DIST) \ + $(am__profiledata_unittest_SOURCES_DIST) \ + $(am__profiler1_unittest_SOURCES_DIST) \ + $(am__profiler2_unittest_SOURCES_DIST) \ + $(am__profiler3_unittest_SOURCES_DIST) \ + $(am__profiler4_unittest_SOURCES_DIST) \ + $(am__profiler_unittest_sh_SOURCES_DIST) \ + $(am__raw_printer_test_SOURCES_DIST) \ + $(am__realloc_debug_unittest_SOURCES_DIST) \ + $(realloc_unittest_SOURCES) \ + $(am__sampler_debug_test_SOURCES_DIST) \ + $(am__sampler_test_SOURCES_DIST) \ + $(am__sampling_debug_test_SOURCES_DIST) \ + $(am__sampling_debug_test_sh_SOURCES_DIST) \ + $(am__sampling_test_SOURCES_DIST) \ + $(am__sampling_test_sh_SOURCES_DIST) \ + $(am__simple_compat_test_SOURCES_DIST) \ + $(stack_trace_table_test_SOURCES) \ + $(am__stacktrace_unittest_SOURCES_DIST) \ + $(am__system_alloc_unittest_SOURCES_DIST) \ + $(am__tcm_asserts_unittest_SOURCES_DIST) \ + $(am__tcm_min_asserts_unittest_SOURCES_DIST) \ + $(am__tcmalloc_and_profiler_unittest_SOURCES_DIST) \ + $(am__tcmalloc_both_unittest_SOURCES_DIST) \ + $(am__tcmalloc_debug_unittest_SOURCES_DIST) \ + $(am__tcmalloc_large_heap_fragmentation_unittest_SOURCES_DIST) \ + $(am__tcmalloc_large_unittest_SOURCES_DIST) \ + $(am__tcmalloc_minimal_debug_unittest_SOURCES_DIST) \ + $(tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES) \ + $(tcmalloc_minimal_large_unittest_SOURCES) \ + $(tcmalloc_minimal_unittest_SOURCES) \ + $(am__tcmalloc_unittest_SOURCES_DIST) \ + $(am__tcmalloc_unittest_sh_SOURCES_DIST) \ + $(thread_dealloc_unittest_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(dist_man_MANS) +am__dist_doc_DATA_DIST = AUTHORS COPYING ChangeLog INSTALL NEWS README \ + README_windows.txt TODO ChangeLog.old docs/index.html \ + docs/designstyle.css docs/pprof_remote_servers.html \ + docs/tcmalloc.html docs/overview.gif docs/pageheap.gif \ + docs/spanmap.gif docs/threadheap.gif docs/t-test1.times.txt \ + docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \ + docs/tcmalloc-opspersec.vs.size.1.threads.png \ + docs/tcmalloc-opspersec.vs.size.12.threads.png \ + docs/tcmalloc-opspersec.vs.size.16.threads.png \ + docs/tcmalloc-opspersec.vs.size.2.threads.png \ + docs/tcmalloc-opspersec.vs.size.20.threads.png \ + docs/tcmalloc-opspersec.vs.size.3.threads.png \ + docs/tcmalloc-opspersec.vs.size.4.threads.png \ + docs/tcmalloc-opspersec.vs.size.5.threads.png \ + docs/tcmalloc-opspersec.vs.size.8.threads.png \ + docs/overview.dot docs/pageheap.dot docs/spanmap.dot \ + docs/threadheap.dot docs/heapprofile.html \ + docs/heap-example1.png docs/heap_checker.html \ + docs/cpuprofile.html docs/cpuprofile-fileformat.html \ + docs/pprof-test-big.gif docs/pprof-test.gif \ + docs/pprof-vsnprintf-big.gif docs/pprof-vsnprintf.gif +DATA = $(dist_doc_DATA) $(pkgconfig_DATA) +am__perftoolsinclude_HEADERS_DIST = src/gperftools/stacktrace.h \ + src/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h src/gperftools/nallocx.h \ + src/gperftools/heap-profiler.h src/gperftools/heap-checker.h \ + src/gperftools/profiler.h +HEADERS = $(googleinclude_HEADERS) $(nodist_perftoolsinclude_HEADERS) \ + $(noinst_HEADERS) $(perftoolsinclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope check recheck +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ + $(top_srcdir)/src/config.h.in \ + $(top_srcdir)/src/gperftools/tcmalloc.h.in \ + $(top_srcdir)/src/windows/gperftools/tcmalloc.h.in AUTHORS \ + COPYING ChangeLog INSTALL NEWS README TODO compile \ + config.guess config.sub depcomp install-sh ltmain.sh missing \ + test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).zip +GZIP_ENV = --best +DIST_TARGETS = dist-gzip dist-zip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GIT = @GIT@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSTDCXX_LA_LINKER_FLAG = @LIBSTDCXX_LA_LINKER_FLAG@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NANOSLEEP_LIBS = @NANOSLEEP_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJCOPY = @OBJCOPY@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROFILER_SO_VERSION = @PROFILER_SO_VERSION@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TCMALLOC_AND_PROFILER_SO_VERSION = @TCMALLOC_AND_PROFILER_SO_VERSION@ +TCMALLOC_SO_VERSION = @TCMALLOC_SO_VERSION@ +TC_VERSION_MAJOR = @TC_VERSION_MAJOR@ +TC_VERSION_MINOR = @TC_VERSION_MINOR@ +TC_VERSION_PATCH = @TC_VERSION_PATCH@ +UNWIND_LIBS = @UNWIND_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_have_std_align_val_t = @ac_cv_have_std_align_val_t@ +ac_cv_have_struct_mallinfo = @ac_cv_have_struct_mallinfo@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Make sure that when we re-make ./configure, we get the macros we need +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +# This is so we can #include +AM_CPPFLAGS = -I$(top_srcdir)/src $(am__append_1) + +# This is mostly based on configure options +AM_CXXFLAGS = $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) $(am__append_7) \ + $(am__append_8) + +# The -no-undefined flag allows libtool to generate shared libraries for +# Cygwin and MinGW. LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug. +AM_LDFLAGS = -no-undefined $(LIBSTDCXX_LA_LINKER_FLAG) + +# For windows systems (at least, mingw), we need to tell all our +# tests to link in libtcmalloc using -u. This is because libtcmalloc +# accomplishes its tasks via patching, leaving no work for the linker +# to identify, so the linker will ignore libtcmalloc by default unless +# we explicitly create a dependency via -u. +TCMALLOC_FLAGS = $(am__append_9) +@HAVE_OBJCOPY_WEAKEN_FALSE@WEAKEN = : + +# If we have objcopy, make malloc/free/etc weak symbols. That way folks +# can override our malloc if they want to (they can still use tc_malloc). +# Note: the weird-looking symbols are the c++ memory functions: +# (in order) new, new(nothrow), new[], new[](nothrow), delete, delete[] +# In theory this will break if mangling changes, but that seems pretty +# unlikely at this point. Just in case, I throw in versions with an +# extra underscore as well, which may help on OS X. +@HAVE_OBJCOPY_WEAKEN_TRUE@WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W memalign -W posix_memalign -W valloc -W pvalloc \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W aligned_alloc \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W malloc_stats -W mallopt -W mallinfo -W nallocx \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W _ZdlPv -W _ZdaPv \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \ +@HAVE_OBJCOPY_WEAKEN_TRUE@ -W __ZdlPv -W __ZdaPv + +LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_31) \ + $(am__append_46) $(am__append_63) $(am__append_78) +perftoolsincludedir = $(includedir)/gperftools +# The .h files you want to install (that is, .h files that people +# who install this package can include in their own applications.) +# We'll add to this later, on a library-by-library basis +perftoolsinclude_HEADERS = $(am__append_15) \ + $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_43) \ + $(am__append_70) +# tcmalloc.h is a special case, because it's a .h.in file +nodist_perftoolsinclude_HEADERS = src/gperftools/tcmalloc.h +noinst_HEADERS = src/gperftools/tcmalloc.h.in + +# This is provided for backwards compatibility. It is populated by +# files that just forward to the canonical location in +# perftoolsincludedir. +googleincludedir = $(includedir)/google +googleinclude_HEADERS = \ + src/google/heap-checker.h \ + src/google/heap-profiler.h \ + src/google/malloc_extension.h \ + src/google/malloc_extension_c.h \ + src/google/malloc_hook.h \ + src/google/malloc_hook_c.h \ + src/google/profiler.h \ + src/google/stacktrace.h \ + src/google/tcmalloc.h + + +# This is for HTML and other documentation you want to install. +# Add your documentation files (in doc/) in addition to these +# top-level boilerplate files. Also add a TODO file if you have one. +# We'll add to this later, on a library-by-library basis + +### Documentation + +# I don't know how to say "distribute the .dot files but don't install them"; +# noinst doesn't seem to work with data. I separate them out anyway, in case +# one day we figure it out. Regardless, installing the dot files isn't the +# end of the world. +dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ + README_windows.txt TODO ChangeLog.old docs/index.html \ + docs/designstyle.css $(am__append_18) $(am__append_21) \ + docs/tcmalloc.html docs/overview.gif docs/pageheap.gif \ + docs/spanmap.gif docs/threadheap.gif docs/t-test1.times.txt \ + docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \ + docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \ + docs/tcmalloc-opspersec.vs.size.1.threads.png \ + docs/tcmalloc-opspersec.vs.size.12.threads.png \ + docs/tcmalloc-opspersec.vs.size.16.threads.png \ + docs/tcmalloc-opspersec.vs.size.2.threads.png \ + docs/tcmalloc-opspersec.vs.size.20.threads.png \ + docs/tcmalloc-opspersec.vs.size.3.threads.png \ + docs/tcmalloc-opspersec.vs.size.4.threads.png \ + docs/tcmalloc-opspersec.vs.size.5.threads.png \ + docs/tcmalloc-opspersec.vs.size.8.threads.png \ + docs/overview.dot docs/pageheap.dot docs/spanmap.dot \ + docs/threadheap.dot $(am__append_60) $(am__append_61) \ + $(am__append_75) + +# The libraries (.so's) you want to install +# We'll add to this later, on a library-by-library basis +lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_30) \ + $(am__append_45) $(am__append_62) $(am__append_71) \ + $(am__append_76) +# This is for 'convenience libraries' -- basically just a container for sources + +### Making the library +noinst_LTLIBRARIES = liblogging.la libsysinfo.la libmaybe_threads.la \ + $(am__append_10) $(am__append_13) $(am__append_16) \ + libtcmalloc_minimal_internal.la $(am__append_38) \ + $(am__append_44) + +# 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 = gperftools.sln \ + vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj \ + 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.vcxproj \ + $(am__append_22) \ + vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj \ + vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj \ + vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj \ + vsprojects/addressmap_unittest/addressmap_unittest.vcxproj \ + vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj \ + vsprojects/packed-cache_test/packed-cache_test.vcxproj \ + vsprojects/frag_unittest/frag_unittest.vcxproj \ + vsprojects/markidle_unittest/markidle_unittest.vcxproj \ + vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj \ + vsprojects/malloc_hook_test/malloc_hook_test.vcxproj \ + vsprojects/malloc_extension_test/malloc_extension_test.vcxproj \ + vsprojects/page_heap_test/page_heap_test.vcxproj \ + vsprojects/pagemap_unittest/pagemap_unittest.vcxproj \ + vsprojects/realloc_unittest/realloc_unittest.vcxproj \ + vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj \ + vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj \ + $(am__append_53) +# 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. +TESTS_ENVIRONMENT = $(am__append_19) $(am__append_52) +# All script tests should be added here +noinst_SCRIPTS = $(am__append_24) $(am__append_36) $(am__append_48) \ + $(am__append_55) $(am__append_58) $(am__append_73) + +# This is my own var, used for extra libraries I make that I need installed +EXTRA_INSTALL = + +### ------- library routines, in src/base + +# This is a 'convenience library' -- it's not actually installed or anything +LOGGING_INCLUDES = src/base/logging.h \ + src/base/commandlineflags.h \ + src/base/basictypes.h \ + src/base/dynamic_annotations.h + +liblogging_la_SOURCES = src/base/logging.cc \ + src/base/dynamic_annotations.c \ + $(LOGGING_INCLUDES) + +SYSINFO_INCLUDES = src/base/sysinfo.h \ + src/getenv_safe.h \ + src/base/logging.h \ + src/base/commandlineflags.h \ + src/base/arm_instruction_set_select.h \ + src/base/basictypes.h + +libsysinfo_la_SOURCES = src/base/sysinfo.cc \ + $(SYSINFO_INCLUDES) + +libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_11) +# .cc is conditionally added below +libmaybe_threads_la_SOURCES = src/maybe_threads.h $(am__append_12) \ + $(am__append_14) + +# For MinGW, we use also have to use libwindows Luckily, we need the +# windows.a library in exactly the same place we need spinlock.a +# (pretty much everywhere), so we can use the same variable name for +# each. We can also optimize the MinGW rule a bit by leaving out +# files we know aren't used on windows, such as +# atomicops-internals-x86.cc. libwindows also obsoletes the need for +# other files like system_alloc.cc. +@MINGW_TRUE@WINDOWS_INCLUDES = src/windows/port.h \ +@MINGW_TRUE@ src/windows/mingw.h \ +@MINGW_TRUE@ src/windows/mini_disassembler.h \ +@MINGW_TRUE@ src/windows/mini_disassembler_types.h \ +@MINGW_TRUE@ src/windows/preamble_patcher.h + +@MINGW_TRUE@libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \ +@MINGW_TRUE@ src/windows/port.cc \ +@MINGW_TRUE@ src/windows/system-alloc.cc \ +@MINGW_TRUE@ src/windows/ia32_modrm_map.cc \ +@MINGW_TRUE@ src/windows/ia32_opcode_map.cc \ +@MINGW_TRUE@ src/windows/mini_disassembler.cc \ +@MINGW_TRUE@ src/windows/patch_functions.cc \ +@MINGW_TRUE@ src/windows/preamble_patcher.cc \ +@MINGW_TRUE@ src/windows/preamble_patcher_with_stub.cc + +# patch_functions.cc uses Psapi.lib. MSVC has a #pragma for that, but not us. +@MINGW_TRUE@libwindows_la_LIBADD = -lpsapi +# spinlock is the only code that uses atomicops. +@MINGW_FALSE@SPINLOCK_INCLUDES = src/base/spinlock.h \ +@MINGW_FALSE@ src/base/spinlock_internal.h \ +@MINGW_FALSE@ src/base/atomicops.h \ +@MINGW_FALSE@ src/base/atomicops-internals-macosx.h \ +@MINGW_FALSE@ src/base/atomicops-internals-linuxppc.h \ +@MINGW_FALSE@ src/base/atomicops-internals-windows.h \ +@MINGW_FALSE@ src/base/atomicops-internals-x86.h + +@MINGW_TRUE@SPINLOCK_INCLUDES = src/base/spinlock.h \ +@MINGW_TRUE@ src/base/spinlock_internal.h \ +@MINGW_TRUE@ src/base/spinlock_win32-inl.h \ +@MINGW_TRUE@ src/base/spinlock_linux-inl.h \ +@MINGW_TRUE@ src/base/spinlock_posix-inl.h \ +@MINGW_TRUE@ src/base/atomicops-internals-macosx.h \ +@MINGW_TRUE@ src/base/atomicops-internals-linuxppc.h \ +@MINGW_TRUE@ src/base/atomicops-internals-arm-generic.h \ +@MINGW_TRUE@ src/base/atomicops-internals-arm-v6plus.h \ +@MINGW_TRUE@ src/base/atomicops-internals-mips.h \ +@MINGW_TRUE@ src/base/atomicops-internals-windows.h \ +@MINGW_TRUE@ src/base/atomicops-internals-gcc.h \ +@MINGW_TRUE@ src/base/atomicops-internals-x86.h + +@MINGW_FALSE@libspinlock_la_SOURCES = src/base/spinlock.cc \ +@MINGW_FALSE@ src/base/spinlock_internal.cc \ +@MINGW_FALSE@ src/base/atomicops-internals-x86.cc \ +@MINGW_FALSE@ $(SPINLOCK_INCLUDES) + +@MINGW_TRUE@libspinlock_la_SOURCES = src/base/spinlock.cc \ +@MINGW_TRUE@ src/base/spinlock_internal.cc \ +@MINGW_TRUE@ src/base/atomicops-internals-x86.cc \ +@MINGW_TRUE@ $(SPINLOCK_INCLUDES) + +# spinlock also needs NumCPUs, from libsysinfo, which in turn needs liblogging +@MINGW_FALSE@LIBSPINLOCK = libspinlock.la libsysinfo.la liblogging.la +@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@SYSTEM_ALLOC_CC = src/system-alloc.cc +@MINGW_TRUE@SYSTEM_ALLOC_CC = +@MINGW_FALSE@libspinlock_la_LIBADD = $(NANOSLEEP_LIBS) +LOW_LEVEL_ALLOC_UNITTEST_INCLUDES = src/base/low_level_alloc.h \ + src/base/basictypes.h \ + src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h \ + $(SPINLOCK_INCLUDES) \ + $(LOGGING_INCLUDES) + +low_level_alloc_unittest_SOURCES = src/base/low_level_alloc.cc \ + src/malloc_hook.cc \ + src/tests/low_level_alloc_unittest.cc \ + $(LOW_LEVEL_ALLOC_UNITTEST_INCLUDES) + +# By default, MallocHook takes stack traces for use by the heap-checker. +# We don't need that functionality here, so we turn it off to reduce deps. +low_level_alloc_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES +low_level_alloc_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la +ATOMICOPS_UNITTEST_INCLUDES = src/base/atomicops.h \ + src/base/atomicops-internals-macosx.h \ + src/base/atomicops-internals-windows.h \ + src/base/atomicops-internals-x86.h \ + $(LOGGING_INCLUDES) + +atomicops_unittest_SOURCES = src/tests/atomicops_unittest.cc \ + $(ATOMICOPS_UNITTEST_INCLUDES) + +atomicops_unittest_LDADD = $(LIBSPINLOCK) + +### ------- stack trace + +### The header files we use. We divide into categories based on directory +@WITH_STACK_TRACE_TRUE@S_STACKTRACE_INCLUDES = src/stacktrace_impl_setup-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_generic-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_generic_fp-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_libgcc-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_libunwind-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_arm-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-darwin-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_powerpc-linux-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_x86-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_win32-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/stacktrace_instrument-inl.h \ +@WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.h \ +@WITH_STACK_TRACE_TRUE@ src/base/vdso_support.h + +@WITH_STACK_TRACE_TRUE@SG_STACKTRACE_INCLUDES = src/gperftools/stacktrace.h +@WITH_STACK_TRACE_TRUE@STACKTRACE_INCLUDES = $(S_STACKTRACE_INCLUDES) $(SG_STACKTRACE_INCLUDES) +@WITH_STACK_TRACE_TRUE@libstacktrace_la_SOURCES = src/stacktrace.cc \ +@WITH_STACK_TRACE_TRUE@ src/base/elf_mem_image.cc \ +@WITH_STACK_TRACE_TRUE@ src/base/vdso_support.cc \ +@WITH_STACK_TRACE_TRUE@ $(STACKTRACE_INCLUDES) + +@WITH_STACK_TRACE_TRUE@libstacktrace_la_LIBADD = $(UNWIND_LIBS) $(LIBSPINLOCK) +@WITH_STACK_TRACE_TRUE@STACKTRACE_SYMBOLS = '(GetStackTrace|GetStackFrames|GetStackTraceWithContext|GetStackFramesWithContext)' +@WITH_STACK_TRACE_TRUE@libstacktrace_la_LDFLAGS = -export-symbols-regex $(STACKTRACE_SYMBOLS) $(AM_LDFLAGS) +@WITH_STACK_TRACE_TRUE@libfake_stacktrace_scope_la_SOURCES = src/fake_stacktrace_scope.cc +@WITH_STACK_TRACE_TRUE@STACKTRACE_UNITTEST_INCLUDES = src/config_for_unittests.h \ +@WITH_STACK_TRACE_TRUE@ src/base/commandlineflags.h \ +@WITH_STACK_TRACE_TRUE@ $(STACKTRACE_INCLUDES) \ +@WITH_STACK_TRACE_TRUE@ $(LOGGING_INCLUDES) + +@WITH_STACK_TRACE_TRUE@stacktrace_unittest_SOURCES = src/tests/stacktrace_unittest.cc \ +@WITH_STACK_TRACE_TRUE@ $(STACKTRACE_UNITTEST_INCLUDES) + +@WITH_STACK_TRACE_TRUE@stacktrace_unittest_LDADD = libstacktrace.la liblogging.la libfake_stacktrace_scope.la + +### ------- pprof + +# If we are not compiling with stacktrace support, pprof is worthless +@WITH_STACK_TRACE_TRUE@bin_SCRIPTS = pprof-symbolize $(am__append_20) + +### Unittests +@WITH_STACK_TRACE_TRUE@check_SCRIPTS = pprof_unittest +@INSTALL_PPROF_TRUE@@WITH_STACK_TRACE_TRUE@dist_man_MANS = docs/pprof.1 + +### ------- tcmalloc_minimal (thread-caching malloc) + +### The header files we use. We divide into categories based on directory +S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \ + src/internal_logging.h \ + src/system-alloc.h \ + src/packed-cache-inl.h \ + $(SPINLOCK_INCLUDES) \ + src/tcmalloc_guard.h \ + src/base/commandlineflags.h \ + src/base/basictypes.h \ + src/pagemap.h \ + src/sampler.h \ + src/central_freelist.h \ + src/linked_list.h \ + src/libc_override.h \ + src/libc_override_gcc_and_weak.h \ + src/libc_override_glibc.h \ + src/libc_override_osx.h \ + src/libc_override_redefine.h \ + src/page_heap.h \ + src/page_heap_allocator.h \ + src/span.h \ + src/static_vars.h \ + src/symbolize.h \ + src/thread_cache.h \ + src/stack_trace_table.h \ + src/base/thread_annotations.h \ + src/malloc_hook-inl.h \ + src/malloc_hook_mmap_linux.h \ + src/malloc_hook_mmap_freebsd.h + +SG_TCMALLOC_MINIMAL_INCLUDES = src/gperftools/malloc_hook.h \ + src/gperftools/malloc_hook_c.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h \ + src/gperftools/nallocx.h + +TCMALLOC_MINIMAL_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES) $(SG_STACKTRACE_INCLUDES) +libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \ + src/internal_logging.cc \ + $(SYSTEM_ALLOC_CC) \ + src/memfs_malloc.cc \ + src/central_freelist.cc \ + src/page_heap.cc \ + src/sampler.cc \ + src/span.cc \ + src/stack_trace_table.cc \ + src/static_vars.cc \ + src/symbolize.cc \ + src/thread_cache.cc \ + src/malloc_hook.cc \ + src/malloc_extension.cc \ + $(TCMALLOC_MINIMAL_INCLUDES) + +# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal. +libtcmalloc_minimal_internal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \ + -DNO_HEAP_CHECK \ + -DNDEBUG \ + $(AM_CXXFLAGS) + +libtcmalloc_minimal_internal_la_LDFLAGS = $(AM_LDFLAGS) +libtcmalloc_minimal_internal_la_LIBADD = $(LIBSPINLOCK) libmaybe_threads.la +libtcmalloc_minimal_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_MINIMAL_INCLUDES) +libtcmalloc_minimal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \ + $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS) + +# -version-info gets passed to libtool +libtcmalloc_minimal_la_LDFLAGS = -version-info @TCMALLOC_SO_VERSION@ $(AM_LDFLAGS) +libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la +@MINGW_FALSE@LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la + +# For windows, we're playing around with trying to do some stacktrace +# support even with libtcmalloc_minimal. For everyone else, though, +# we turn off all stack-trace activity for libtcmalloc_minimal. +# TODO(csilvers): when we're done experimenting, do something principled here +@MINGW_TRUE@LIBTCMALLOC_MINIMAL = libtcmalloc_minimal.la libstacktrace.la +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) $(AM_CXXFLAGS) +tcmalloc_minimal_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +tcmalloc_minimal_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) \ + liblogging.la $(PTHREAD_LIBS) + +tcm_min_asserts_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ + src/tests/testutil.h src/tests/testutil.cc \ + $(libtcmalloc_minimal_internal_la_SOURCES) \ + $(libtcmalloc_minimal_la_SOURCES) \ + $(TCMALLOC_UNITTEST_INCLUDES) + +tcm_min_asserts_unittest_CXXFLAGS = -DNO_TCMALLOC_SAMPLES -DNO_HEAP_CHECK \ + $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) + +tcm_min_asserts_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcm_min_asserts_unittest_LDADD = $(LIBSPINLOCK) libmaybe_threads.la \ + liblogging.la $(PTHREAD_LIBS) + +tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc +tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_minimal_large_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +tcmalloc_minimal_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc +tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +@ENABLE_STATIC_FALSE@@MINGW_FALSE@maybe_threads_unittest_sh_SOURCES = src/tests/maybe_threads_unittest.sh +ADDRESSMAP_UNITTEST_INCLUDES = src/addressmap-inl.h \ + src/base/commandlineflags.h \ + $(LOGGING_INCLUDES) + +addressmap_unittest_SOURCES = src/tests/addressmap_unittest.cc \ + $(ADDRESSMAP_UNITTEST_INCLUDES) $(am__append_25) +addressmap_unittest_CXXFLAGS = -g $(AM_CXXFLAGS) +addressmap_unittest_LDADD = liblogging.la +@MINGW_FALSE@system_alloc_unittest_SOURCES = src/config_for_unittests.h \ +@MINGW_FALSE@ src/tests/system-alloc_unittest.cc + +@MINGW_FALSE@system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +packed_cache_test_SOURCES = src/tests/packed-cache_test.cc +packed_cache_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +packed_cache_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +packed_cache_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h +frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +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) $(AM_CXXFLAGS) +markidle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +markidle_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +current_allocated_bytes_test_SOURCES = src/tests/current_allocated_bytes_test.cc \ + src/config_for_unittests.h + +current_allocated_bytes_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +current_allocated_bytes_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +current_allocated_bytes_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +malloc_hook_test_SOURCES = src/tests/malloc_hook_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/gperftools/malloc_hook.h \ + src/tests/testutil.h src/tests/testutil.cc + +malloc_hook_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_hook_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_hook_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +malloc_extension_test_SOURCES = src/tests/malloc_extension_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/gperftools/malloc_extension.h \ + src/gperftools/malloc_extension_c.h + +malloc_extension_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +malloc_extension_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +malloc_extension_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +@MINGW_FALSE@malloc_extension_c_test_SOURCES = src/tests/malloc_extension_c_test.c \ +@MINGW_FALSE@ src/gperftools/malloc_extension.h \ +@MINGW_FALSE@ src/gperftools/malloc_extension_c.h + +@MINGW_FALSE@malloc_extension_c_test_CFLAGS = $(PTHREAD_CFLAGS) \ +@MINGW_FALSE@ $(AM_CFLAGS) $(am__append_28) +@MINGW_FALSE@malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) -lstdc++ -lm +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_SOURCES = src/tests/memalign_unittest.cc \ +@MINGW_FALSE@@OSX_FALSE@ src/tcmalloc.h \ +@MINGW_FALSE@@OSX_FALSE@ src/config_for_unittests.h \ +@MINGW_FALSE@@OSX_FALSE@ src/tests/testutil.h src/tests/testutil.cc + +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@@OSX_FALSE@memalign_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +page_heap_test_SOURCES = src/tests/page_heap_test.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/common.h \ + src/page_heap.h + +page_heap_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +page_heap_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +page_heap_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +pagemap_unittest_SOURCES = src/tests/pagemap_unittest.cc \ + src/config_for_unittests.h \ + src/base/logging.h \ + src/pagemap.h + +pagemap_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +pagemap_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +pagemap_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +realloc_unittest_SOURCES = src/tests/realloc_unittest.cc \ + src/config_for_unittests.h \ + src/base/logging.h + +realloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +realloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +realloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +stack_trace_table_test_SOURCES = src/tests/stack_trace_table_test.cc \ + src/config_for_unittests.h + +stack_trace_table_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +stack_trace_table_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +stack_trace_table_test_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) $(AM_CXXFLAGS) +thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \ +@WITH_DEBUGALLOC_TRUE@ $(TCMALLOC_MINIMAL_INCLUDES) + +@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \ +@WITH_DEBUGALLOC_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION + +# version_info gets passed to libtool +@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS) \ +@WITH_DEBUGALLOC_TRUE@ -version-info @TCMALLOC_SO_VERSION@ + +@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD) +@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_SOURCES = $(tcmalloc_minimal_unittest_SOURCES) +@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_CXXFLAGS = $(tcmalloc_minimal_unittest_CXXFLAGS) \ +@WITH_DEBUGALLOC_TRUE@ -DDEBUGALLOCATION + +@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_LDFLAGS = $(tcmalloc_minimal_unittest_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_SOURCES = $(malloc_extension_test_SOURCES) +@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS) +@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES) +@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_SOURCES = src/tests/debugallocation_test.cc +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) +@MINGW_FALSE@librun_benchmark_la_SOURCES = \ +@MINGW_FALSE@ benchmark/run_benchmark.c benchmark/run_benchmark.h + +@MINGW_FALSE@malloc_bench_SOURCES = benchmark/malloc_bench.cc +@MINGW_FALSE@malloc_bench_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@malloc_bench_LDFLAGS = $(PTHREAD_CFLAGS) \ +@MINGW_FALSE@ $(TCMALLOC_FLAGS) $(am__append_40) +@MINGW_FALSE@malloc_bench_LDADD = librun_benchmark.la libtcmalloc_minimal.la $(PTHREAD_LIBS) +@MINGW_FALSE@malloc_bench_shared_SOURCES = benchmark/malloc_bench.cc +@MINGW_FALSE@malloc_bench_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@malloc_bench_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@malloc_bench_shared_LDADD = librun_benchmark.la libtcmalloc_minimal.la $(PTHREAD_LIBS) +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@malloc_bench_shared_full_SOURCES = benchmark/malloc_bench.cc +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@malloc_bench_shared_full_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@malloc_bench_shared_full_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@malloc_bench_shared_full_LDADD = librun_benchmark.la libtcmalloc.la $(PTHREAD_LIBS) +@MINGW_FALSE@binary_trees_SOURCES = benchmark/binary_trees.cc +@MINGW_FALSE@binary_trees_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@binary_trees_LDFLAGS = $(PTHREAD_CFLAGS) \ +@MINGW_FALSE@ $(TCMALLOC_FLAGS) $(am__append_42) +@MINGW_FALSE@binary_trees_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) +@MINGW_FALSE@binary_trees_shared_SOURCES = benchmark/binary_trees.cc +@MINGW_FALSE@binary_trees_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@MINGW_FALSE@binary_trees_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@MINGW_FALSE@binary_trees_shared_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) + +### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker) + +### The header files we use. We divide into categories based on directory +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@S_TCMALLOC_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(LOGGING_INCLUDES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/addressmap-inl.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/raw_printer.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/elfcore.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/googleinit.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/linux_syscall_support.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/linuxthreads.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/stl_allocator.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/sysinfo.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/thread_lister.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-table.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-stats.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/maybe_emergency_malloc.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/emergency_malloc.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@SG_TCMALLOC_INCLUDES = src/gperftools/heap-profiler.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/gperftools/heap-checker.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@TCMALLOC_INCLUDES = $(S_TCMALLOC_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(SG_TCMALLOC_INCLUDES) $(SG_STACKTRACE_INCLUDES) + +@BUILD_EMERGENCY_MALLOC_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@EMERGENCY_MALLOC_CC = src/fake_stacktrace_scope.cc +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@EMERGENCY_MALLOC_CC = src/emergency_malloc.cc src/emergency_malloc_for_stacktrace.cc +@BUILD_EMERGENCY_MALLOC_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@EMERGENCY_MALLOC_DEFINE = +@BUILD_EMERGENCY_MALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@EMERGENCY_MALLOC_DEFINE = -DENABLE_EMERGENCY_MALLOC +@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES = + +### Making the library + +# heap-checker-bcad is last, in hopes its global ctor will run first. +# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la, +# but that's ok; the internal/external distinction is only useful for +# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.) +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES = src/base/thread_lister.c \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/linuxthreads.cc \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker.cc \ +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker-bcad.cc + +@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@MAYBE_NO_HEAP_CHECK = -DNO_HEAP_CHECK +@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@MAYBE_NO_HEAP_CHECK = +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_SOURCES = $(libtcmalloc_minimal_internal_la_SOURCES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/low_level_alloc.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profile-table.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-profiler.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/raw_printer.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(EMERGENCY_MALLOC_CC) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/memory_region_map.cc + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) $(EMERGENCY_MALLOC_DEFINE) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(MAYBE_NO_HEAP_CHECK) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_SOURCES = $(TCMALLOC_CC) $(TCMALLOC_INCLUDES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(HEAP_CHECKER_SOURCES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LIBADD = libtcmalloc_internal.la libmaybe_threads.la $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_with_asserts_la_SOURCES = $(libtcmalloc_internal_la_SOURCES) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_with_asserts_la_CXXFLAGS = $(PTHREAD_CFLAGS) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) $(EMERGENCY_MALLOC_DEFINE) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(MAYBE_NO_HEAP_CHECK) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_with_asserts_la_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_with_asserts_la_LIBADD = libstacktrace.la $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_with_asserts_la_SOURCES = $(libtcmalloc_la_SOURCES) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_with_asserts_la_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(MAYBE_NO_HEAP_CHECK) $(EMERGENCY_MALLOC_DEFINE) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_with_asserts_la_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_with_asserts_la_LIBADD = libtcmalloc_internal_with_asserts.la libmaybe_threads.la $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@LIBTCMALLOC = libtcmalloc.la +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_sh_SOURCES = src/tests/tcmalloc_unittest.sh +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_INCLUDES = src/config_for_unittests.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/gperftools/malloc_extension.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tcmalloc.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_INCLUDES = src/config_for_unittests.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/gperftools/malloc_extension.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tcmalloc.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcm_asserts_unittest_LDADD = libtcmalloc_with_asserts.la liblogging.la $(PTHREAD_LIBS) + +# This makes sure it's safe to link in both tcmalloc and +# tcmalloc_minimal. (One would never do this on purpose, but perhaps +# by accident...) When we can compile libprofiler, we also link it in +# to make sure that works too. NOTE: On OS X, it's *not* safe to +# link both in (we end up with two copies of every global var, and +# the code tends to pick one arbitrarily), so don't run the test there. +# (We define these outside the 'if' because they're reused below.) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_srcs = src/tests/tcmalloc_unittest.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_UNITTEST_INCLUDES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_cflags = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_lflags = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la $(PTHREAD_LIBS) + +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_ladd = $(LIBTCMALLOC) $(LIBTCMALLOC_MINIMAL) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la liblogging.la $(PTHREAD_LIBS) + +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_LDADD = $(tcmalloc_both_unittest_ladd) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_SOURCES = src/tests/large_heap_fragmentation_unittest.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_heap_fragmentation_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_SOURCES = src/tests/raw_printer_test.cc +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_SOURCES = src/tests/sampler_test.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/config_for_unittests.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) -lm +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_sh_SOURCES = src/tests/sampling_test.sh +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@SAMPLING_TEST_INCLUDES = src/config_for_unittests.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/logging.h \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/gperftools/malloc_extension.h + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_SOURCES = src/tests/sampling_test.cc \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(SAMPLING_TEST_INCLUDES) + +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh +@WITH_HEAP_PROFILER_TRUE@HEAP_PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \ +@WITH_HEAP_PROFILER_TRUE@ src/gperftools/heap-profiler.h + +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_SOURCES = src/tests/heap-profiler_unittest.cc \ +@WITH_HEAP_PROFILER_TRUE@ $(HEAP_PROFILER_UNITTEST_INCLUDES) + +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_LDADD = $(LIBTCMALLOC) $(PTHREAD_LIBS) +@WITH_HEAP_PROFILER_TRUE@simple_compat_test_SOURCES = src/tests/simple_compat_test.cc \ +@WITH_HEAP_PROFILER_TRUE@ $(googleinclude_HEADERS) + +@WITH_HEAP_PROFILER_TRUE@simple_compat_test_LDFLAGS = $(TCMALLOC_FLAGS) +@WITH_HEAP_PROFILER_TRUE@simple_compat_test_LDADD = $(LIBTCMALLOC) +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh +@WITH_HEAP_CHECKER_TRUE@heap_checker_death_unittest_sh_SOURCES = src/tests/heap-checker-death_unittest.sh +@WITH_HEAP_CHECKER_TRUE@HEAP_CHECKER_UNITTEST_INCLUDES = src/config_for_unittests.h \ +@WITH_HEAP_CHECKER_TRUE@ src/memory_region_map.h \ +@WITH_HEAP_CHECKER_TRUE@ src/base/commandlineflags.h \ +@WITH_HEAP_CHECKER_TRUE@ src/base/googleinit.h \ +@WITH_HEAP_CHECKER_TRUE@ src/gperftools/heap-checker.h \ +@WITH_HEAP_CHECKER_TRUE@ $(LOGGING_INCLUDES) + +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_SOURCES = src/tests/heap-checker_unittest.cc \ +@WITH_HEAP_CHECKER_TRUE@ $(HEAP_CHECKER_UNITTEST_INCLUDES) + +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +# We also put pthreads after tcmalloc, because some pthread +# implementations define their own malloc, and we need to go on the +# first linkline to make sure our malloc 'wins'. +@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_LDADD = $(LIBTCMALLOC) liblogging.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_SOURCES = src/debugallocation.cc $(HEAP_CHECKER_SOURCES) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) + +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION + +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -version-info @TCMALLOC_SO_VERSION@ + +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_SOURCES = $(tcmalloc_unittest_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_CXXFLAGS = $(tcmalloc_unittest_CXXFLAGS) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -DDEBUGALLOCATION + +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_LDFLAGS = $(tcmalloc_unittest_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_SOURCES = $(sampler_test_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_CXXFLAGS = $(samples_test_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_LDFLAGS = $(sampler_test_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) -lm +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_sh_SOURCES = src/tests/sampling_test.sh +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_SOURCES = $(sampling_test_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_CXXFLAGS = $(sampling_test_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_LDFLAGS = $(sampling_test_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_SOURCES = $(heap_profiler_unittest_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_CXXFLAGS = $(heap_profiler_unittest_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_LDFLAGS = $(heap_profiler_unittest_LDFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_SOURCES = $(heap_checker_unittest_SOURCES) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_CXXFLAGS = $(heap_checker_unittest_CXXFLAGS) +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_LDFLAGS = $(heap_checker_unittest_LDFLAGS) +# We want libtcmalloc last on the link line, but due to a bug in +# libtool involving convenience libs, they need to come last on the +# link line in order to get dependency ordering right. This is ok: +# convenience libraries are .a's, so tcmalloc is still the last .so. +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_LDADD = libtcmalloc_debug.la liblogging.la \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ $(PTHREAD_LIBS) + + +### ------- CPU profiler + +### The header files we use. We divide into categories based on directory +@WITH_CPU_PROFILER_TRUE@S_CPU_PROFILER_INCLUDES = src/profiledata.h \ +@WITH_CPU_PROFILER_TRUE@ src/profile-handler.h \ +@WITH_CPU_PROFILER_TRUE@ src/getpc.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/basictypes.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/commandlineflags.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/googleinit.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/logging.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/simple_mutex.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/sysinfo.h \ +@WITH_CPU_PROFILER_TRUE@ $(SPINLOCK_INCLUDES) \ +@WITH_CPU_PROFILER_TRUE@ $(LOGGING_INCLUDES) + +@WITH_CPU_PROFILER_TRUE@SG_CPU_PROFILER_INCLUDES = src/gperftools/profiler.h +@WITH_CPU_PROFILER_TRUE@CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_INCLUDES) \ +@WITH_CPU_PROFILER_TRUE@ $(SG_STACKTRACE_INCLUDES) + +@WITH_CPU_PROFILER_TRUE@libprofiler_la_SOURCES = src/profiler.cc \ +@WITH_CPU_PROFILER_TRUE@ src/profile-handler.cc \ +@WITH_CPU_PROFILER_TRUE@ src/profiledata.cc \ +@WITH_CPU_PROFILER_TRUE@ $(CPU_PROFILER_INCLUDES) + +@WITH_CPU_PROFILER_TRUE@libprofiler_la_LIBADD = libstacktrace.la libmaybe_threads.la libfake_stacktrace_scope.la +# We have to include ProfileData for profiledata_unittest +@WITH_CPU_PROFILER_TRUE@CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler|ProfilerGetStackTrace)' +@WITH_CPU_PROFILER_TRUE@libprofiler_la_LDFLAGS = -export-symbols-regex $(CPU_PROFILER_SYMBOLS) \ +@WITH_CPU_PROFILER_TRUE@ -version-info @PROFILER_SO_VERSION@ + + +# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this. +# Basically it's to work around systems where --rpath doesn't work right. +@WITH_CPU_PROFILER_TRUE@LIBPROFILER = libstacktrace.la libprofiler.la +#WINDOWS_PROJECTS += vsprojects/getpc_test/getpc_test.vcxproj +@WITH_CPU_PROFILER_TRUE@getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h +#WINDOWS_PROJECTS += vsprojects/profiledata_unittest/profiledata_unittest.vcxproj +@WITH_CPU_PROFILER_TRUE@profiledata_unittest_SOURCES = src/tests/profiledata_unittest.cc \ +@WITH_CPU_PROFILER_TRUE@ src/profiledata.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/commandlineflags.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/logging.h \ +@WITH_CPU_PROFILER_TRUE@ src/base/basictypes.h + +@WITH_CPU_PROFILER_TRUE@profiledata_unittest_LDADD = $(LIBPROFILER) +@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_SOURCES = src/tests/profile-handler_unittest.cc \ +@WITH_CPU_PROFILER_TRUE@ src/profile-handler.h + +@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) +@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS) +@WITH_CPU_PROFILER_TRUE@profiler_unittest_sh_SOURCES = src/tests/profiler_unittest.sh +@WITH_CPU_PROFILER_TRUE@PROFILER_UNITTEST_INCLUDES = src/config_for_unittests.h \ +@WITH_CPU_PROFILER_TRUE@ src/gperftools/profiler.h + +@WITH_CPU_PROFILER_TRUE@PROFILER_UNITTEST_SRCS = src/tests/profiler_unittest.cc \ +@WITH_CPU_PROFILER_TRUE@ src/tests/testutil.h src/tests/testutil.cc \ +@WITH_CPU_PROFILER_TRUE@ $(PROFILER_UNITTEST_INCLUDES) + +@WITH_CPU_PROFILER_TRUE@profiler1_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +@WITH_CPU_PROFILER_TRUE@profiler1_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler1_unittest_LDADD = $(LIBPROFILER) +@WITH_CPU_PROFILER_TRUE@profiler2_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +@WITH_CPU_PROFILER_TRUE@profiler2_unittest_CXXFLAGS = -g -DNO_THREADS $(AM_CXXFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler2_unittest_LDADD = -lstacktrace -lprofiler +# We depend on -lprofiler but haven't yet said how to build it. Do so now. +@WITH_CPU_PROFILER_TRUE@profiler2_unittest_DEPENDENCIES = $(LIBPROFILER) +@WITH_CPU_PROFILER_TRUE@profiler3_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +@WITH_CPU_PROFILER_TRUE@profiler3_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler3_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler3_unittest_LDADD = $(LIBPROFILER) $(PTHREAD_LIBS) +@WITH_CPU_PROFILER_TRUE@profiler4_unittest_SOURCES = $(PROFILER_UNITTEST_SRCS) +@WITH_CPU_PROFILER_TRUE@profiler4_unittest_CXXFLAGS = -g $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler4_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +@WITH_CPU_PROFILER_TRUE@profiler4_unittest_LDADD = -lstacktrace -lprofiler $(PTHREAD_LIBS) +# We depend on -lprofiler but haven't yet said how to build it. Do so now. +@WITH_CPU_PROFILER_TRUE@profiler4_unittest_DEPENDENCIES = $(LIBPROFILER) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_SOURCES = $(libtcmalloc_la_SOURCES) $(libprofiler_la_SOURCES) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) $(libprofiler_la_CXXFLAGS) +# Since this library is meant to be used as a .a, I don't worry as much +# about .so versioning. I just give the libtcmalloc version number. +# TODO(csilvers): use -export-symbols-regex? +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_LDFLAGS = $(PTHREAD_CFLAGS) \ +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -version-info @TCMALLOC_AND_PROFILER_SO_VERSION@ + +# We don't include libprofiler_la_LIBADD here because all it adds is +# libstacktrace.la, which we already get via libtcmalloc. Trying to +# specify it twice causes link-time duplicate-definition errors. :-( +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_and_profiler_la_LIBADD = $(libtcmalloc_la_LIBADD) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_SOURCES = $(tcmalloc_both_unittest_srcs) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_CXXFLAGS = $(tcmalloc_both_unittest_cflags) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDFLAGS = $(tcmalloc_both_unittest_lflags) +@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_LDADD = libtcmalloc_and_profiler.la + +# http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libtcmalloc.pc libtcmalloc_minimal.pc \ + libtcmalloc_debug.pc libtcmalloc_minimal_debug.pc \ + libprofiler.pc + +CLEANFILES = $(pkgconfig_DATA) +EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \ + $(SCRIPTS) libtool \ + src/windows/get_mangled_names.cc src/windows/override_functions.cc \ + src/windows/config.h src/windows/gperftools/tcmalloc.h \ + docs/pprof.see_also src/windows/TODO \ + $(WINDOWS_PROJECTS) \ + src/solaris/libstdc++.la + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .lo .log .o .obj .test .test$(EXEEXT) .trs +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +src/config.h: src/stamp-h1 + @test -f $@ || rm -f src/stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1 + +src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status + @rm -f src/stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status src/config.h +$(top_srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f src/stamp-h1 + touch $@ + +distclean-hdr: + -rm -f src/config.h src/stamp-h1 +src/gperftools/tcmalloc.h: $(top_builddir)/config.status $(top_srcdir)/src/gperftools/tcmalloc.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +src/windows/gperftools/tcmalloc.h: $(top_builddir)/config.status $(top_srcdir)/src/windows/gperftools/tcmalloc.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/fake_stacktrace_scope.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libfake_stacktrace_scope.la: $(libfake_stacktrace_scope_la_OBJECTS) $(libfake_stacktrace_scope_la_DEPENDENCIES) $(EXTRA_libfake_stacktrace_scope_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(am_libfake_stacktrace_scope_la_rpath) $(libfake_stacktrace_scope_la_OBJECTS) $(libfake_stacktrace_scope_la_LIBADD) $(LIBS) +src/base/$(am__dirstamp): + @$(MKDIR_P) src/base + @: > src/base/$(am__dirstamp) +src/base/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/base/$(DEPDIR) + @: > src/base/$(DEPDIR)/$(am__dirstamp) +src/base/logging.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/base/dynamic_annotations.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) + +liblogging.la: $(liblogging_la_OBJECTS) $(liblogging_la_DEPENDENCIES) $(EXTRA_liblogging_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(liblogging_la_OBJECTS) $(liblogging_la_LIBADD) $(LIBS) +src/maybe_threads.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libmaybe_threads.la: $(libmaybe_threads_la_OBJECTS) $(libmaybe_threads_la_DEPENDENCIES) $(EXTRA_libmaybe_threads_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libmaybe_threads_la_OBJECTS) $(libmaybe_threads_la_LIBADD) $(LIBS) +src/profiler.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/profile-handler.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/profiledata.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +libprofiler.la: $(libprofiler_la_OBJECTS) $(libprofiler_la_DEPENDENCIES) $(EXTRA_libprofiler_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libprofiler_la_LINK) $(am_libprofiler_la_rpath) $(libprofiler_la_OBJECTS) $(libprofiler_la_LIBADD) $(LIBS) +benchmark/$(am__dirstamp): + @$(MKDIR_P) benchmark + @: > benchmark/$(am__dirstamp) +benchmark/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) benchmark/$(DEPDIR) + @: > benchmark/$(DEPDIR)/$(am__dirstamp) +benchmark/run_benchmark.lo: benchmark/$(am__dirstamp) \ + benchmark/$(DEPDIR)/$(am__dirstamp) + +librun_benchmark.la: $(librun_benchmark_la_OBJECTS) $(librun_benchmark_la_DEPENDENCIES) $(EXTRA_librun_benchmark_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(am_librun_benchmark_la_rpath) $(librun_benchmark_la_OBJECTS) $(librun_benchmark_la_LIBADD) $(LIBS) +src/base/spinlock.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/base/spinlock_internal.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/base/atomicops-internals-x86.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) + +libspinlock.la: $(libspinlock_la_OBJECTS) $(libspinlock_la_DEPENDENCIES) $(EXTRA_libspinlock_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(am_libspinlock_la_rpath) $(libspinlock_la_OBJECTS) $(libspinlock_la_LIBADD) $(LIBS) +src/stacktrace.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/base/elf_mem_image.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/base/vdso_support.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) + +libstacktrace.la: $(libstacktrace_la_OBJECTS) $(libstacktrace_la_DEPENDENCIES) $(EXTRA_libstacktrace_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libstacktrace_la_LINK) $(am_libstacktrace_la_rpath) $(libstacktrace_la_OBJECTS) $(libstacktrace_la_LIBADD) $(LIBS) +src/base/sysinfo.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) + +libsysinfo.la: $(libsysinfo_la_OBJECTS) $(libsysinfo_la_DEPENDENCIES) $(EXTRA_libsysinfo_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libsysinfo_la_OBJECTS) $(libsysinfo_la_LIBADD) $(LIBS) +src/libtcmalloc_la-tcmalloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/base/thread_lister.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_la-linuxthreads.lo: src/base/$(am__dirstamp) \ + src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_la-heap-checker.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_la-heap-checker-bcad.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc.la: $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_DEPENDENCIES) $(EXTRA_libtcmalloc_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_la_LINK) $(am_libtcmalloc_la_rpath) $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_LIBADD) $(LIBS) +src/libtcmalloc_and_profiler_la-tcmalloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_and_profiler_la-linuxthreads.lo: \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_and_profiler_la-heap-checker.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_and_profiler_la-profiler.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_and_profiler_la-profile-handler.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_and_profiler_la-profiledata.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_and_profiler.la: $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_DEPENDENCIES) $(EXTRA_libtcmalloc_and_profiler_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_and_profiler_la_LINK) $(am_libtcmalloc_and_profiler_la_rpath) $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_LIBADD) $(LIBS) +src/libtcmalloc_debug_la-debugallocation.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_debug_la-linuxthreads.lo: \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_debug_la-heap-checker.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_debug_la-heap-checker-bcad.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_debug.la: $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_DEPENDENCIES) $(EXTRA_libtcmalloc_debug_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_debug_la_LINK) $(am_libtcmalloc_debug_la_rpath) $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_LIBADD) $(LIBS) +src/libtcmalloc_internal_la-common.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-internal_logging.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-system-alloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-memfs_malloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-central_freelist.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-page_heap.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-sampler.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-span.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-stack_trace_table.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-static_vars.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-symbolize.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-thread_cache.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-malloc_hook.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-malloc_extension.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_internal_la-low_level_alloc.lo: \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-heap-profile-table.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-heap-profiler.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-raw_printer.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-fake_stacktrace_scope.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-emergency_malloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_la-memory_region_map.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_internal.la: $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_DEPENDENCIES) $(EXTRA_libtcmalloc_internal_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_internal_la_LINK) $(am_libtcmalloc_internal_la_rpath) $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_LIBADD) $(LIBS) +src/libtcmalloc_internal_with_asserts_la-common.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-internal_logging.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-system-alloc.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-central_freelist.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-page_heap.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-sampler.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-span.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-static_vars.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-symbolize.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-thread_cache.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo: \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-raw_printer.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_internal_with_asserts.la: $(libtcmalloc_internal_with_asserts_la_OBJECTS) $(libtcmalloc_internal_with_asserts_la_DEPENDENCIES) $(EXTRA_libtcmalloc_internal_with_asserts_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_internal_with_asserts_la_LINK) $(am_libtcmalloc_internal_with_asserts_la_rpath) $(libtcmalloc_internal_with_asserts_la_OBJECTS) $(libtcmalloc_internal_with_asserts_la_LIBADD) $(LIBS) +src/libtcmalloc_minimal_la-tcmalloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_minimal.la: $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_DEPENDENCIES) $(EXTRA_libtcmalloc_minimal_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_minimal_la_LINK) -rpath $(libdir) $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_LIBADD) $(LIBS) +src/libtcmalloc_minimal_debug_la-debugallocation.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_minimal_debug.la: $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_DEPENDENCIES) $(EXTRA_libtcmalloc_minimal_debug_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_minimal_debug_la_LINK) $(am_libtcmalloc_minimal_debug_la_rpath) $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_LIBADD) $(LIBS) +src/libtcmalloc_minimal_internal_la-common.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-internal_logging.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-system-alloc.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-memfs_malloc.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-central_freelist.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-page_heap.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-sampler.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-span.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-stack_trace_table.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-static_vars.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-symbolize.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-thread_cache.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-malloc_hook.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_minimal_internal_la-malloc_extension.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_minimal_internal.la: $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_DEPENDENCIES) $(EXTRA_libtcmalloc_minimal_internal_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_minimal_internal_la_LINK) $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_LIBADD) $(LIBS) +src/libtcmalloc_with_asserts_la-tcmalloc.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/base/libtcmalloc_with_asserts_la-linuxthreads.lo: \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_with_asserts_la-heap-checker.lo: src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo: \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) + +libtcmalloc_with_asserts.la: $(libtcmalloc_with_asserts_la_OBJECTS) $(libtcmalloc_with_asserts_la_DEPENDENCIES) $(EXTRA_libtcmalloc_with_asserts_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtcmalloc_with_asserts_la_LINK) $(am_libtcmalloc_with_asserts_la_rpath) $(libtcmalloc_with_asserts_la_OBJECTS) $(libtcmalloc_with_asserts_la_LIBADD) $(LIBS) +src/windows/$(am__dirstamp): + @$(MKDIR_P) src/windows + @: > src/windows/$(am__dirstamp) +src/windows/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/windows/$(DEPDIR) + @: > src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/port.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/system-alloc.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/ia32_modrm_map.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/ia32_opcode_map.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/mini_disassembler.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/patch_functions.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/preamble_patcher.lo: src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) +src/windows/preamble_patcher_with_stub.lo: \ + src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) + +libwindows.la: $(libwindows_la_OBJECTS) $(libwindows_la_DEPENDENCIES) $(EXTRA_libwindows_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(am_libwindows_la_rpath) $(libwindows_la_OBJECTS) $(libwindows_la_LIBADD) $(LIBS) +src/tests/$(am__dirstamp): + @$(MKDIR_P) src/tests + @: > src/tests/$(am__dirstamp) +src/tests/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/tests/$(DEPDIR) + @: > src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/addressmap_unittest-addressmap_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/windows/addressmap_unittest-port.$(OBJEXT): \ + src/windows/$(am__dirstamp) \ + src/windows/$(DEPDIR)/$(am__dirstamp) + +addressmap_unittest$(EXEEXT): $(addressmap_unittest_OBJECTS) $(addressmap_unittest_DEPENDENCIES) $(EXTRA_addressmap_unittest_DEPENDENCIES) + @rm -f addressmap_unittest$(EXEEXT) + $(AM_V_CXXLD)$(addressmap_unittest_LINK) $(addressmap_unittest_OBJECTS) $(addressmap_unittest_LDADD) $(LIBS) +src/tests/atomicops_unittest.$(OBJEXT): src/tests/$(am__dirstamp) \ + src/tests/$(DEPDIR)/$(am__dirstamp) + +atomicops_unittest$(EXEEXT): $(atomicops_unittest_OBJECTS) $(atomicops_unittest_DEPENDENCIES) $(EXTRA_atomicops_unittest_DEPENDENCIES) + @rm -f atomicops_unittest$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(atomicops_unittest_OBJECTS) $(atomicops_unittest_LDADD) $(LIBS) +benchmark/binary_trees-binary_trees.$(OBJEXT): \ + benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp) + +binary_trees$(EXEEXT): $(binary_trees_OBJECTS) $(binary_trees_DEPENDENCIES) $(EXTRA_binary_trees_DEPENDENCIES) + @rm -f binary_trees$(EXEEXT) + $(AM_V_CXXLD)$(binary_trees_LINK) $(binary_trees_OBJECTS) $(binary_trees_LDADD) $(LIBS) +benchmark/binary_trees_shared-binary_trees.$(OBJEXT): \ + benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp) + +binary_trees_shared$(EXEEXT): $(binary_trees_shared_OBJECTS) $(binary_trees_shared_DEPENDENCIES) $(EXTRA_binary_trees_shared_DEPENDENCIES) + @rm -f binary_trees_shared$(EXEEXT) + $(AM_V_CXXLD)$(binary_trees_shared_LINK) $(binary_trees_shared_OBJECTS) $(binary_trees_shared_LDADD) $(LIBS) +src/tests/current_allocated_bytes_test-current_allocated_bytes_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +current_allocated_bytes_test$(EXEEXT): $(current_allocated_bytes_test_OBJECTS) $(current_allocated_bytes_test_DEPENDENCIES) $(EXTRA_current_allocated_bytes_test_DEPENDENCIES) + @rm -f current_allocated_bytes_test$(EXEEXT) + $(AM_V_CXXLD)$(current_allocated_bytes_test_LINK) $(current_allocated_bytes_test_OBJECTS) $(current_allocated_bytes_test_LDADD) $(LIBS) +src/tests/debugallocation_test-debugallocation_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +debugallocation_test$(EXEEXT): $(debugallocation_test_OBJECTS) $(debugallocation_test_DEPENDENCIES) $(EXTRA_debugallocation_test_DEPENDENCIES) + @rm -f debugallocation_test$(EXEEXT) + $(AM_V_CXXLD)$(debugallocation_test_LINK) $(debugallocation_test_OBJECTS) $(debugallocation_test_LDADD) $(LIBS) + +@WITH_DEBUGALLOC_FALSE@debugallocation_test.sh$(EXEEXT): $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_DEPENDENCIES) $(EXTRA_debugallocation_test_sh_DEPENDENCIES) +@WITH_DEBUGALLOC_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT) +@WITH_DEBUGALLOC_FALSE@ $(AM_V_CCLD)$(LINK) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS) + +@WITH_STACK_TRACE_FALSE@debugallocation_test.sh$(EXEEXT): $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_DEPENDENCIES) $(EXTRA_debugallocation_test_sh_DEPENDENCIES) +@WITH_STACK_TRACE_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT) +@WITH_STACK_TRACE_FALSE@ $(AM_V_CCLD)$(LINK) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS) +src/tests/frag_unittest-frag_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +frag_unittest$(EXEEXT): $(frag_unittest_OBJECTS) $(frag_unittest_DEPENDENCIES) $(EXTRA_frag_unittest_DEPENDENCIES) + @rm -f frag_unittest$(EXEEXT) + $(AM_V_CXXLD)$(frag_unittest_LINK) $(frag_unittest_OBJECTS) $(frag_unittest_LDADD) $(LIBS) +src/tests/getpc_test.$(OBJEXT): src/tests/$(am__dirstamp) \ + src/tests/$(DEPDIR)/$(am__dirstamp) + +getpc_test$(EXEEXT): $(getpc_test_OBJECTS) $(getpc_test_DEPENDENCIES) $(EXTRA_getpc_test_DEPENDENCIES) + @rm -f getpc_test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(getpc_test_OBJECTS) $(getpc_test_LDADD) $(LIBS) + +@WITH_HEAP_CHECKER_FALSE@heap-checker-death_unittest.sh$(EXEEXT): $(heap_checker_death_unittest_sh_OBJECTS) $(heap_checker_death_unittest_sh_DEPENDENCIES) $(EXTRA_heap_checker_death_unittest_sh_DEPENDENCIES) +@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker-death_unittest.sh$(EXEEXT) +@WITH_HEAP_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_checker_death_unittest_sh_OBJECTS) $(heap_checker_death_unittest_sh_LDADD) $(LIBS) +src/tests/heap_checker_debug_unittest-heap-checker_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +heap-checker_debug_unittest$(EXEEXT): $(heap_checker_debug_unittest_OBJECTS) $(heap_checker_debug_unittest_DEPENDENCIES) $(EXTRA_heap_checker_debug_unittest_DEPENDENCIES) + @rm -f heap-checker_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(heap_checker_debug_unittest_LINK) $(heap_checker_debug_unittest_OBJECTS) $(heap_checker_debug_unittest_LDADD) $(LIBS) + +@WITH_DEBUGALLOC_FALSE@heap-checker_debug_unittest.sh$(EXEEXT): $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_DEPENDENCIES) $(EXTRA_heap_checker_debug_unittest_sh_DEPENDENCIES) +@WITH_DEBUGALLOC_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_LDADD) $(LIBS) + +@WITH_HEAP_CHECKER_FALSE@heap-checker_debug_unittest.sh$(EXEEXT): $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_DEPENDENCIES) $(EXTRA_heap_checker_debug_unittest_sh_DEPENDENCIES) +@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT) +@WITH_HEAP_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_LDADD) $(LIBS) +src/tests/heap_checker_unittest-heap-checker_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +heap-checker_unittest$(EXEEXT): $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_DEPENDENCIES) $(EXTRA_heap_checker_unittest_DEPENDENCIES) + @rm -f heap-checker_unittest$(EXEEXT) + $(AM_V_CXXLD)$(heap_checker_unittest_LINK) $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_LDADD) $(LIBS) + +@WITH_HEAP_CHECKER_FALSE@heap-checker_unittest.sh$(EXEEXT): $(heap_checker_unittest_sh_OBJECTS) $(heap_checker_unittest_sh_DEPENDENCIES) $(EXTRA_heap_checker_unittest_sh_DEPENDENCIES) +@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_unittest.sh$(EXEEXT) +@WITH_HEAP_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_checker_unittest_sh_OBJECTS) $(heap_checker_unittest_sh_LDADD) $(LIBS) +src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +heap-profiler_debug_unittest$(EXEEXT): $(heap_profiler_debug_unittest_OBJECTS) $(heap_profiler_debug_unittest_DEPENDENCIES) $(EXTRA_heap_profiler_debug_unittest_DEPENDENCIES) + @rm -f heap-profiler_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(heap_profiler_debug_unittest_LINK) $(heap_profiler_debug_unittest_OBJECTS) $(heap_profiler_debug_unittest_LDADD) $(LIBS) + +@WITH_DEBUGALLOC_FALSE@heap-profiler_debug_unittest.sh$(EXEEXT): $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_DEPENDENCIES) $(EXTRA_heap_profiler_debug_unittest_sh_DEPENDENCIES) +@WITH_DEBUGALLOC_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT) +@WITH_DEBUGALLOC_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_LDADD) $(LIBS) + +@WITH_HEAP_PROFILER_FALSE@heap-profiler_debug_unittest.sh$(EXEEXT): $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_DEPENDENCIES) $(EXTRA_heap_profiler_debug_unittest_sh_DEPENDENCIES) +@WITH_HEAP_PROFILER_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT) +@WITH_HEAP_PROFILER_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_LDADD) $(LIBS) +src/tests/heap_profiler_unittest-heap-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +heap-profiler_unittest$(EXEEXT): $(heap_profiler_unittest_OBJECTS) $(heap_profiler_unittest_DEPENDENCIES) $(EXTRA_heap_profiler_unittest_DEPENDENCIES) + @rm -f heap-profiler_unittest$(EXEEXT) + $(AM_V_CXXLD)$(heap_profiler_unittest_LINK) $(heap_profiler_unittest_OBJECTS) $(heap_profiler_unittest_LDADD) $(LIBS) + +@WITH_HEAP_PROFILER_FALSE@heap-profiler_unittest.sh$(EXEEXT): $(heap_profiler_unittest_sh_OBJECTS) $(heap_profiler_unittest_sh_DEPENDENCIES) $(EXTRA_heap_profiler_unittest_sh_DEPENDENCIES) +@WITH_HEAP_PROFILER_FALSE@ @rm -f heap-profiler_unittest.sh$(EXEEXT) +@WITH_HEAP_PROFILER_FALSE@ $(AM_V_CCLD)$(LINK) $(heap_profiler_unittest_sh_OBJECTS) $(heap_profiler_unittest_sh_LDADD) $(LIBS) +src/base/low_level_alloc_unittest-low_level_alloc.$(OBJEXT): \ + src/base/$(am__dirstamp) src/base/$(DEPDIR)/$(am__dirstamp) +src/low_level_alloc_unittest-malloc_hook.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tests/low_level_alloc_unittest-low_level_alloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +low_level_alloc_unittest$(EXEEXT): $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_DEPENDENCIES) $(EXTRA_low_level_alloc_unittest_DEPENDENCIES) + @rm -f low_level_alloc_unittest$(EXEEXT) + $(AM_V_CXXLD)$(low_level_alloc_unittest_LINK) $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_LDADD) $(LIBS) +benchmark/malloc_bench-malloc_bench.$(OBJEXT): \ + benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp) + +malloc_bench$(EXEEXT): $(malloc_bench_OBJECTS) $(malloc_bench_DEPENDENCIES) $(EXTRA_malloc_bench_DEPENDENCIES) + @rm -f malloc_bench$(EXEEXT) + $(AM_V_CXXLD)$(malloc_bench_LINK) $(malloc_bench_OBJECTS) $(malloc_bench_LDADD) $(LIBS) +benchmark/malloc_bench_shared-malloc_bench.$(OBJEXT): \ + benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp) + +malloc_bench_shared$(EXEEXT): $(malloc_bench_shared_OBJECTS) $(malloc_bench_shared_DEPENDENCIES) $(EXTRA_malloc_bench_shared_DEPENDENCIES) + @rm -f malloc_bench_shared$(EXEEXT) + $(AM_V_CXXLD)$(malloc_bench_shared_LINK) $(malloc_bench_shared_OBJECTS) $(malloc_bench_shared_LDADD) $(LIBS) +benchmark/malloc_bench_shared_full-malloc_bench.$(OBJEXT): \ + benchmark/$(am__dirstamp) benchmark/$(DEPDIR)/$(am__dirstamp) + +malloc_bench_shared_full$(EXEEXT): $(malloc_bench_shared_full_OBJECTS) $(malloc_bench_shared_full_DEPENDENCIES) $(EXTRA_malloc_bench_shared_full_DEPENDENCIES) + @rm -f malloc_bench_shared_full$(EXEEXT) + $(AM_V_CXXLD)$(malloc_bench_shared_full_LINK) $(malloc_bench_shared_full_OBJECTS) $(malloc_bench_shared_full_LDADD) $(LIBS) +src/tests/malloc_extension_c_test-malloc_extension_c_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +malloc_extension_c_test$(EXEEXT): $(malloc_extension_c_test_OBJECTS) $(malloc_extension_c_test_DEPENDENCIES) $(EXTRA_malloc_extension_c_test_DEPENDENCIES) + @rm -f malloc_extension_c_test$(EXEEXT) + $(AM_V_CCLD)$(malloc_extension_c_test_LINK) $(malloc_extension_c_test_OBJECTS) $(malloc_extension_c_test_LDADD) $(LIBS) +src/tests/malloc_extension_debug_test-malloc_extension_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +malloc_extension_debug_test$(EXEEXT): $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_DEPENDENCIES) $(EXTRA_malloc_extension_debug_test_DEPENDENCIES) + @rm -f malloc_extension_debug_test$(EXEEXT) + $(AM_V_CXXLD)$(malloc_extension_debug_test_LINK) $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_LDADD) $(LIBS) +src/tests/malloc_extension_test-malloc_extension_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +malloc_extension_test$(EXEEXT): $(malloc_extension_test_OBJECTS) $(malloc_extension_test_DEPENDENCIES) $(EXTRA_malloc_extension_test_DEPENDENCIES) + @rm -f malloc_extension_test$(EXEEXT) + $(AM_V_CXXLD)$(malloc_extension_test_LINK) $(malloc_extension_test_OBJECTS) $(malloc_extension_test_LDADD) $(LIBS) +src/tests/malloc_hook_test-malloc_hook_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/malloc_hook_test-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +malloc_hook_test$(EXEEXT): $(malloc_hook_test_OBJECTS) $(malloc_hook_test_DEPENDENCIES) $(EXTRA_malloc_hook_test_DEPENDENCIES) + @rm -f malloc_hook_test$(EXEEXT) + $(AM_V_CXXLD)$(malloc_hook_test_LINK) $(malloc_hook_test_OBJECTS) $(malloc_hook_test_LDADD) $(LIBS) +src/tests/markidle_unittest-markidle_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/markidle_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +markidle_unittest$(EXEEXT): $(markidle_unittest_OBJECTS) $(markidle_unittest_DEPENDENCIES) $(EXTRA_markidle_unittest_DEPENDENCIES) + @rm -f markidle_unittest$(EXEEXT) + $(AM_V_CXXLD)$(markidle_unittest_LINK) $(markidle_unittest_OBJECTS) $(markidle_unittest_LDADD) $(LIBS) + +@ENABLE_STATIC_TRUE@maybe_threads_unittest.sh$(EXEEXT): $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_DEPENDENCIES) $(EXTRA_maybe_threads_unittest_sh_DEPENDENCIES) +@ENABLE_STATIC_TRUE@ @rm -f maybe_threads_unittest.sh$(EXEEXT) +@ENABLE_STATIC_TRUE@ $(AM_V_CCLD)$(LINK) $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_LDADD) $(LIBS) + +@MINGW_TRUE@maybe_threads_unittest.sh$(EXEEXT): $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_DEPENDENCIES) $(EXTRA_maybe_threads_unittest_sh_DEPENDENCIES) +@MINGW_TRUE@ @rm -f maybe_threads_unittest.sh$(EXEEXT) +@MINGW_TRUE@ $(AM_V_CCLD)$(LINK) $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_LDADD) $(LIBS) +src/tests/memalign_debug_unittest-memalign_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/memalign_debug_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +memalign_debug_unittest$(EXEEXT): $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_DEPENDENCIES) $(EXTRA_memalign_debug_unittest_DEPENDENCIES) + @rm -f memalign_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(memalign_debug_unittest_LINK) $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_LDADD) $(LIBS) +src/tests/memalign_unittest-memalign_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/memalign_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +memalign_unittest$(EXEEXT): $(memalign_unittest_OBJECTS) $(memalign_unittest_DEPENDENCIES) $(EXTRA_memalign_unittest_DEPENDENCIES) + @rm -f memalign_unittest$(EXEEXT) + $(AM_V_CXXLD)$(memalign_unittest_LINK) $(memalign_unittest_OBJECTS) $(memalign_unittest_LDADD) $(LIBS) +src/tests/packed_cache_test-packed-cache_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +packed_cache_test$(EXEEXT): $(packed_cache_test_OBJECTS) $(packed_cache_test_DEPENDENCIES) $(EXTRA_packed_cache_test_DEPENDENCIES) + @rm -f packed_cache_test$(EXEEXT) + $(AM_V_CXXLD)$(packed_cache_test_LINK) $(packed_cache_test_OBJECTS) $(packed_cache_test_LDADD) $(LIBS) +src/tests/page_heap_test-page_heap_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +page_heap_test$(EXEEXT): $(page_heap_test_OBJECTS) $(page_heap_test_DEPENDENCIES) $(EXTRA_page_heap_test_DEPENDENCIES) + @rm -f page_heap_test$(EXEEXT) + $(AM_V_CXXLD)$(page_heap_test_LINK) $(page_heap_test_OBJECTS) $(page_heap_test_LDADD) $(LIBS) +src/tests/pagemap_unittest-pagemap_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +pagemap_unittest$(EXEEXT): $(pagemap_unittest_OBJECTS) $(pagemap_unittest_DEPENDENCIES) $(EXTRA_pagemap_unittest_DEPENDENCIES) + @rm -f pagemap_unittest$(EXEEXT) + $(AM_V_CXXLD)$(pagemap_unittest_LINK) $(pagemap_unittest_OBJECTS) $(pagemap_unittest_LDADD) $(LIBS) +src/tests/profile_handler_unittest-profile-handler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +profile_handler_unittest$(EXEEXT): $(profile_handler_unittest_OBJECTS) $(profile_handler_unittest_DEPENDENCIES) $(EXTRA_profile_handler_unittest_DEPENDENCIES) + @rm -f profile_handler_unittest$(EXEEXT) + $(AM_V_CXXLD)$(profile_handler_unittest_LINK) $(profile_handler_unittest_OBJECTS) $(profile_handler_unittest_LDADD) $(LIBS) +src/tests/profiledata_unittest.$(OBJEXT): src/tests/$(am__dirstamp) \ + src/tests/$(DEPDIR)/$(am__dirstamp) + +profiledata_unittest$(EXEEXT): $(profiledata_unittest_OBJECTS) $(profiledata_unittest_DEPENDENCIES) $(EXTRA_profiledata_unittest_DEPENDENCIES) + @rm -f profiledata_unittest$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(profiledata_unittest_OBJECTS) $(profiledata_unittest_LDADD) $(LIBS) +src/tests/profiler1_unittest-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/profiler1_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +profiler1_unittest$(EXEEXT): $(profiler1_unittest_OBJECTS) $(profiler1_unittest_DEPENDENCIES) $(EXTRA_profiler1_unittest_DEPENDENCIES) + @rm -f profiler1_unittest$(EXEEXT) + $(AM_V_CXXLD)$(profiler1_unittest_LINK) $(profiler1_unittest_OBJECTS) $(profiler1_unittest_LDADD) $(LIBS) +src/tests/profiler2_unittest-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/profiler2_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +profiler2_unittest$(EXEEXT): $(profiler2_unittest_OBJECTS) $(profiler2_unittest_DEPENDENCIES) $(EXTRA_profiler2_unittest_DEPENDENCIES) + @rm -f profiler2_unittest$(EXEEXT) + $(AM_V_CXXLD)$(profiler2_unittest_LINK) $(profiler2_unittest_OBJECTS) $(profiler2_unittest_LDADD) $(LIBS) +src/tests/profiler3_unittest-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/profiler3_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +profiler3_unittest$(EXEEXT): $(profiler3_unittest_OBJECTS) $(profiler3_unittest_DEPENDENCIES) $(EXTRA_profiler3_unittest_DEPENDENCIES) + @rm -f profiler3_unittest$(EXEEXT) + $(AM_V_CXXLD)$(profiler3_unittest_LINK) $(profiler3_unittest_OBJECTS) $(profiler3_unittest_LDADD) $(LIBS) +src/tests/profiler4_unittest-profiler_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/profiler4_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +profiler4_unittest$(EXEEXT): $(profiler4_unittest_OBJECTS) $(profiler4_unittest_DEPENDENCIES) $(EXTRA_profiler4_unittest_DEPENDENCIES) + @rm -f profiler4_unittest$(EXEEXT) + $(AM_V_CXXLD)$(profiler4_unittest_LINK) $(profiler4_unittest_OBJECTS) $(profiler4_unittest_LDADD) $(LIBS) + +@WITH_CPU_PROFILER_FALSE@profiler_unittest.sh$(EXEEXT): $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_DEPENDENCIES) $(EXTRA_profiler_unittest_sh_DEPENDENCIES) +@WITH_CPU_PROFILER_FALSE@ @rm -f profiler_unittest.sh$(EXEEXT) +@WITH_CPU_PROFILER_FALSE@ $(AM_V_CCLD)$(LINK) $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_LDADD) $(LIBS) +src/tests/raw_printer_test-raw_printer_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +raw_printer_test$(EXEEXT): $(raw_printer_test_OBJECTS) $(raw_printer_test_DEPENDENCIES) $(EXTRA_raw_printer_test_DEPENDENCIES) + @rm -f raw_printer_test$(EXEEXT) + $(AM_V_CXXLD)$(raw_printer_test_LINK) $(raw_printer_test_OBJECTS) $(raw_printer_test_LDADD) $(LIBS) +src/tests/realloc_debug_unittest-realloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +realloc_debug_unittest$(EXEEXT): $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_DEPENDENCIES) $(EXTRA_realloc_debug_unittest_DEPENDENCIES) + @rm -f realloc_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(realloc_debug_unittest_LINK) $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_LDADD) $(LIBS) +src/tests/realloc_unittest-realloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +realloc_unittest$(EXEEXT): $(realloc_unittest_OBJECTS) $(realloc_unittest_DEPENDENCIES) $(EXTRA_realloc_unittest_DEPENDENCIES) + @rm -f realloc_unittest$(EXEEXT) + $(AM_V_CXXLD)$(realloc_unittest_LINK) $(realloc_unittest_OBJECTS) $(realloc_unittest_LDADD) $(LIBS) +src/tests/sampler_debug_test-sampler_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +sampler_debug_test$(EXEEXT): $(sampler_debug_test_OBJECTS) $(sampler_debug_test_DEPENDENCIES) $(EXTRA_sampler_debug_test_DEPENDENCIES) + @rm -f sampler_debug_test$(EXEEXT) + $(AM_V_CXXLD)$(sampler_debug_test_LINK) $(sampler_debug_test_OBJECTS) $(sampler_debug_test_LDADD) $(LIBS) +src/tests/sampler_test-sampler_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +sampler_test$(EXEEXT): $(sampler_test_OBJECTS) $(sampler_test_DEPENDENCIES) $(EXTRA_sampler_test_DEPENDENCIES) + @rm -f sampler_test$(EXEEXT) + $(AM_V_CXXLD)$(sampler_test_LINK) $(sampler_test_OBJECTS) $(sampler_test_LDADD) $(LIBS) +src/tests/sampling_debug_test-sampling_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +sampling_debug_test$(EXEEXT): $(sampling_debug_test_OBJECTS) $(sampling_debug_test_DEPENDENCIES) $(EXTRA_sampling_debug_test_DEPENDENCIES) + @rm -f sampling_debug_test$(EXEEXT) + $(AM_V_CXXLD)$(sampling_debug_test_LINK) $(sampling_debug_test_OBJECTS) $(sampling_debug_test_LDADD) $(LIBS) + +@WITH_DEBUGALLOC_FALSE@sampling_debug_test.sh$(EXEEXT): $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_DEPENDENCIES) $(EXTRA_sampling_debug_test_sh_DEPENDENCIES) +@WITH_DEBUGALLOC_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT) +@WITH_DEBUGALLOC_FALSE@ $(AM_V_CCLD)$(LINK) $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_LDADD) $(LIBS) + +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@sampling_debug_test.sh$(EXEEXT): $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_DEPENDENCIES) $(EXTRA_sampling_debug_test_sh_DEPENDENCIES) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_LDADD) $(LIBS) +src/tests/sampling_test-sampling_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +sampling_test$(EXEEXT): $(sampling_test_OBJECTS) $(sampling_test_DEPENDENCIES) $(EXTRA_sampling_test_DEPENDENCIES) + @rm -f sampling_test$(EXEEXT) + $(AM_V_CXXLD)$(sampling_test_LINK) $(sampling_test_OBJECTS) $(sampling_test_LDADD) $(LIBS) + +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@sampling_test.sh$(EXEEXT): $(sampling_test_sh_OBJECTS) $(sampling_test_sh_DEPENDENCIES) $(EXTRA_sampling_test_sh_DEPENDENCIES) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f sampling_test.sh$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(sampling_test_sh_OBJECTS) $(sampling_test_sh_LDADD) $(LIBS) +src/tests/simple_compat_test.$(OBJEXT): src/tests/$(am__dirstamp) \ + src/tests/$(DEPDIR)/$(am__dirstamp) + +simple_compat_test$(EXEEXT): $(simple_compat_test_OBJECTS) $(simple_compat_test_DEPENDENCIES) $(EXTRA_simple_compat_test_DEPENDENCIES) + @rm -f simple_compat_test$(EXEEXT) + $(AM_V_CXXLD)$(simple_compat_test_LINK) $(simple_compat_test_OBJECTS) $(simple_compat_test_LDADD) $(LIBS) +src/tests/stack_trace_table_test-stack_trace_table_test.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +stack_trace_table_test$(EXEEXT): $(stack_trace_table_test_OBJECTS) $(stack_trace_table_test_DEPENDENCIES) $(EXTRA_stack_trace_table_test_DEPENDENCIES) + @rm -f stack_trace_table_test$(EXEEXT) + $(AM_V_CXXLD)$(stack_trace_table_test_LINK) $(stack_trace_table_test_OBJECTS) $(stack_trace_table_test_LDADD) $(LIBS) +src/tests/stacktrace_unittest.$(OBJEXT): src/tests/$(am__dirstamp) \ + src/tests/$(DEPDIR)/$(am__dirstamp) + +stacktrace_unittest$(EXEEXT): $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_DEPENDENCIES) $(EXTRA_stacktrace_unittest_DEPENDENCIES) + @rm -f stacktrace_unittest$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_LDADD) $(LIBS) +src/tests/system_alloc_unittest-system-alloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +system_alloc_unittest$(EXEEXT): $(system_alloc_unittest_OBJECTS) $(system_alloc_unittest_DEPENDENCIES) $(EXTRA_system_alloc_unittest_DEPENDENCIES) + @rm -f system_alloc_unittest$(EXEEXT) + $(AM_V_CXXLD)$(system_alloc_unittest_LINK) $(system_alloc_unittest_OBJECTS) $(system_alloc_unittest_LDADD) $(LIBS) +src/tests/tcm_asserts_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcm_asserts_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcm_asserts_unittest$(EXEEXT): $(tcm_asserts_unittest_OBJECTS) $(tcm_asserts_unittest_DEPENDENCIES) $(EXTRA_tcm_asserts_unittest_DEPENDENCIES) + @rm -f tcm_asserts_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcm_asserts_unittest_LINK) $(tcm_asserts_unittest_OBJECTS) $(tcm_asserts_unittest_LDADD) $(LIBS) +src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcm_min_asserts_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-common.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-internal_logging.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-system-alloc.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-memfs_malloc.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-central_freelist.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-page_heap.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-sampler.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-span.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-stack_trace_table.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-static_vars.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-symbolize.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-thread_cache.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-malloc_hook.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-malloc_extension.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/tcm_min_asserts_unittest-tcmalloc.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) + +tcm_min_asserts_unittest$(EXEEXT): $(tcm_min_asserts_unittest_OBJECTS) $(tcm_min_asserts_unittest_DEPENDENCIES) $(EXTRA_tcm_min_asserts_unittest_DEPENDENCIES) + @rm -f tcm_min_asserts_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcm_min_asserts_unittest_LINK) $(tcm_min_asserts_unittest_OBJECTS) $(tcm_min_asserts_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_and_profiler_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_and_profiler_unittest$(EXEEXT): $(tcmalloc_and_profiler_unittest_OBJECTS) $(tcmalloc_and_profiler_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_and_profiler_unittest_DEPENDENCIES) + @rm -f tcmalloc_and_profiler_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_and_profiler_unittest_LINK) $(tcmalloc_and_profiler_unittest_OBJECTS) $(tcmalloc_and_profiler_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_both_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_both_unittest$(EXEEXT): $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_both_unittest_DEPENDENCIES) + @rm -f tcmalloc_both_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_both_unittest_LINK) $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_debug_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_debug_unittest$(EXEEXT): $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_debug_unittest_DEPENDENCIES) + @rm -f tcmalloc_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_debug_unittest_LINK) $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_large_heap_fragmentation_unittest$(EXEEXT): $(tcmalloc_large_heap_fragmentation_unittest_OBJECTS) $(tcmalloc_large_heap_fragmentation_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_large_heap_fragmentation_unittest_DEPENDENCIES) + @rm -f tcmalloc_large_heap_fragmentation_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_large_heap_fragmentation_unittest_LINK) $(tcmalloc_large_heap_fragmentation_unittest_OBJECTS) $(tcmalloc_large_heap_fragmentation_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_large_unittest$(EXEEXT): $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_large_unittest_DEPENDENCIES) + @rm -f tcmalloc_large_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_large_unittest_LINK) $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_minimal_debug_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_minimal_debug_unittest$(EXEEXT): $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_minimal_debug_unittest_DEPENDENCIES) + @rm -f tcmalloc_minimal_debug_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_minimal_debug_unittest_LINK) $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT): $(tcmalloc_minimal_large_heap_fragmentation_unittest_OBJECTS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_minimal_large_heap_fragmentation_unittest_DEPENDENCIES) + @rm -f tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_minimal_large_heap_fragmentation_unittest_LINK) $(tcmalloc_minimal_large_heap_fragmentation_unittest_OBJECTS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_minimal_large_unittest$(EXEEXT): $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_minimal_large_unittest_DEPENDENCIES) + @rm -f tcmalloc_minimal_large_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_minimal_large_unittest_LINK) $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_minimal_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_minimal_unittest$(EXEEXT): $(tcmalloc_minimal_unittest_OBJECTS) $(tcmalloc_minimal_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_minimal_unittest_DEPENDENCIES) + @rm -f tcmalloc_minimal_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_minimal_unittest_LINK) $(tcmalloc_minimal_unittest_OBJECTS) $(tcmalloc_minimal_unittest_LDADD) $(LIBS) +src/tests/tcmalloc_unittest-tcmalloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/tcmalloc_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +tcmalloc_unittest$(EXEEXT): $(tcmalloc_unittest_OBJECTS) $(tcmalloc_unittest_DEPENDENCIES) $(EXTRA_tcmalloc_unittest_DEPENDENCIES) + @rm -f tcmalloc_unittest$(EXEEXT) + $(AM_V_CXXLD)$(tcmalloc_unittest_LINK) $(tcmalloc_unittest_OBJECTS) $(tcmalloc_unittest_LDADD) $(LIBS) + +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@tcmalloc_unittest.sh$(EXEEXT): $(tcmalloc_unittest_sh_OBJECTS) $(tcmalloc_unittest_sh_DEPENDENCIES) $(EXTRA_tcmalloc_unittest_sh_DEPENDENCIES) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f tcmalloc_unittest.sh$(EXEEXT) +@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(AM_V_CCLD)$(LINK) $(tcmalloc_unittest_sh_OBJECTS) $(tcmalloc_unittest_sh_LDADD) $(LIBS) +src/tests/thread_dealloc_unittest-thread_dealloc_unittest.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) +src/tests/thread_dealloc_unittest-testutil.$(OBJEXT): \ + src/tests/$(am__dirstamp) src/tests/$(DEPDIR)/$(am__dirstamp) + +thread_dealloc_unittest$(EXEEXT): $(thread_dealloc_unittest_OBJECTS) $(thread_dealloc_unittest_DEPENDENCIES) $(EXTRA_thread_dealloc_unittest_DEPENDENCIES) + @rm -f thread_dealloc_unittest$(EXEEXT) + $(AM_V_CXXLD)$(thread_dealloc_unittest_LINK) $(thread_dealloc_unittest_OBJECTS) $(thread_dealloc_unittest_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f benchmark/*.$(OBJEXT) + -rm -f benchmark/*.lo + -rm -f src/*.$(OBJEXT) + -rm -f src/*.lo + -rm -f src/base/*.$(OBJEXT) + -rm -f src/base/*.lo + -rm -f src/tests/*.$(OBJEXT) + -rm -f src/windows/*.$(OBJEXT) + -rm -f src/windows/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/binary_trees-binary_trees.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@benchmark/$(DEPDIR)/run_benchmark.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/fake_stacktrace_scope.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-span.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_la-heap-checker.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/maybe_threads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/profile-handler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/profiledata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/profiler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/stacktrace.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/atomicops-internals-x86.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/dynamic_annotations.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/elf_mem_image.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/spinlock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/spinlock_internal.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/sysinfo.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/thread_lister.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/base/$(DEPDIR)/vdso_support.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/atomicops_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/getpc_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/markidle_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/memalign_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiledata_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/sampler_test-sampler_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/sampling_test-sampling_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/simple_compat_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/stacktrace_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/addressmap_unittest-port.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/ia32_modrm_map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/ia32_opcode_map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/mini_disassembler.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/patch_functions.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/port.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/preamble_patcher.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/preamble_patcher_with_stub.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/windows/$(DEPDIR)/system-alloc.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +src/tests/malloc_extension_c_test-malloc_extension_c_test.o: src/tests/malloc_extension_c_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -MT src/tests/malloc_extension_c_test-malloc_extension_c_test.o -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo -c -o src/tests/malloc_extension_c_test-malloc_extension_c_test.o `test -f 'src/tests/malloc_extension_c_test.c' || echo '$(srcdir)/'`src/tests/malloc_extension_c_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tests/malloc_extension_c_test.c' object='src/tests/malloc_extension_c_test-malloc_extension_c_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -c -o src/tests/malloc_extension_c_test-malloc_extension_c_test.o `test -f 'src/tests/malloc_extension_c_test.c' || echo '$(srcdir)/'`src/tests/malloc_extension_c_test.c + +src/tests/malloc_extension_c_test-malloc_extension_c_test.obj: src/tests/malloc_extension_c_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -MT src/tests/malloc_extension_c_test-malloc_extension_c_test.obj -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo -c -o src/tests/malloc_extension_c_test-malloc_extension_c_test.obj `if test -f 'src/tests/malloc_extension_c_test.c'; then $(CYGPATH_W) 'src/tests/malloc_extension_c_test.c'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_c_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tests/malloc_extension_c_test.c' object='src/tests/malloc_extension_c_test-malloc_extension_c_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -c -o src/tests/malloc_extension_c_test-malloc_extension_c_test.obj `if test -f 'src/tests/malloc_extension_c_test.c'; then $(CYGPATH_W) 'src/tests/malloc_extension_c_test.c'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_c_test.c'; fi` + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +src/libtcmalloc_la-tcmalloc.lo: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_la-tcmalloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo -c -o src/libtcmalloc_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/libtcmalloc_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc + +src/base/libtcmalloc_la-linuxthreads.lo: src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_la-linuxthreads.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Tpo -c -o src/base/libtcmalloc_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Tpo src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/linuxthreads.cc' object='src/base/libtcmalloc_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc + +src/libtcmalloc_la-heap-checker.lo: src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_la-heap-checker.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_la-heap-checker.Tpo -c -o src/libtcmalloc_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_la-heap-checker.Tpo src/$(DEPDIR)/libtcmalloc_la-heap-checker.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker.cc' object='src/libtcmalloc_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc + +src/libtcmalloc_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_la-heap-checker-bcad.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Tpo -c -o src/libtcmalloc_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Tpo src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker-bcad.cc' object='src/libtcmalloc_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc + +src/libtcmalloc_and_profiler_la-tcmalloc.lo: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-tcmalloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Tpo -c -o src/libtcmalloc_and_profiler_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/libtcmalloc_and_profiler_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc + +src/base/libtcmalloc_and_profiler_la-linuxthreads.lo: src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_and_profiler_la-linuxthreads.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Tpo -c -o src/base/libtcmalloc_and_profiler_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Tpo src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/linuxthreads.cc' object='src/base/libtcmalloc_and_profiler_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_and_profiler_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc + +src/libtcmalloc_and_profiler_la-heap-checker.lo: src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-heap-checker.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Tpo -c -o src/libtcmalloc_and_profiler_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker.cc' object='src/libtcmalloc_and_profiler_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc + +src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Tpo -c -o src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker-bcad.cc' object='src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc + +src/libtcmalloc_and_profiler_la-profiler.lo: src/profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-profiler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Tpo -c -o src/libtcmalloc_and_profiler_la-profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/profiler.cc' object='src/libtcmalloc_and_profiler_la-profiler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc + +src/libtcmalloc_and_profiler_la-profile-handler.lo: src/profile-handler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-profile-handler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Tpo -c -o src/libtcmalloc_and_profiler_la-profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/profile-handler.cc' object='src/libtcmalloc_and_profiler_la-profile-handler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc + +src/libtcmalloc_and_profiler_la-profiledata.lo: src/profiledata.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_and_profiler_la-profiledata.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Tpo -c -o src/libtcmalloc_and_profiler_la-profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Tpo src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/profiledata.cc' object='src/libtcmalloc_and_profiler_la-profiledata.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_and_profiler_la-profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc + +src/libtcmalloc_debug_la-debugallocation.lo: src/debugallocation.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_debug_la-debugallocation.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo -c -o src/libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/debugallocation.cc' object='src/libtcmalloc_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc + +src/base/libtcmalloc_debug_la-linuxthreads.lo: src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_debug_la-linuxthreads.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo -c -o src/base/libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/linuxthreads.cc' object='src/base/libtcmalloc_debug_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc + +src/libtcmalloc_debug_la-heap-checker.lo: src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_debug_la-heap-checker.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo -c -o src/libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker.cc' object='src/libtcmalloc_debug_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc + +src/libtcmalloc_debug_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_debug_la-heap-checker-bcad.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo -c -o src/libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker-bcad.cc' object='src/libtcmalloc_debug_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc + +src/libtcmalloc_internal_la-common.lo: src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-common.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-common.Tpo -c -o src/libtcmalloc_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-common.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-common.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common.cc' object='src/libtcmalloc_internal_la-common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc + +src/libtcmalloc_internal_la-internal_logging.lo: src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-internal_logging.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Tpo -c -o src/libtcmalloc_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/internal_logging.cc' object='src/libtcmalloc_internal_la-internal_logging.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc + +src/libtcmalloc_internal_la-system-alloc.lo: src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-system-alloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Tpo -c -o src/libtcmalloc_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/system-alloc.cc' object='src/libtcmalloc_internal_la-system-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc + +src/libtcmalloc_internal_la-memfs_malloc.lo: src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-memfs_malloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Tpo -c -o src/libtcmalloc_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memfs_malloc.cc' object='src/libtcmalloc_internal_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc + +src/libtcmalloc_internal_la-central_freelist.lo: src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-central_freelist.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Tpo -c -o src/libtcmalloc_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/central_freelist.cc' object='src/libtcmalloc_internal_la-central_freelist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc + +src/libtcmalloc_internal_la-page_heap.lo: src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-page_heap.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Tpo -c -o src/libtcmalloc_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/page_heap.cc' object='src/libtcmalloc_internal_la-page_heap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc + +src/libtcmalloc_internal_la-sampler.lo: src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-sampler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Tpo -c -o src/libtcmalloc_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/sampler.cc' object='src/libtcmalloc_internal_la-sampler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc + +src/libtcmalloc_internal_la-span.lo: src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-span.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-span.Tpo -c -o src/libtcmalloc_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-span.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-span.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/span.cc' object='src/libtcmalloc_internal_la-span.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc + +src/libtcmalloc_internal_la-stack_trace_table.lo: src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-stack_trace_table.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Tpo -c -o src/libtcmalloc_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/stack_trace_table.cc' object='src/libtcmalloc_internal_la-stack_trace_table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc + +src/libtcmalloc_internal_la-static_vars.lo: src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-static_vars.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Tpo -c -o src/libtcmalloc_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/static_vars.cc' object='src/libtcmalloc_internal_la-static_vars.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc + +src/libtcmalloc_internal_la-symbolize.lo: src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-symbolize.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo -c -o src/libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/symbolize.cc' object='src/libtcmalloc_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc + +src/libtcmalloc_internal_la-thread_cache.lo: src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-thread_cache.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo -c -o src/libtcmalloc_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thread_cache.cc' object='src/libtcmalloc_internal_la-thread_cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc + +src/libtcmalloc_internal_la-malloc_hook.lo: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-malloc_hook.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Tpo -c -o src/libtcmalloc_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/libtcmalloc_internal_la-malloc_hook.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc + +src/libtcmalloc_internal_la-malloc_extension.lo: src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-malloc_extension.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Tpo -c -o src/libtcmalloc_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_extension.cc' object='src/libtcmalloc_internal_la-malloc_extension.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc + +src/base/libtcmalloc_internal_la-low_level_alloc.lo: src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_internal_la-low_level_alloc.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Tpo -c -o src/base/libtcmalloc_internal_la-low_level_alloc.lo `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Tpo src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/low_level_alloc.cc' object='src/base/libtcmalloc_internal_la-low_level_alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_internal_la-low_level_alloc.lo `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc + +src/libtcmalloc_internal_la-heap-profile-table.lo: src/heap-profile-table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-heap-profile-table.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Tpo -c -o src/libtcmalloc_internal_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-profile-table.cc' object='src/libtcmalloc_internal_la-heap-profile-table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc + +src/libtcmalloc_internal_la-heap-profiler.lo: src/heap-profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-heap-profiler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Tpo -c -o src/libtcmalloc_internal_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-profiler.cc' object='src/libtcmalloc_internal_la-heap-profiler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc + +src/libtcmalloc_internal_la-raw_printer.lo: src/raw_printer.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-raw_printer.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Tpo -c -o src/libtcmalloc_internal_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/raw_printer.cc' object='src/libtcmalloc_internal_la-raw_printer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc + +src/libtcmalloc_internal_la-fake_stacktrace_scope.lo: src/fake_stacktrace_scope.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-fake_stacktrace_scope.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Tpo -c -o src/libtcmalloc_internal_la-fake_stacktrace_scope.lo `test -f 'src/fake_stacktrace_scope.cc' || echo '$(srcdir)/'`src/fake_stacktrace_scope.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fake_stacktrace_scope.cc' object='src/libtcmalloc_internal_la-fake_stacktrace_scope.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-fake_stacktrace_scope.lo `test -f 'src/fake_stacktrace_scope.cc' || echo '$(srcdir)/'`src/fake_stacktrace_scope.cc + +src/libtcmalloc_internal_la-emergency_malloc.lo: src/emergency_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-emergency_malloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Tpo -c -o src/libtcmalloc_internal_la-emergency_malloc.lo `test -f 'src/emergency_malloc.cc' || echo '$(srcdir)/'`src/emergency_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/emergency_malloc.cc' object='src/libtcmalloc_internal_la-emergency_malloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-emergency_malloc.lo `test -f 'src/emergency_malloc.cc' || echo '$(srcdir)/'`src/emergency_malloc.cc + +src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo: src/emergency_malloc_for_stacktrace.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Tpo -c -o src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo `test -f 'src/emergency_malloc_for_stacktrace.cc' || echo '$(srcdir)/'`src/emergency_malloc_for_stacktrace.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/emergency_malloc_for_stacktrace.cc' object='src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.lo `test -f 'src/emergency_malloc_for_stacktrace.cc' || echo '$(srcdir)/'`src/emergency_malloc_for_stacktrace.cc + +src/libtcmalloc_internal_la-memory_region_map.lo: src/memory_region_map.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_la-memory_region_map.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Tpo -c -o src/libtcmalloc_internal_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Tpo src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memory_region_map.cc' object='src/libtcmalloc_internal_la-memory_region_map.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc + +src/libtcmalloc_internal_with_asserts_la-common.lo: src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-common.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common.cc' object='src/libtcmalloc_internal_with_asserts_la-common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc + +src/libtcmalloc_internal_with_asserts_la-internal_logging.lo: src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-internal_logging.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/internal_logging.cc' object='src/libtcmalloc_internal_with_asserts_la-internal_logging.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc + +src/libtcmalloc_internal_with_asserts_la-system-alloc.lo: src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-system-alloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/system-alloc.cc' object='src/libtcmalloc_internal_with_asserts_la-system-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc + +src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo: src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memfs_malloc.cc' object='src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc + +src/libtcmalloc_internal_with_asserts_la-central_freelist.lo: src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-central_freelist.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/central_freelist.cc' object='src/libtcmalloc_internal_with_asserts_la-central_freelist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc + +src/libtcmalloc_internal_with_asserts_la-page_heap.lo: src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-page_heap.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/page_heap.cc' object='src/libtcmalloc_internal_with_asserts_la-page_heap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc + +src/libtcmalloc_internal_with_asserts_la-sampler.lo: src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-sampler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/sampler.cc' object='src/libtcmalloc_internal_with_asserts_la-sampler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc + +src/libtcmalloc_internal_with_asserts_la-span.lo: src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-span.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/span.cc' object='src/libtcmalloc_internal_with_asserts_la-span.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc + +src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo: src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/stack_trace_table.cc' object='src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc + +src/libtcmalloc_internal_with_asserts_la-static_vars.lo: src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-static_vars.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/static_vars.cc' object='src/libtcmalloc_internal_with_asserts_la-static_vars.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc + +src/libtcmalloc_internal_with_asserts_la-symbolize.lo: src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-symbolize.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/symbolize.cc' object='src/libtcmalloc_internal_with_asserts_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc + +src/libtcmalloc_internal_with_asserts_la-thread_cache.lo: src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-thread_cache.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thread_cache.cc' object='src/libtcmalloc_internal_with_asserts_la-thread_cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc + +src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc + +src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo: src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_extension.cc' object='src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc + +src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo: src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Tpo -c -o src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Tpo src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/low_level_alloc.cc' object='src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_internal_with_asserts_la-low_level_alloc.lo `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc + +src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo: src/heap-profile-table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-profile-table.cc' object='src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc + +src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo: src/heap-profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-profiler.cc' object='src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc + +src/libtcmalloc_internal_with_asserts_la-raw_printer.lo: src/raw_printer.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-raw_printer.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/raw_printer.cc' object='src/libtcmalloc_internal_with_asserts_la-raw_printer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc + +src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo: src/fake_stacktrace_scope.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo `test -f 'src/fake_stacktrace_scope.cc' || echo '$(srcdir)/'`src/fake_stacktrace_scope.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/fake_stacktrace_scope.cc' object='src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.lo `test -f 'src/fake_stacktrace_scope.cc' || echo '$(srcdir)/'`src/fake_stacktrace_scope.cc + +src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo: src/emergency_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo `test -f 'src/emergency_malloc.cc' || echo '$(srcdir)/'`src/emergency_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/emergency_malloc.cc' object='src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-emergency_malloc.lo `test -f 'src/emergency_malloc.cc' || echo '$(srcdir)/'`src/emergency_malloc.cc + +src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo: src/emergency_malloc_for_stacktrace.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo `test -f 'src/emergency_malloc_for_stacktrace.cc' || echo '$(srcdir)/'`src/emergency_malloc_for_stacktrace.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/emergency_malloc_for_stacktrace.cc' object='src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.lo `test -f 'src/emergency_malloc_for_stacktrace.cc' || echo '$(srcdir)/'`src/emergency_malloc_for_stacktrace.cc + +src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo: src/memory_region_map.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Tpo -c -o src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Tpo src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memory_region_map.cc' object='src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_internal_with_asserts_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc + +src/libtcmalloc_minimal_la-tcmalloc.lo: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_la-tcmalloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo -c -o src/libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/libtcmalloc_minimal_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc + +src/libtcmalloc_minimal_debug_la-debugallocation.lo: src/debugallocation.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_debug_la-debugallocation.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo -c -o src/libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/debugallocation.cc' object='src/libtcmalloc_minimal_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc + +src/libtcmalloc_minimal_internal_la-common.lo: src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-common.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo -c -o src/libtcmalloc_minimal_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common.cc' object='src/libtcmalloc_minimal_internal_la-common.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc + +src/libtcmalloc_minimal_internal_la-internal_logging.lo: src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-internal_logging.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Tpo -c -o src/libtcmalloc_minimal_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/internal_logging.cc' object='src/libtcmalloc_minimal_internal_la-internal_logging.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc + +src/libtcmalloc_minimal_internal_la-system-alloc.lo: src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-system-alloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Tpo -c -o src/libtcmalloc_minimal_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/system-alloc.cc' object='src/libtcmalloc_minimal_internal_la-system-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc + +src/libtcmalloc_minimal_internal_la-memfs_malloc.lo: src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-memfs_malloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Tpo -c -o src/libtcmalloc_minimal_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memfs_malloc.cc' object='src/libtcmalloc_minimal_internal_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc + +src/libtcmalloc_minimal_internal_la-central_freelist.lo: src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-central_freelist.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Tpo -c -o src/libtcmalloc_minimal_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/central_freelist.cc' object='src/libtcmalloc_minimal_internal_la-central_freelist.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc + +src/libtcmalloc_minimal_internal_la-page_heap.lo: src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-page_heap.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Tpo -c -o src/libtcmalloc_minimal_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/page_heap.cc' object='src/libtcmalloc_minimal_internal_la-page_heap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc + +src/libtcmalloc_minimal_internal_la-sampler.lo: src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-sampler.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Tpo -c -o src/libtcmalloc_minimal_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/sampler.cc' object='src/libtcmalloc_minimal_internal_la-sampler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc + +src/libtcmalloc_minimal_internal_la-span.lo: src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-span.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Tpo -c -o src/libtcmalloc_minimal_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/span.cc' object='src/libtcmalloc_minimal_internal_la-span.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc + +src/libtcmalloc_minimal_internal_la-stack_trace_table.lo: src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-stack_trace_table.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Tpo -c -o src/libtcmalloc_minimal_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/stack_trace_table.cc' object='src/libtcmalloc_minimal_internal_la-stack_trace_table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc + +src/libtcmalloc_minimal_internal_la-static_vars.lo: src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-static_vars.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Tpo -c -o src/libtcmalloc_minimal_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/static_vars.cc' object='src/libtcmalloc_minimal_internal_la-static_vars.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc + +src/libtcmalloc_minimal_internal_la-symbolize.lo: src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-symbolize.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo -c -o src/libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/symbolize.cc' object='src/libtcmalloc_minimal_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc + +src/libtcmalloc_minimal_internal_la-thread_cache.lo: src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-thread_cache.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo -c -o src/libtcmalloc_minimal_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thread_cache.cc' object='src/libtcmalloc_minimal_internal_la-thread_cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc + +src/libtcmalloc_minimal_internal_la-malloc_hook.lo: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-malloc_hook.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Tpo -c -o src/libtcmalloc_minimal_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/libtcmalloc_minimal_internal_la-malloc_hook.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc + +src/libtcmalloc_minimal_internal_la-malloc_extension.lo: src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_minimal_internal_la-malloc_extension.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Tpo -c -o src/libtcmalloc_minimal_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Tpo src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_extension.cc' object='src/libtcmalloc_minimal_internal_la-malloc_extension.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_minimal_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc + +src/libtcmalloc_with_asserts_la-tcmalloc.lo: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_with_asserts_la-tcmalloc.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Tpo -c -o src/libtcmalloc_with_asserts_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Tpo src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/libtcmalloc_with_asserts_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_with_asserts_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc + +src/base/libtcmalloc_with_asserts_la-linuxthreads.lo: src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libtcmalloc_with_asserts_la-linuxthreads.lo -MD -MP -MF src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Tpo -c -o src/base/libtcmalloc_with_asserts_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Tpo src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/linuxthreads.cc' object='src/base/libtcmalloc_with_asserts_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/base/libtcmalloc_with_asserts_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc + +src/libtcmalloc_with_asserts_la-heap-checker.lo: src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_with_asserts_la-heap-checker.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Tpo -c -o src/libtcmalloc_with_asserts_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Tpo src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker.cc' object='src/libtcmalloc_with_asserts_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_with_asserts_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc + +src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -MT src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo -MD -MP -MF src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Tpo -c -o src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Tpo src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/heap-checker-bcad.cc' object='src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_with_asserts_la_CXXFLAGS) $(CXXFLAGS) -c -o src/libtcmalloc_with_asserts_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc + +src/tests/addressmap_unittest-addressmap_unittest.o: src/tests/addressmap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/addressmap_unittest-addressmap_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo -c -o src/tests/addressmap_unittest-addressmap_unittest.o `test -f 'src/tests/addressmap_unittest.cc' || echo '$(srcdir)/'`src/tests/addressmap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/addressmap_unittest.cc' object='src/tests/addressmap_unittest-addressmap_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/addressmap_unittest-addressmap_unittest.o `test -f 'src/tests/addressmap_unittest.cc' || echo '$(srcdir)/'`src/tests/addressmap_unittest.cc + +src/tests/addressmap_unittest-addressmap_unittest.obj: src/tests/addressmap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/addressmap_unittest-addressmap_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo -c -o src/tests/addressmap_unittest-addressmap_unittest.obj `if test -f 'src/tests/addressmap_unittest.cc'; then $(CYGPATH_W) 'src/tests/addressmap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/addressmap_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/addressmap_unittest.cc' object='src/tests/addressmap_unittest-addressmap_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/addressmap_unittest-addressmap_unittest.obj `if test -f 'src/tests/addressmap_unittest.cc'; then $(CYGPATH_W) 'src/tests/addressmap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/addressmap_unittest.cc'; fi` + +src/windows/addressmap_unittest-port.o: src/windows/port.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/windows/addressmap_unittest-port.o -MD -MP -MF src/windows/$(DEPDIR)/addressmap_unittest-port.Tpo -c -o src/windows/addressmap_unittest-port.o `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/windows/$(DEPDIR)/addressmap_unittest-port.Tpo src/windows/$(DEPDIR)/addressmap_unittest-port.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/windows/port.cc' object='src/windows/addressmap_unittest-port.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/windows/addressmap_unittest-port.o `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc + +src/windows/addressmap_unittest-port.obj: src/windows/port.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/windows/addressmap_unittest-port.obj -MD -MP -MF src/windows/$(DEPDIR)/addressmap_unittest-port.Tpo -c -o src/windows/addressmap_unittest-port.obj `if test -f 'src/windows/port.cc'; then $(CYGPATH_W) 'src/windows/port.cc'; else $(CYGPATH_W) '$(srcdir)/src/windows/port.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/windows/$(DEPDIR)/addressmap_unittest-port.Tpo src/windows/$(DEPDIR)/addressmap_unittest-port.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/windows/port.cc' object='src/windows/addressmap_unittest-port.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/windows/addressmap_unittest-port.obj `if test -f 'src/windows/port.cc'; then $(CYGPATH_W) 'src/windows/port.cc'; else $(CYGPATH_W) '$(srcdir)/src/windows/port.cc'; fi` + +benchmark/binary_trees-binary_trees.o: benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_CXXFLAGS) $(CXXFLAGS) -MT benchmark/binary_trees-binary_trees.o -MD -MP -MF benchmark/$(DEPDIR)/binary_trees-binary_trees.Tpo -c -o benchmark/binary_trees-binary_trees.o `test -f 'benchmark/binary_trees.cc' || echo '$(srcdir)/'`benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/binary_trees-binary_trees.Tpo benchmark/$(DEPDIR)/binary_trees-binary_trees.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/binary_trees.cc' object='benchmark/binary_trees-binary_trees.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/binary_trees-binary_trees.o `test -f 'benchmark/binary_trees.cc' || echo '$(srcdir)/'`benchmark/binary_trees.cc + +benchmark/binary_trees-binary_trees.obj: benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_CXXFLAGS) $(CXXFLAGS) -MT benchmark/binary_trees-binary_trees.obj -MD -MP -MF benchmark/$(DEPDIR)/binary_trees-binary_trees.Tpo -c -o benchmark/binary_trees-binary_trees.obj `if test -f 'benchmark/binary_trees.cc'; then $(CYGPATH_W) 'benchmark/binary_trees.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/binary_trees.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/binary_trees-binary_trees.Tpo benchmark/$(DEPDIR)/binary_trees-binary_trees.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/binary_trees.cc' object='benchmark/binary_trees-binary_trees.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/binary_trees-binary_trees.obj `if test -f 'benchmark/binary_trees.cc'; then $(CYGPATH_W) 'benchmark/binary_trees.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/binary_trees.cc'; fi` + +benchmark/binary_trees_shared-binary_trees.o: benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_shared_CXXFLAGS) $(CXXFLAGS) -MT benchmark/binary_trees_shared-binary_trees.o -MD -MP -MF benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Tpo -c -o benchmark/binary_trees_shared-binary_trees.o `test -f 'benchmark/binary_trees.cc' || echo '$(srcdir)/'`benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Tpo benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/binary_trees.cc' object='benchmark/binary_trees_shared-binary_trees.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_shared_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/binary_trees_shared-binary_trees.o `test -f 'benchmark/binary_trees.cc' || echo '$(srcdir)/'`benchmark/binary_trees.cc + +benchmark/binary_trees_shared-binary_trees.obj: benchmark/binary_trees.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_shared_CXXFLAGS) $(CXXFLAGS) -MT benchmark/binary_trees_shared-binary_trees.obj -MD -MP -MF benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Tpo -c -o benchmark/binary_trees_shared-binary_trees.obj `if test -f 'benchmark/binary_trees.cc'; then $(CYGPATH_W) 'benchmark/binary_trees.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/binary_trees.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Tpo benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/binary_trees.cc' object='benchmark/binary_trees_shared-binary_trees.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(binary_trees_shared_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/binary_trees_shared-binary_trees.obj `if test -f 'benchmark/binary_trees.cc'; then $(CYGPATH_W) 'benchmark/binary_trees.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/binary_trees.cc'; fi` + +src/tests/current_allocated_bytes_test-current_allocated_bytes_test.o: src/tests/current_allocated_bytes_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/current_allocated_bytes_test-current_allocated_bytes_test.o -MD -MP -MF src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo -c -o src/tests/current_allocated_bytes_test-current_allocated_bytes_test.o `test -f 'src/tests/current_allocated_bytes_test.cc' || echo '$(srcdir)/'`src/tests/current_allocated_bytes_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/current_allocated_bytes_test.cc' object='src/tests/current_allocated_bytes_test-current_allocated_bytes_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/current_allocated_bytes_test-current_allocated_bytes_test.o `test -f 'src/tests/current_allocated_bytes_test.cc' || echo '$(srcdir)/'`src/tests/current_allocated_bytes_test.cc + +src/tests/current_allocated_bytes_test-current_allocated_bytes_test.obj: src/tests/current_allocated_bytes_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/current_allocated_bytes_test-current_allocated_bytes_test.obj -MD -MP -MF src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo -c -o src/tests/current_allocated_bytes_test-current_allocated_bytes_test.obj `if test -f 'src/tests/current_allocated_bytes_test.cc'; then $(CYGPATH_W) 'src/tests/current_allocated_bytes_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/current_allocated_bytes_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/current_allocated_bytes_test.cc' object='src/tests/current_allocated_bytes_test-current_allocated_bytes_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/current_allocated_bytes_test-current_allocated_bytes_test.obj `if test -f 'src/tests/current_allocated_bytes_test.cc'; then $(CYGPATH_W) 'src/tests/current_allocated_bytes_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/current_allocated_bytes_test.cc'; fi` + +src/tests/debugallocation_test-debugallocation_test.o: src/tests/debugallocation_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/debugallocation_test-debugallocation_test.o -MD -MP -MF src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo -c -o src/tests/debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/debugallocation_test.cc' object='src/tests/debugallocation_test-debugallocation_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc + +src/tests/debugallocation_test-debugallocation_test.obj: src/tests/debugallocation_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/debugallocation_test-debugallocation_test.obj -MD -MP -MF src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo -c -o src/tests/debugallocation_test-debugallocation_test.obj `if test -f 'src/tests/debugallocation_test.cc'; then $(CYGPATH_W) 'src/tests/debugallocation_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/debugallocation_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/debugallocation_test.cc' object='src/tests/debugallocation_test-debugallocation_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/debugallocation_test-debugallocation_test.obj `if test -f 'src/tests/debugallocation_test.cc'; then $(CYGPATH_W) 'src/tests/debugallocation_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/debugallocation_test.cc'; fi` + +src/tests/frag_unittest-frag_unittest.o: src/tests/frag_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/frag_unittest-frag_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Tpo -c -o src/tests/frag_unittest-frag_unittest.o `test -f 'src/tests/frag_unittest.cc' || echo '$(srcdir)/'`src/tests/frag_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Tpo src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/frag_unittest.cc' object='src/tests/frag_unittest-frag_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/frag_unittest-frag_unittest.o `test -f 'src/tests/frag_unittest.cc' || echo '$(srcdir)/'`src/tests/frag_unittest.cc + +src/tests/frag_unittest-frag_unittest.obj: src/tests/frag_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/frag_unittest-frag_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Tpo -c -o src/tests/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` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Tpo src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/frag_unittest.cc' object='src/tests/frag_unittest-frag_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/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` + +src/tests/heap_checker_debug_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_checker_debug_unittest-heap-checker_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo -c -o src/tests/heap_checker_debug_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-checker_unittest.cc' object='src/tests/heap_checker_debug_unittest-heap-checker_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_checker_debug_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc + +src/tests/heap_checker_debug_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_checker_debug_unittest-heap-checker_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo -c -o src/tests/heap_checker_debug_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-checker_unittest.cc' object='src/tests/heap_checker_debug_unittest-heap-checker_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_checker_debug_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi` + +src/tests/heap_checker_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_checker_unittest-heap-checker_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo -c -o src/tests/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@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-checker_unittest.cc' object='src/tests/heap_checker_unittest-heap-checker_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_checker_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc + +src/tests/heap_checker_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_checker_unittest-heap-checker_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo -c -o src/tests/heap_checker_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-checker_unittest.cc' object='src/tests/heap_checker_unittest-heap-checker_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_checker_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi` + +src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo -c -o src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-profiler_unittest.cc' object='src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc + +src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.obj: src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo -c -o src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-profiler_unittest.cc' object='src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_profiler_debug_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi` + +src/tests/heap_profiler_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_profiler_unittest-heap-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo -c -o src/tests/heap_profiler_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-profiler_unittest.cc' object='src/tests/heap_profiler_unittest-heap-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_profiler_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc + +src/tests/heap_profiler_unittest-heap-profiler_unittest.obj: src/tests/heap-profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/heap_profiler_unittest-heap-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo -c -o src/tests/heap_profiler_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/heap-profiler_unittest.cc' object='src/tests/heap_profiler_unittest-heap-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/heap_profiler_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi` + +src/base/low_level_alloc_unittest-low_level_alloc.o: src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/base/low_level_alloc_unittest-low_level_alloc.o -MD -MP -MF src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo -c -o src/base/low_level_alloc_unittest-low_level_alloc.o `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/low_level_alloc.cc' object='src/base/low_level_alloc_unittest-low_level_alloc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/base/low_level_alloc_unittest-low_level_alloc.o `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc + +src/base/low_level_alloc_unittest-low_level_alloc.obj: src/base/low_level_alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/base/low_level_alloc_unittest-low_level_alloc.obj -MD -MP -MF src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo -c -o src/base/low_level_alloc_unittest-low_level_alloc.obj `if test -f 'src/base/low_level_alloc.cc'; then $(CYGPATH_W) 'src/base/low_level_alloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/base/low_level_alloc.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/base/low_level_alloc.cc' object='src/base/low_level_alloc_unittest-low_level_alloc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/base/low_level_alloc_unittest-low_level_alloc.obj `if test -f 'src/base/low_level_alloc.cc'; then $(CYGPATH_W) 'src/base/low_level_alloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/base/low_level_alloc.cc'; fi` + +src/low_level_alloc_unittest-malloc_hook.o: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/low_level_alloc_unittest-malloc_hook.o -MD -MP -MF src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo -c -o src/low_level_alloc_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/low_level_alloc_unittest-malloc_hook.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/low_level_alloc_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc + +src/low_level_alloc_unittest-malloc_hook.obj: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/low_level_alloc_unittest-malloc_hook.obj -MD -MP -MF src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo -c -o src/low_level_alloc_unittest-malloc_hook.obj `if test -f 'src/malloc_hook.cc'; then $(CYGPATH_W) 'src/malloc_hook.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_hook.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/low_level_alloc_unittest-malloc_hook.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/low_level_alloc_unittest-malloc_hook.obj `if test -f 'src/malloc_hook.cc'; then $(CYGPATH_W) 'src/malloc_hook.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_hook.cc'; fi` + +src/tests/low_level_alloc_unittest-low_level_alloc_unittest.o: src/tests/low_level_alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/low_level_alloc_unittest-low_level_alloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo -c -o src/tests/low_level_alloc_unittest-low_level_alloc_unittest.o `test -f 'src/tests/low_level_alloc_unittest.cc' || echo '$(srcdir)/'`src/tests/low_level_alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/low_level_alloc_unittest.cc' object='src/tests/low_level_alloc_unittest-low_level_alloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/low_level_alloc_unittest-low_level_alloc_unittest.o `test -f 'src/tests/low_level_alloc_unittest.cc' || echo '$(srcdir)/'`src/tests/low_level_alloc_unittest.cc + +src/tests/low_level_alloc_unittest-low_level_alloc_unittest.obj: src/tests/low_level_alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/low_level_alloc_unittest-low_level_alloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo -c -o src/tests/low_level_alloc_unittest-low_level_alloc_unittest.obj `if test -f 'src/tests/low_level_alloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/low_level_alloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/low_level_alloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/low_level_alloc_unittest.cc' object='src/tests/low_level_alloc_unittest-low_level_alloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/low_level_alloc_unittest-low_level_alloc_unittest.obj `if test -f 'src/tests/low_level_alloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/low_level_alloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/low_level_alloc_unittest.cc'; fi` + +benchmark/malloc_bench-malloc_bench.o: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench-malloc_bench.o -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Tpo -c -o benchmark/malloc_bench-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench-malloc_bench.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc + +benchmark/malloc_bench-malloc_bench.obj: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench-malloc_bench.obj -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Tpo -c -o benchmark/malloc_bench-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench-malloc_bench.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` + +benchmark/malloc_bench_shared-malloc_bench.o: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench_shared-malloc_bench.o -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Tpo -c -o benchmark/malloc_bench_shared-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench_shared-malloc_bench.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench_shared-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc + +benchmark/malloc_bench_shared-malloc_bench.obj: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench_shared-malloc_bench.obj -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Tpo -c -o benchmark/malloc_bench_shared-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench_shared-malloc_bench.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench_shared-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` + +benchmark/malloc_bench_shared_full-malloc_bench.o: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_full_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench_shared_full-malloc_bench.o -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Tpo -c -o benchmark/malloc_bench_shared_full-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench_shared_full-malloc_bench.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_full_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench_shared_full-malloc_bench.o `test -f 'benchmark/malloc_bench.cc' || echo '$(srcdir)/'`benchmark/malloc_bench.cc + +benchmark/malloc_bench_shared_full-malloc_bench.obj: benchmark/malloc_bench.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_full_CXXFLAGS) $(CXXFLAGS) -MT benchmark/malloc_bench_shared_full-malloc_bench.obj -MD -MP -MF benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Tpo -c -o benchmark/malloc_bench_shared_full-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Tpo benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='benchmark/malloc_bench.cc' object='benchmark/malloc_bench_shared_full-malloc_bench.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_bench_shared_full_CXXFLAGS) $(CXXFLAGS) -c -o benchmark/malloc_bench_shared_full-malloc_bench.obj `if test -f 'benchmark/malloc_bench.cc'; then $(CYGPATH_W) 'benchmark/malloc_bench.cc'; else $(CYGPATH_W) '$(srcdir)/benchmark/malloc_bench.cc'; fi` + +src/tests/malloc_extension_debug_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_extension_debug_test-malloc_extension_test.o -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo -c -o src/tests/malloc_extension_debug_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_extension_test.cc' object='src/tests/malloc_extension_debug_test-malloc_extension_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_extension_debug_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc + +src/tests/malloc_extension_debug_test-malloc_extension_test.obj: src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_extension_debug_test-malloc_extension_test.obj -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo -c -o src/tests/malloc_extension_debug_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_extension_test.cc' object='src/tests/malloc_extension_debug_test-malloc_extension_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_extension_debug_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi` + +src/tests/malloc_extension_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_extension_test-malloc_extension_test.o -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo -c -o src/tests/malloc_extension_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_extension_test.cc' object='src/tests/malloc_extension_test-malloc_extension_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_extension_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc + +src/tests/malloc_extension_test-malloc_extension_test.obj: src/tests/malloc_extension_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_extension_test-malloc_extension_test.obj -MD -MP -MF src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo -c -o src/tests/malloc_extension_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_extension_test.cc' object='src/tests/malloc_extension_test-malloc_extension_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_extension_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi` + +src/tests/malloc_hook_test-malloc_hook_test.o: src/tests/malloc_hook_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_hook_test-malloc_hook_test.o -MD -MP -MF src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo -c -o src/tests/malloc_hook_test-malloc_hook_test.o `test -f 'src/tests/malloc_hook_test.cc' || echo '$(srcdir)/'`src/tests/malloc_hook_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_hook_test.cc' object='src/tests/malloc_hook_test-malloc_hook_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_hook_test-malloc_hook_test.o `test -f 'src/tests/malloc_hook_test.cc' || echo '$(srcdir)/'`src/tests/malloc_hook_test.cc + +src/tests/malloc_hook_test-malloc_hook_test.obj: src/tests/malloc_hook_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_hook_test-malloc_hook_test.obj -MD -MP -MF src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo -c -o src/tests/malloc_hook_test-malloc_hook_test.obj `if test -f 'src/tests/malloc_hook_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_hook_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_hook_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/malloc_hook_test.cc' object='src/tests/malloc_hook_test-malloc_hook_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_hook_test-malloc_hook_test.obj `if test -f 'src/tests/malloc_hook_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_hook_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_hook_test.cc'; fi` + +src/tests/malloc_hook_test-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_hook_test-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/malloc_hook_test-testutil.Tpo -c -o src/tests/malloc_hook_test-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_hook_test-testutil.Tpo src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/malloc_hook_test-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_hook_test-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/malloc_hook_test-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/malloc_hook_test-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/malloc_hook_test-testutil.Tpo -c -o src/tests/malloc_hook_test-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/malloc_hook_test-testutil.Tpo src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/malloc_hook_test-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/malloc_hook_test-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/markidle_unittest-markidle_unittest.o: src/tests/markidle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/markidle_unittest-markidle_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Tpo -c -o src/tests/markidle_unittest-markidle_unittest.o `test -f 'src/tests/markidle_unittest.cc' || echo '$(srcdir)/'`src/tests/markidle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Tpo src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/markidle_unittest.cc' object='src/tests/markidle_unittest-markidle_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/markidle_unittest-markidle_unittest.o `test -f 'src/tests/markidle_unittest.cc' || echo '$(srcdir)/'`src/tests/markidle_unittest.cc + +src/tests/markidle_unittest-markidle_unittest.obj: src/tests/markidle_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/markidle_unittest-markidle_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Tpo -c -o src/tests/markidle_unittest-markidle_unittest.obj `if test -f 'src/tests/markidle_unittest.cc'; then $(CYGPATH_W) 'src/tests/markidle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/markidle_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Tpo src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/markidle_unittest.cc' object='src/tests/markidle_unittest-markidle_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/markidle_unittest-markidle_unittest.obj `if test -f 'src/tests/markidle_unittest.cc'; then $(CYGPATH_W) 'src/tests/markidle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/markidle_unittest.cc'; fi` + +src/tests/markidle_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/markidle_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/markidle_unittest-testutil.Tpo -c -o src/tests/markidle_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/markidle_unittest-testutil.Tpo src/tests/$(DEPDIR)/markidle_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/markidle_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/markidle_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/markidle_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/markidle_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/markidle_unittest-testutil.Tpo -c -o src/tests/markidle_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/markidle_unittest-testutil.Tpo src/tests/$(DEPDIR)/markidle_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/markidle_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/markidle_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/memalign_debug_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_debug_unittest-memalign_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo -c -o src/tests/memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/memalign_unittest.cc' object='src/tests/memalign_debug_unittest-memalign_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc + +src/tests/memalign_debug_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_debug_unittest-memalign_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo -c -o src/tests/memalign_debug_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/memalign_unittest.cc' object='src/tests/memalign_debug_unittest-memalign_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_debug_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi` + +src/tests/memalign_debug_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_debug_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Tpo -c -o src/tests/memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/memalign_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/memalign_debug_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_debug_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Tpo -c -o src/tests/memalign_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/memalign_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/memalign_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_unittest-memalign_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo -c -o src/tests/memalign_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/memalign_unittest.cc' object='src/tests/memalign_unittest-memalign_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc + +src/tests/memalign_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_unittest-memalign_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo -c -o src/tests/memalign_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/memalign_unittest.cc' object='src/tests/memalign_unittest-memalign_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi` + +src/tests/memalign_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/memalign_unittest-testutil.Tpo -c -o src/tests/memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_unittest-testutil.Tpo src/tests/$(DEPDIR)/memalign_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/memalign_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/memalign_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/memalign_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/memalign_unittest-testutil.Tpo -c -o src/tests/memalign_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/memalign_unittest-testutil.Tpo src/tests/$(DEPDIR)/memalign_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/memalign_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/memalign_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/packed_cache_test-packed-cache_test.o: src/tests/packed-cache_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/packed_cache_test-packed-cache_test.o -MD -MP -MF src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo -c -o src/tests/packed_cache_test-packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/packed-cache_test.cc' object='src/tests/packed_cache_test-packed-cache_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/packed_cache_test-packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc + +src/tests/packed_cache_test-packed-cache_test.obj: src/tests/packed-cache_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/packed_cache_test-packed-cache_test.obj -MD -MP -MF src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo -c -o src/tests/packed_cache_test-packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/packed-cache_test.cc' object='src/tests/packed_cache_test-packed-cache_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/packed_cache_test-packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi` + +src/tests/page_heap_test-page_heap_test.o: src/tests/page_heap_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/page_heap_test-page_heap_test.o -MD -MP -MF src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Tpo -c -o src/tests/page_heap_test-page_heap_test.o `test -f 'src/tests/page_heap_test.cc' || echo '$(srcdir)/'`src/tests/page_heap_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Tpo src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/page_heap_test.cc' object='src/tests/page_heap_test-page_heap_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/page_heap_test-page_heap_test.o `test -f 'src/tests/page_heap_test.cc' || echo '$(srcdir)/'`src/tests/page_heap_test.cc + +src/tests/page_heap_test-page_heap_test.obj: src/tests/page_heap_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/page_heap_test-page_heap_test.obj -MD -MP -MF src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Tpo -c -o src/tests/page_heap_test-page_heap_test.obj `if test -f 'src/tests/page_heap_test.cc'; then $(CYGPATH_W) 'src/tests/page_heap_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/page_heap_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Tpo src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/page_heap_test.cc' object='src/tests/page_heap_test-page_heap_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/page_heap_test-page_heap_test.obj `if test -f 'src/tests/page_heap_test.cc'; then $(CYGPATH_W) 'src/tests/page_heap_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/page_heap_test.cc'; fi` + +src/tests/pagemap_unittest-pagemap_unittest.o: src/tests/pagemap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/pagemap_unittest-pagemap_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo -c -o src/tests/pagemap_unittest-pagemap_unittest.o `test -f 'src/tests/pagemap_unittest.cc' || echo '$(srcdir)/'`src/tests/pagemap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/pagemap_unittest.cc' object='src/tests/pagemap_unittest-pagemap_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/pagemap_unittest-pagemap_unittest.o `test -f 'src/tests/pagemap_unittest.cc' || echo '$(srcdir)/'`src/tests/pagemap_unittest.cc + +src/tests/pagemap_unittest-pagemap_unittest.obj: src/tests/pagemap_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/pagemap_unittest-pagemap_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo -c -o src/tests/pagemap_unittest-pagemap_unittest.obj `if test -f 'src/tests/pagemap_unittest.cc'; then $(CYGPATH_W) 'src/tests/pagemap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/pagemap_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/pagemap_unittest.cc' object='src/tests/pagemap_unittest-pagemap_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/pagemap_unittest-pagemap_unittest.obj `if test -f 'src/tests/pagemap_unittest.cc'; then $(CYGPATH_W) 'src/tests/pagemap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/pagemap_unittest.cc'; fi` + +src/tests/profile_handler_unittest-profile-handler_unittest.o: src/tests/profile-handler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profile_handler_unittest-profile-handler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo -c -o src/tests/profile_handler_unittest-profile-handler_unittest.o `test -f 'src/tests/profile-handler_unittest.cc' || echo '$(srcdir)/'`src/tests/profile-handler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profile-handler_unittest.cc' object='src/tests/profile_handler_unittest-profile-handler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profile_handler_unittest-profile-handler_unittest.o `test -f 'src/tests/profile-handler_unittest.cc' || echo '$(srcdir)/'`src/tests/profile-handler_unittest.cc + +src/tests/profile_handler_unittest-profile-handler_unittest.obj: src/tests/profile-handler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profile_handler_unittest-profile-handler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo -c -o src/tests/profile_handler_unittest-profile-handler_unittest.obj `if test -f 'src/tests/profile-handler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profile-handler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profile-handler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profile-handler_unittest.cc' object='src/tests/profile_handler_unittest-profile-handler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profile_handler_unittest-profile-handler_unittest.obj `if test -f 'src/tests/profile-handler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profile-handler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profile-handler_unittest.cc'; fi` + +src/tests/profiler1_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler1_unittest-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo -c -o src/tests/profiler1_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler1_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler1_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc + +src/tests/profiler1_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler1_unittest-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo -c -o src/tests/profiler1_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler1_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler1_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` + +src/tests/profiler1_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler1_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/profiler1_unittest-testutil.Tpo -c -o src/tests/profiler1_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler1_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler1_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler1_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/profiler1_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler1_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler1_unittest-testutil.Tpo -c -o src/tests/profiler1_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler1_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler1_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler1_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/profiler2_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler2_unittest-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo -c -o src/tests/profiler2_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler2_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler2_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc + +src/tests/profiler2_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler2_unittest-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo -c -o src/tests/profiler2_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler2_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler2_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` + +src/tests/profiler2_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler2_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/profiler2_unittest-testutil.Tpo -c -o src/tests/profiler2_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler2_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler2_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler2_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/profiler2_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler2_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler2_unittest-testutil.Tpo -c -o src/tests/profiler2_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler2_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler2_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler2_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/profiler3_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler3_unittest-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo -c -o src/tests/profiler3_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler3_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler3_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc + +src/tests/profiler3_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler3_unittest-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo -c -o src/tests/profiler3_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler3_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler3_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` + +src/tests/profiler3_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler3_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/profiler3_unittest-testutil.Tpo -c -o src/tests/profiler3_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler3_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler3_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler3_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/profiler3_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler3_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler3_unittest-testutil.Tpo -c -o src/tests/profiler3_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler3_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler3_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler3_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/profiler4_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler4_unittest-profiler_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo -c -o src/tests/profiler4_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler4_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler4_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc + +src/tests/profiler4_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler4_unittest-profiler_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo -c -o src/tests/profiler4_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/profiler_unittest.cc' object='src/tests/profiler4_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler4_unittest-profiler_unittest.obj `if test -f 'src/tests/profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiler_unittest.cc'; fi` + +src/tests/profiler4_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler4_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/profiler4_unittest-testutil.Tpo -c -o src/tests/profiler4_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler4_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler4_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler4_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/profiler4_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/profiler4_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/profiler4_unittest-testutil.Tpo -c -o src/tests/profiler4_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/profiler4_unittest-testutil.Tpo src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/profiler4_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/profiler4_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/raw_printer_test-raw_printer_test.o: src/tests/raw_printer_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/raw_printer_test-raw_printer_test.o -MD -MP -MF src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Tpo -c -o src/tests/raw_printer_test-raw_printer_test.o `test -f 'src/tests/raw_printer_test.cc' || echo '$(srcdir)/'`src/tests/raw_printer_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Tpo src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/raw_printer_test.cc' object='src/tests/raw_printer_test-raw_printer_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/raw_printer_test-raw_printer_test.o `test -f 'src/tests/raw_printer_test.cc' || echo '$(srcdir)/'`src/tests/raw_printer_test.cc + +src/tests/raw_printer_test-raw_printer_test.obj: src/tests/raw_printer_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/raw_printer_test-raw_printer_test.obj -MD -MP -MF src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Tpo -c -o src/tests/raw_printer_test-raw_printer_test.obj `if test -f 'src/tests/raw_printer_test.cc'; then $(CYGPATH_W) 'src/tests/raw_printer_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/raw_printer_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Tpo src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/raw_printer_test.cc' object='src/tests/raw_printer_test-raw_printer_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/raw_printer_test-raw_printer_test.obj `if test -f 'src/tests/raw_printer_test.cc'; then $(CYGPATH_W) 'src/tests/raw_printer_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/raw_printer_test.cc'; fi` + +src/tests/realloc_debug_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/realloc_debug_unittest-realloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo -c -o src/tests/realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/realloc_unittest.cc' object='src/tests/realloc_debug_unittest-realloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc + +src/tests/realloc_debug_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/realloc_debug_unittest-realloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo -c -o src/tests/realloc_debug_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/realloc_unittest.cc' object='src/tests/realloc_debug_unittest-realloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/realloc_debug_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi` + +src/tests/realloc_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/realloc_unittest-realloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo -c -o src/tests/realloc_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/realloc_unittest.cc' object='src/tests/realloc_unittest-realloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/realloc_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc + +src/tests/realloc_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/realloc_unittest-realloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo -c -o src/tests/realloc_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/realloc_unittest.cc' object='src/tests/realloc_unittest-realloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/realloc_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi` + +src/tests/sampler_debug_test-sampler_test.o: src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampler_debug_test-sampler_test.o -MD -MP -MF src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Tpo -c -o src/tests/sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Tpo src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampler_test.cc' object='src/tests/sampler_debug_test-sampler_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc + +src/tests/sampler_debug_test-sampler_test.obj: src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampler_debug_test-sampler_test.obj -MD -MP -MF src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Tpo -c -o src/tests/sampler_debug_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Tpo src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampler_test.cc' object='src/tests/sampler_debug_test-sampler_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampler_debug_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi` + +src/tests/sampler_test-sampler_test.o: src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampler_test-sampler_test.o -MD -MP -MF src/tests/$(DEPDIR)/sampler_test-sampler_test.Tpo -c -o src/tests/sampler_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampler_test-sampler_test.Tpo src/tests/$(DEPDIR)/sampler_test-sampler_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampler_test.cc' object='src/tests/sampler_test-sampler_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampler_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc + +src/tests/sampler_test-sampler_test.obj: src/tests/sampler_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampler_test-sampler_test.obj -MD -MP -MF src/tests/$(DEPDIR)/sampler_test-sampler_test.Tpo -c -o src/tests/sampler_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampler_test-sampler_test.Tpo src/tests/$(DEPDIR)/sampler_test-sampler_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampler_test.cc' object='src/tests/sampler_test-sampler_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampler_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi` + +src/tests/sampling_debug_test-sampling_test.o: src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampling_debug_test-sampling_test.o -MD -MP -MF src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Tpo -c -o src/tests/sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Tpo src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampling_test.cc' object='src/tests/sampling_debug_test-sampling_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc + +src/tests/sampling_debug_test-sampling_test.obj: src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampling_debug_test-sampling_test.obj -MD -MP -MF src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Tpo -c -o src/tests/sampling_debug_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Tpo src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampling_test.cc' object='src/tests/sampling_debug_test-sampling_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampling_debug_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi` + +src/tests/sampling_test-sampling_test.o: src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampling_test-sampling_test.o -MD -MP -MF src/tests/$(DEPDIR)/sampling_test-sampling_test.Tpo -c -o src/tests/sampling_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampling_test-sampling_test.Tpo src/tests/$(DEPDIR)/sampling_test-sampling_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampling_test.cc' object='src/tests/sampling_test-sampling_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampling_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc + +src/tests/sampling_test-sampling_test.obj: src/tests/sampling_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/sampling_test-sampling_test.obj -MD -MP -MF src/tests/$(DEPDIR)/sampling_test-sampling_test.Tpo -c -o src/tests/sampling_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/sampling_test-sampling_test.Tpo src/tests/$(DEPDIR)/sampling_test-sampling_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/sampling_test.cc' object='src/tests/sampling_test-sampling_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/sampling_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi` + +src/tests/stack_trace_table_test-stack_trace_table_test.o: src/tests/stack_trace_table_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/stack_trace_table_test-stack_trace_table_test.o -MD -MP -MF src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo -c -o src/tests/stack_trace_table_test-stack_trace_table_test.o `test -f 'src/tests/stack_trace_table_test.cc' || echo '$(srcdir)/'`src/tests/stack_trace_table_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/stack_trace_table_test.cc' object='src/tests/stack_trace_table_test-stack_trace_table_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/stack_trace_table_test-stack_trace_table_test.o `test -f 'src/tests/stack_trace_table_test.cc' || echo '$(srcdir)/'`src/tests/stack_trace_table_test.cc + +src/tests/stack_trace_table_test-stack_trace_table_test.obj: src/tests/stack_trace_table_test.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -MT src/tests/stack_trace_table_test-stack_trace_table_test.obj -MD -MP -MF src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo -c -o src/tests/stack_trace_table_test-stack_trace_table_test.obj `if test -f 'src/tests/stack_trace_table_test.cc'; then $(CYGPATH_W) 'src/tests/stack_trace_table_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/stack_trace_table_test.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/stack_trace_table_test.cc' object='src/tests/stack_trace_table_test-stack_trace_table_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/stack_trace_table_test-stack_trace_table_test.obj `if test -f 'src/tests/stack_trace_table_test.cc'; then $(CYGPATH_W) 'src/tests/stack_trace_table_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/stack_trace_table_test.cc'; fi` + +src/tests/system_alloc_unittest-system-alloc_unittest.o: src/tests/system-alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/system_alloc_unittest-system-alloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo -c -o src/tests/system_alloc_unittest-system-alloc_unittest.o `test -f 'src/tests/system-alloc_unittest.cc' || echo '$(srcdir)/'`src/tests/system-alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/system-alloc_unittest.cc' object='src/tests/system_alloc_unittest-system-alloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/system_alloc_unittest-system-alloc_unittest.o `test -f 'src/tests/system-alloc_unittest.cc' || echo '$(srcdir)/'`src/tests/system-alloc_unittest.cc + +src/tests/system_alloc_unittest-system-alloc_unittest.obj: src/tests/system-alloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/system_alloc_unittest-system-alloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo -c -o src/tests/system_alloc_unittest-system-alloc_unittest.obj `if test -f 'src/tests/system-alloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/system-alloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/system-alloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/system-alloc_unittest.cc' object='src/tests/system_alloc_unittest-system-alloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/system_alloc_unittest-system-alloc_unittest.obj `if test -f 'src/tests/system-alloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/system-alloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/system-alloc_unittest.cc'; fi` + +src/tests/tcm_asserts_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_asserts_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcm_asserts_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcm_asserts_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_asserts_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcm_asserts_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_asserts_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcm_asserts_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcm_asserts_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_asserts_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcm_asserts_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_asserts_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Tpo -c -o src/tests/tcm_asserts_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcm_asserts_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_asserts_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcm_asserts_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_asserts_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Tpo -c -o src/tests/tcm_asserts_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcm_asserts_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_asserts_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_min_asserts_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcm_min_asserts_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_min_asserts_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Tpo -c -o src/tests/tcm_min_asserts_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcm_min_asserts_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_min_asserts_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcm_min_asserts_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcm_min_asserts_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Tpo -c -o src/tests/tcm_min_asserts_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcm_min_asserts_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcm_min_asserts_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tcm_min_asserts_unittest-common.o: src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-common.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-common.Tpo -c -o src/tcm_min_asserts_unittest-common.o `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-common.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common.cc' object='src/tcm_min_asserts_unittest-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-common.o `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc + +src/tcm_min_asserts_unittest-common.obj: src/common.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-common.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-common.Tpo -c -o src/tcm_min_asserts_unittest-common.obj `if test -f 'src/common.cc'; then $(CYGPATH_W) 'src/common.cc'; else $(CYGPATH_W) '$(srcdir)/src/common.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-common.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common.cc' object='src/tcm_min_asserts_unittest-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-common.obj `if test -f 'src/common.cc'; then $(CYGPATH_W) 'src/common.cc'; else $(CYGPATH_W) '$(srcdir)/src/common.cc'; fi` + +src/tcm_min_asserts_unittest-internal_logging.o: src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-internal_logging.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Tpo -c -o src/tcm_min_asserts_unittest-internal_logging.o `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/internal_logging.cc' object='src/tcm_min_asserts_unittest-internal_logging.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-internal_logging.o `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc + +src/tcm_min_asserts_unittest-internal_logging.obj: src/internal_logging.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-internal_logging.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Tpo -c -o src/tcm_min_asserts_unittest-internal_logging.obj `if test -f 'src/internal_logging.cc'; then $(CYGPATH_W) 'src/internal_logging.cc'; else $(CYGPATH_W) '$(srcdir)/src/internal_logging.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/internal_logging.cc' object='src/tcm_min_asserts_unittest-internal_logging.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-internal_logging.obj `if test -f 'src/internal_logging.cc'; then $(CYGPATH_W) 'src/internal_logging.cc'; else $(CYGPATH_W) '$(srcdir)/src/internal_logging.cc'; fi` + +src/tcm_min_asserts_unittest-system-alloc.o: src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-system-alloc.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Tpo -c -o src/tcm_min_asserts_unittest-system-alloc.o `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/system-alloc.cc' object='src/tcm_min_asserts_unittest-system-alloc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-system-alloc.o `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc + +src/tcm_min_asserts_unittest-system-alloc.obj: src/system-alloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-system-alloc.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Tpo -c -o src/tcm_min_asserts_unittest-system-alloc.obj `if test -f 'src/system-alloc.cc'; then $(CYGPATH_W) 'src/system-alloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/system-alloc.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/system-alloc.cc' object='src/tcm_min_asserts_unittest-system-alloc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-system-alloc.obj `if test -f 'src/system-alloc.cc'; then $(CYGPATH_W) 'src/system-alloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/system-alloc.cc'; fi` + +src/tcm_min_asserts_unittest-memfs_malloc.o: src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-memfs_malloc.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Tpo -c -o src/tcm_min_asserts_unittest-memfs_malloc.o `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memfs_malloc.cc' object='src/tcm_min_asserts_unittest-memfs_malloc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-memfs_malloc.o `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc + +src/tcm_min_asserts_unittest-memfs_malloc.obj: src/memfs_malloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-memfs_malloc.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Tpo -c -o src/tcm_min_asserts_unittest-memfs_malloc.obj `if test -f 'src/memfs_malloc.cc'; then $(CYGPATH_W) 'src/memfs_malloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/memfs_malloc.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/memfs_malloc.cc' object='src/tcm_min_asserts_unittest-memfs_malloc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-memfs_malloc.obj `if test -f 'src/memfs_malloc.cc'; then $(CYGPATH_W) 'src/memfs_malloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/memfs_malloc.cc'; fi` + +src/tcm_min_asserts_unittest-central_freelist.o: src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-central_freelist.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Tpo -c -o src/tcm_min_asserts_unittest-central_freelist.o `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/central_freelist.cc' object='src/tcm_min_asserts_unittest-central_freelist.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-central_freelist.o `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc + +src/tcm_min_asserts_unittest-central_freelist.obj: src/central_freelist.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-central_freelist.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Tpo -c -o src/tcm_min_asserts_unittest-central_freelist.obj `if test -f 'src/central_freelist.cc'; then $(CYGPATH_W) 'src/central_freelist.cc'; else $(CYGPATH_W) '$(srcdir)/src/central_freelist.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/central_freelist.cc' object='src/tcm_min_asserts_unittest-central_freelist.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-central_freelist.obj `if test -f 'src/central_freelist.cc'; then $(CYGPATH_W) 'src/central_freelist.cc'; else $(CYGPATH_W) '$(srcdir)/src/central_freelist.cc'; fi` + +src/tcm_min_asserts_unittest-page_heap.o: src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-page_heap.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Tpo -c -o src/tcm_min_asserts_unittest-page_heap.o `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/page_heap.cc' object='src/tcm_min_asserts_unittest-page_heap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-page_heap.o `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc + +src/tcm_min_asserts_unittest-page_heap.obj: src/page_heap.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-page_heap.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Tpo -c -o src/tcm_min_asserts_unittest-page_heap.obj `if test -f 'src/page_heap.cc'; then $(CYGPATH_W) 'src/page_heap.cc'; else $(CYGPATH_W) '$(srcdir)/src/page_heap.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/page_heap.cc' object='src/tcm_min_asserts_unittest-page_heap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-page_heap.obj `if test -f 'src/page_heap.cc'; then $(CYGPATH_W) 'src/page_heap.cc'; else $(CYGPATH_W) '$(srcdir)/src/page_heap.cc'; fi` + +src/tcm_min_asserts_unittest-sampler.o: src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-sampler.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Tpo -c -o src/tcm_min_asserts_unittest-sampler.o `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/sampler.cc' object='src/tcm_min_asserts_unittest-sampler.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-sampler.o `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc + +src/tcm_min_asserts_unittest-sampler.obj: src/sampler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-sampler.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Tpo -c -o src/tcm_min_asserts_unittest-sampler.obj `if test -f 'src/sampler.cc'; then $(CYGPATH_W) 'src/sampler.cc'; else $(CYGPATH_W) '$(srcdir)/src/sampler.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/sampler.cc' object='src/tcm_min_asserts_unittest-sampler.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-sampler.obj `if test -f 'src/sampler.cc'; then $(CYGPATH_W) 'src/sampler.cc'; else $(CYGPATH_W) '$(srcdir)/src/sampler.cc'; fi` + +src/tcm_min_asserts_unittest-span.o: src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-span.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-span.Tpo -c -o src/tcm_min_asserts_unittest-span.o `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-span.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/span.cc' object='src/tcm_min_asserts_unittest-span.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-span.o `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc + +src/tcm_min_asserts_unittest-span.obj: src/span.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-span.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-span.Tpo -c -o src/tcm_min_asserts_unittest-span.obj `if test -f 'src/span.cc'; then $(CYGPATH_W) 'src/span.cc'; else $(CYGPATH_W) '$(srcdir)/src/span.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-span.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/span.cc' object='src/tcm_min_asserts_unittest-span.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-span.obj `if test -f 'src/span.cc'; then $(CYGPATH_W) 'src/span.cc'; else $(CYGPATH_W) '$(srcdir)/src/span.cc'; fi` + +src/tcm_min_asserts_unittest-stack_trace_table.o: src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-stack_trace_table.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Tpo -c -o src/tcm_min_asserts_unittest-stack_trace_table.o `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/stack_trace_table.cc' object='src/tcm_min_asserts_unittest-stack_trace_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-stack_trace_table.o `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc + +src/tcm_min_asserts_unittest-stack_trace_table.obj: src/stack_trace_table.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-stack_trace_table.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Tpo -c -o src/tcm_min_asserts_unittest-stack_trace_table.obj `if test -f 'src/stack_trace_table.cc'; then $(CYGPATH_W) 'src/stack_trace_table.cc'; else $(CYGPATH_W) '$(srcdir)/src/stack_trace_table.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/stack_trace_table.cc' object='src/tcm_min_asserts_unittest-stack_trace_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-stack_trace_table.obj `if test -f 'src/stack_trace_table.cc'; then $(CYGPATH_W) 'src/stack_trace_table.cc'; else $(CYGPATH_W) '$(srcdir)/src/stack_trace_table.cc'; fi` + +src/tcm_min_asserts_unittest-static_vars.o: src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-static_vars.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Tpo -c -o src/tcm_min_asserts_unittest-static_vars.o `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/static_vars.cc' object='src/tcm_min_asserts_unittest-static_vars.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-static_vars.o `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc + +src/tcm_min_asserts_unittest-static_vars.obj: src/static_vars.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-static_vars.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Tpo -c -o src/tcm_min_asserts_unittest-static_vars.obj `if test -f 'src/static_vars.cc'; then $(CYGPATH_W) 'src/static_vars.cc'; else $(CYGPATH_W) '$(srcdir)/src/static_vars.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/static_vars.cc' object='src/tcm_min_asserts_unittest-static_vars.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-static_vars.obj `if test -f 'src/static_vars.cc'; then $(CYGPATH_W) 'src/static_vars.cc'; else $(CYGPATH_W) '$(srcdir)/src/static_vars.cc'; fi` + +src/tcm_min_asserts_unittest-symbolize.o: src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-symbolize.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Tpo -c -o src/tcm_min_asserts_unittest-symbolize.o `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/symbolize.cc' object='src/tcm_min_asserts_unittest-symbolize.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-symbolize.o `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc + +src/tcm_min_asserts_unittest-symbolize.obj: src/symbolize.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-symbolize.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Tpo -c -o src/tcm_min_asserts_unittest-symbolize.obj `if test -f 'src/symbolize.cc'; then $(CYGPATH_W) 'src/symbolize.cc'; else $(CYGPATH_W) '$(srcdir)/src/symbolize.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/symbolize.cc' object='src/tcm_min_asserts_unittest-symbolize.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-symbolize.obj `if test -f 'src/symbolize.cc'; then $(CYGPATH_W) 'src/symbolize.cc'; else $(CYGPATH_W) '$(srcdir)/src/symbolize.cc'; fi` + +src/tcm_min_asserts_unittest-thread_cache.o: src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-thread_cache.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Tpo -c -o src/tcm_min_asserts_unittest-thread_cache.o `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thread_cache.cc' object='src/tcm_min_asserts_unittest-thread_cache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-thread_cache.o `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc + +src/tcm_min_asserts_unittest-thread_cache.obj: src/thread_cache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-thread_cache.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Tpo -c -o src/tcm_min_asserts_unittest-thread_cache.obj `if test -f 'src/thread_cache.cc'; then $(CYGPATH_W) 'src/thread_cache.cc'; else $(CYGPATH_W) '$(srcdir)/src/thread_cache.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thread_cache.cc' object='src/tcm_min_asserts_unittest-thread_cache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-thread_cache.obj `if test -f 'src/thread_cache.cc'; then $(CYGPATH_W) 'src/thread_cache.cc'; else $(CYGPATH_W) '$(srcdir)/src/thread_cache.cc'; fi` + +src/tcm_min_asserts_unittest-malloc_hook.o: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-malloc_hook.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Tpo -c -o src/tcm_min_asserts_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/tcm_min_asserts_unittest-malloc_hook.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc + +src/tcm_min_asserts_unittest-malloc_hook.obj: src/malloc_hook.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-malloc_hook.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Tpo -c -o src/tcm_min_asserts_unittest-malloc_hook.obj `if test -f 'src/malloc_hook.cc'; then $(CYGPATH_W) 'src/malloc_hook.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_hook.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_hook.cc' object='src/tcm_min_asserts_unittest-malloc_hook.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-malloc_hook.obj `if test -f 'src/malloc_hook.cc'; then $(CYGPATH_W) 'src/malloc_hook.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_hook.cc'; fi` + +src/tcm_min_asserts_unittest-malloc_extension.o: src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-malloc_extension.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Tpo -c -o src/tcm_min_asserts_unittest-malloc_extension.o `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_extension.cc' object='src/tcm_min_asserts_unittest-malloc_extension.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-malloc_extension.o `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc + +src/tcm_min_asserts_unittest-malloc_extension.obj: src/malloc_extension.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-malloc_extension.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Tpo -c -o src/tcm_min_asserts_unittest-malloc_extension.obj `if test -f 'src/malloc_extension.cc'; then $(CYGPATH_W) 'src/malloc_extension.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_extension.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/malloc_extension.cc' object='src/tcm_min_asserts_unittest-malloc_extension.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-malloc_extension.obj `if test -f 'src/malloc_extension.cc'; then $(CYGPATH_W) 'src/malloc_extension.cc'; else $(CYGPATH_W) '$(srcdir)/src/malloc_extension.cc'; fi` + +src/tcm_min_asserts_unittest-tcmalloc.o: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-tcmalloc.o -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Tpo -c -o src/tcm_min_asserts_unittest-tcmalloc.o `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/tcm_min_asserts_unittest-tcmalloc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-tcmalloc.o `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc + +src/tcm_min_asserts_unittest-tcmalloc.obj: src/tcmalloc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tcm_min_asserts_unittest-tcmalloc.obj -MD -MP -MF src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Tpo -c -o src/tcm_min_asserts_unittest-tcmalloc.obj `if test -f 'src/tcmalloc.cc'; then $(CYGPATH_W) 'src/tcmalloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/tcmalloc.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Tpo src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tcmalloc.cc' object='src/tcm_min_asserts_unittest-tcmalloc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcm_min_asserts_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tcm_min_asserts_unittest-tcmalloc.obj `if test -f 'src/tcmalloc.cc'; then $(CYGPATH_W) 'src/tcmalloc.cc'; else $(CYGPATH_W) '$(srcdir)/src/tcmalloc.cc'; fi` + +src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_and_profiler_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_and_profiler_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo -c -o src/tests/tcmalloc_and_profiler_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_and_profiler_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_and_profiler_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_and_profiler_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_and_profiler_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo -c -o src/tests/tcmalloc_and_profiler_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_and_profiler_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_and_profiler_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcmalloc_both_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_both_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_both_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_both_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_both_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_both_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_both_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_both_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_both_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_both_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_both_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_both_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo -c -o src/tests/tcmalloc_both_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_both_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_both_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_both_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_both_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo -c -o src/tests/tcmalloc_both_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_both_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_both_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_debug_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_debug_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo -c -o src/tests/tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_debug_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_debug_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo -c -o src/tests/tcmalloc_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o: src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo -c -o src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o `test -f 'src/tests/large_heap_fragmentation_unittest.cc' || echo '$(srcdir)/'`src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/large_heap_fragmentation_unittest.cc' object='src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o `test -f 'src/tests/large_heap_fragmentation_unittest.cc' || echo '$(srcdir)/'`src/tests/large_heap_fragmentation_unittest.cc + +src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj: src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo -c -o src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj `if test -f 'src/tests/large_heap_fragmentation_unittest.cc'; then $(CYGPATH_W) 'src/tests/large_heap_fragmentation_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/large_heap_fragmentation_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/large_heap_fragmentation_unittest.cc' object='src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj `if test -f 'src/tests/large_heap_fragmentation_unittest.cc'; then $(CYGPATH_W) 'src/tests/large_heap_fragmentation_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/large_heap_fragmentation_unittest.cc'; fi` + +src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo -c -o src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_large_unittest.cc' object='src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc + +src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.obj: src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo -c -o src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.obj `if test -f 'src/tests/tcmalloc_large_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_large_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_large_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_large_unittest.cc' object='src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_large_unittest-tcmalloc_large_unittest.obj `if test -f 'src/tests/tcmalloc_large_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_large_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_large_unittest.cc'; fi` + +src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_minimal_debug_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_debug_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo -c -o src/tests/tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_minimal_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_minimal_debug_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_debug_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo -c -o src/tests/tcmalloc_minimal_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_minimal_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o: src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo -c -o src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o `test -f 'src/tests/large_heap_fragmentation_unittest.cc' || echo '$(srcdir)/'`src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/large_heap_fragmentation_unittest.cc' object='src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.o `test -f 'src/tests/large_heap_fragmentation_unittest.cc' || echo '$(srcdir)/'`src/tests/large_heap_fragmentation_unittest.cc + +src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj: src/tests/large_heap_fragmentation_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo -c -o src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj `if test -f 'src/tests/large_heap_fragmentation_unittest.cc'; then $(CYGPATH_W) 'src/tests/large_heap_fragmentation_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/large_heap_fragmentation_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/large_heap_fragmentation_unittest.cc' object='src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_heap_fragmentation_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.obj `if test -f 'src/tests/large_heap_fragmentation_unittest.cc'; then $(CYGPATH_W) 'src/tests/large_heap_fragmentation_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/large_heap_fragmentation_unittest.cc'; fi` + +src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo -c -o src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_large_unittest.cc' object='src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc + +src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj: src/tests/tcmalloc_large_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo -c -o src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj `if test -f 'src/tests/tcmalloc_large_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_large_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_large_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_large_unittest.cc' object='src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj `if test -f 'src/tests/tcmalloc_large_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_large_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_large_unittest.cc'; fi` + +src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_minimal_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo -c -o src/tests/tcmalloc_minimal_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_minimal_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_minimal_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_minimal_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo -c -o src/tests/tcmalloc_minimal_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_minimal_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_minimal_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/tcmalloc_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_unittest-tcmalloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc + +src/tests/tcmalloc_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_unittest-tcmalloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo -c -o src/tests/tcmalloc_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/tcmalloc_unittest.cc' object='src/tests/tcmalloc_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi` + +src/tests/tcmalloc_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Tpo -c -o src/tests/tcmalloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/tcmalloc_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/tcmalloc_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Tpo -c -o src/tests/tcmalloc_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Tpo src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/tcmalloc_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/tcmalloc_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +src/tests/thread_dealloc_unittest-thread_dealloc_unittest.o: src/tests/thread_dealloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/thread_dealloc_unittest-thread_dealloc_unittest.o -MD -MP -MF src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo -c -o src/tests/thread_dealloc_unittest-thread_dealloc_unittest.o `test -f 'src/tests/thread_dealloc_unittest.cc' || echo '$(srcdir)/'`src/tests/thread_dealloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/thread_dealloc_unittest.cc' object='src/tests/thread_dealloc_unittest-thread_dealloc_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/thread_dealloc_unittest-thread_dealloc_unittest.o `test -f 'src/tests/thread_dealloc_unittest.cc' || echo '$(srcdir)/'`src/tests/thread_dealloc_unittest.cc + +src/tests/thread_dealloc_unittest-thread_dealloc_unittest.obj: src/tests/thread_dealloc_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/thread_dealloc_unittest-thread_dealloc_unittest.obj -MD -MP -MF src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo -c -o src/tests/thread_dealloc_unittest-thread_dealloc_unittest.obj `if test -f 'src/tests/thread_dealloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/thread_dealloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/thread_dealloc_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/thread_dealloc_unittest.cc' object='src/tests/thread_dealloc_unittest-thread_dealloc_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/thread_dealloc_unittest-thread_dealloc_unittest.obj `if test -f 'src/tests/thread_dealloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/thread_dealloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/thread_dealloc_unittest.cc'; fi` + +src/tests/thread_dealloc_unittest-testutil.o: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/thread_dealloc_unittest-testutil.o -MD -MP -MF src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Tpo -c -o src/tests/thread_dealloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Tpo src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/thread_dealloc_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/thread_dealloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc + +src/tests/thread_dealloc_unittest-testutil.obj: src/tests/testutil.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT src/tests/thread_dealloc_unittest-testutil.obj -MD -MP -MF src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Tpo -c -o src/tests/thread_dealloc_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Tpo src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tests/testutil.cc' object='src/tests/thread_dealloc_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o src/tests/thread_dealloc_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf benchmark/.libs benchmark/_libs + -rm -rf src/.libs src/_libs + -rm -rf src/base/.libs src/base/_libs + -rm -rf src/windows/.libs src/windows/_libs + +distclean-libtool: + -rm -f libtool config.lt +install-man1: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-googleincludeHEADERS: $(googleinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(googleinclude_HEADERS)'; test -n "$(googleincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(googleincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(googleincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(googleincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(googleincludedir)" || exit $$?; \ + done + +uninstall-googleincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(googleinclude_HEADERS)'; test -n "$(googleincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(googleincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_perftoolsincludeHEADERS: $(nodist_perftoolsinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_perftoolsinclude_HEADERS)'; test -n "$(perftoolsincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(perftoolsincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(perftoolsincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(perftoolsincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(perftoolsincludedir)" || exit $$?; \ + done + +uninstall-nodist_perftoolsincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_perftoolsinclude_HEADERS)'; test -n "$(perftoolsincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(perftoolsincludedir)'; $(am__uninstall_files_from_dir) +install-perftoolsincludeHEADERS: $(perftoolsinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(perftoolsinclude_HEADERS)'; test -n "$(perftoolsincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(perftoolsincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(perftoolsincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(perftoolsincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(perftoolsincludedir)" || exit $$?; \ + done + +uninstall-perftoolsincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(perftoolsinclude_HEADERS)'; test -n "$(perftoolsincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(perftoolsincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: $(check_SCRIPTS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_SCRIPTS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +low_level_alloc_unittest.log: low_level_alloc_unittest$(EXEEXT) + @p='low_level_alloc_unittest$(EXEEXT)'; \ + b='low_level_alloc_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +atomicops_unittest.log: atomicops_unittest$(EXEEXT) + @p='atomicops_unittest$(EXEEXT)'; \ + b='atomicops_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stacktrace_unittest.log: stacktrace_unittest$(EXEEXT) + @p='stacktrace_unittest$(EXEEXT)'; \ + b='stacktrace_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_minimal_unittest.log: tcmalloc_minimal_unittest$(EXEEXT) + @p='tcmalloc_minimal_unittest$(EXEEXT)'; \ + b='tcmalloc_minimal_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcm_min_asserts_unittest.log: tcm_min_asserts_unittest$(EXEEXT) + @p='tcm_min_asserts_unittest$(EXEEXT)'; \ + b='tcm_min_asserts_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_minimal_large_unittest.log: tcmalloc_minimal_large_unittest$(EXEEXT) + @p='tcmalloc_minimal_large_unittest$(EXEEXT)'; \ + b='tcmalloc_minimal_large_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_minimal_large_heap_fragmentation_unittest.log: tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT) + @p='tcmalloc_minimal_large_heap_fragmentation_unittest$(EXEEXT)'; \ + b='tcmalloc_minimal_large_heap_fragmentation_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +maybe_threads_unittest.sh.log: maybe_threads_unittest.sh$(EXEEXT) + @p='maybe_threads_unittest.sh$(EXEEXT)'; \ + b='maybe_threads_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +addressmap_unittest.log: addressmap_unittest$(EXEEXT) + @p='addressmap_unittest$(EXEEXT)'; \ + b='addressmap_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +system_alloc_unittest.log: system_alloc_unittest$(EXEEXT) + @p='system_alloc_unittest$(EXEEXT)'; \ + b='system_alloc_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +packed_cache_test.log: packed_cache_test$(EXEEXT) + @p='packed_cache_test$(EXEEXT)'; \ + b='packed_cache_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +frag_unittest.log: frag_unittest$(EXEEXT) + @p='frag_unittest$(EXEEXT)'; \ + b='frag_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +markidle_unittest.log: markidle_unittest$(EXEEXT) + @p='markidle_unittest$(EXEEXT)'; \ + b='markidle_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +current_allocated_bytes_test.log: current_allocated_bytes_test$(EXEEXT) + @p='current_allocated_bytes_test$(EXEEXT)'; \ + b='current_allocated_bytes_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +malloc_hook_test.log: malloc_hook_test$(EXEEXT) + @p='malloc_hook_test$(EXEEXT)'; \ + b='malloc_hook_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +malloc_extension_test.log: malloc_extension_test$(EXEEXT) + @p='malloc_extension_test$(EXEEXT)'; \ + b='malloc_extension_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +malloc_extension_c_test.log: malloc_extension_c_test$(EXEEXT) + @p='malloc_extension_c_test$(EXEEXT)'; \ + b='malloc_extension_c_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +memalign_unittest.log: memalign_unittest$(EXEEXT) + @p='memalign_unittest$(EXEEXT)'; \ + b='memalign_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +page_heap_test.log: page_heap_test$(EXEEXT) + @p='page_heap_test$(EXEEXT)'; \ + b='page_heap_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pagemap_unittest.log: pagemap_unittest$(EXEEXT) + @p='pagemap_unittest$(EXEEXT)'; \ + b='pagemap_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +realloc_unittest.log: realloc_unittest$(EXEEXT) + @p='realloc_unittest$(EXEEXT)'; \ + b='realloc_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stack_trace_table_test.log: stack_trace_table_test$(EXEEXT) + @p='stack_trace_table_test$(EXEEXT)'; \ + b='stack_trace_table_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +thread_dealloc_unittest.log: thread_dealloc_unittest$(EXEEXT) + @p='thread_dealloc_unittest$(EXEEXT)'; \ + b='thread_dealloc_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_minimal_debug_unittest.log: tcmalloc_minimal_debug_unittest$(EXEEXT) + @p='tcmalloc_minimal_debug_unittest$(EXEEXT)'; \ + b='tcmalloc_minimal_debug_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +malloc_extension_debug_test.log: malloc_extension_debug_test$(EXEEXT) + @p='malloc_extension_debug_test$(EXEEXT)'; \ + b='malloc_extension_debug_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +memalign_debug_unittest.log: memalign_debug_unittest$(EXEEXT) + @p='memalign_debug_unittest$(EXEEXT)'; \ + b='memalign_debug_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +realloc_debug_unittest.log: realloc_debug_unittest$(EXEEXT) + @p='realloc_debug_unittest$(EXEEXT)'; \ + b='realloc_debug_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +debugallocation_test.sh.log: debugallocation_test.sh$(EXEEXT) + @p='debugallocation_test.sh$(EXEEXT)'; \ + b='debugallocation_test.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_unittest.sh.log: tcmalloc_unittest.sh$(EXEEXT) + @p='tcmalloc_unittest.sh$(EXEEXT)'; \ + b='tcmalloc_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcm_asserts_unittest.log: tcm_asserts_unittest$(EXEEXT) + @p='tcm_asserts_unittest$(EXEEXT)'; \ + b='tcm_asserts_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_both_unittest.log: tcmalloc_both_unittest$(EXEEXT) + @p='tcmalloc_both_unittest$(EXEEXT)'; \ + b='tcmalloc_both_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_large_unittest.log: tcmalloc_large_unittest$(EXEEXT) + @p='tcmalloc_large_unittest$(EXEEXT)'; \ + b='tcmalloc_large_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_large_heap_fragmentation_unittest.log: tcmalloc_large_heap_fragmentation_unittest$(EXEEXT) + @p='tcmalloc_large_heap_fragmentation_unittest$(EXEEXT)'; \ + b='tcmalloc_large_heap_fragmentation_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +raw_printer_test.log: raw_printer_test$(EXEEXT) + @p='raw_printer_test$(EXEEXT)'; \ + b='raw_printer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sampler_test.log: sampler_test$(EXEEXT) + @p='sampler_test$(EXEEXT)'; \ + b='sampler_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sampling_test.sh.log: sampling_test.sh$(EXEEXT) + @p='sampling_test.sh$(EXEEXT)'; \ + b='sampling_test.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap-profiler_unittest.sh.log: heap-profiler_unittest.sh$(EXEEXT) + @p='heap-profiler_unittest.sh$(EXEEXT)'; \ + b='heap-profiler_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +simple_compat_test.log: simple_compat_test$(EXEEXT) + @p='simple_compat_test$(EXEEXT)'; \ + b='simple_compat_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap-checker_unittest.sh.log: heap-checker_unittest.sh$(EXEEXT) + @p='heap-checker_unittest.sh$(EXEEXT)'; \ + b='heap-checker_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap-checker-death_unittest.sh.log: heap-checker-death_unittest.sh$(EXEEXT) + @p='heap-checker-death_unittest.sh$(EXEEXT)'; \ + b='heap-checker-death_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_debug_unittest.log: tcmalloc_debug_unittest$(EXEEXT) + @p='tcmalloc_debug_unittest$(EXEEXT)'; \ + b='tcmalloc_debug_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sampler_debug_test.log: sampler_debug_test$(EXEEXT) + @p='sampler_debug_test$(EXEEXT)'; \ + b='sampler_debug_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sampling_debug_test.sh.log: sampling_debug_test.sh$(EXEEXT) + @p='sampling_debug_test.sh$(EXEEXT)'; \ + b='sampling_debug_test.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap-profiler_debug_unittest.sh.log: heap-profiler_debug_unittest.sh$(EXEEXT) + @p='heap-profiler_debug_unittest.sh$(EXEEXT)'; \ + b='heap-profiler_debug_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +heap-checker_debug_unittest.sh.log: heap-checker_debug_unittest.sh$(EXEEXT) + @p='heap-checker_debug_unittest.sh$(EXEEXT)'; \ + b='heap-checker_debug_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +getpc_test.log: getpc_test$(EXEEXT) + @p='getpc_test$(EXEEXT)'; \ + b='getpc_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +profiledata_unittest.log: profiledata_unittest$(EXEEXT) + @p='profiledata_unittest$(EXEEXT)'; \ + b='profiledata_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +profile_handler_unittest.log: profile_handler_unittest$(EXEEXT) + @p='profile_handler_unittest$(EXEEXT)'; \ + b='profile_handler_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +profiler_unittest.sh.log: profiler_unittest.sh$(EXEEXT) + @p='profiler_unittest.sh$(EXEEXT)'; \ + b='profiler_unittest.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcmalloc_and_profiler_unittest.log: tcmalloc_and_profiler_unittest$(EXEEXT) + @p='tcmalloc_and_profiler_unittest$(EXEEXT)'; \ + b='tcmalloc_and_profiler_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) \ + $(HEADERS) all-local +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(googleincludedir)" "$(DESTDIR)$(perftoolsincludedir)" "$(DESTDIR)$(perftoolsincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f benchmark/$(DEPDIR)/$(am__dirstamp) + -rm -f benchmark/$(am__dirstamp) + -rm -f src/$(DEPDIR)/$(am__dirstamp) + -rm -f src/$(am__dirstamp) + -rm -f src/base/$(DEPDIR)/$(am__dirstamp) + -rm -f src/base/$(am__dirstamp) + -rm -f src/tests/$(DEPDIR)/$(am__dirstamp) + -rm -f src/tests/$(am__dirstamp) + -rm -f src/windows/$(DEPDIR)/$(am__dirstamp) + -rm -f src/windows/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f benchmark/$(DEPDIR)/binary_trees-binary_trees.Po + -rm -f benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/run_benchmark.Plo + -rm -f src/$(DEPDIR)/fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po + -rm -f src/$(DEPDIR)/maybe_threads.Plo + -rm -f src/$(DEPDIR)/profile-handler.Plo + -rm -f src/$(DEPDIR)/profiledata.Plo + -rm -f src/$(DEPDIR)/profiler.Plo + -rm -f src/$(DEPDIR)/stacktrace.Plo + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po + -rm -f src/base/$(DEPDIR)/atomicops-internals-x86.Plo + -rm -f src/base/$(DEPDIR)/dynamic_annotations.Plo + -rm -f src/base/$(DEPDIR)/elf_mem_image.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/logging.Plo + -rm -f src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po + -rm -f src/base/$(DEPDIR)/spinlock.Plo + -rm -f src/base/$(DEPDIR)/spinlock_internal.Plo + -rm -f src/base/$(DEPDIR)/sysinfo.Plo + -rm -f src/base/$(DEPDIR)/thread_lister.Plo + -rm -f src/base/$(DEPDIR)/vdso_support.Plo + -rm -f src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po + -rm -f src/tests/$(DEPDIR)/atomicops_unittest.Po + -rm -f src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po + -rm -f src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po + -rm -f src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po + -rm -f src/tests/$(DEPDIR)/getpc_test.Po + -rm -f src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po + -rm -f src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po + -rm -f src/tests/$(DEPDIR)/markidle_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po + -rm -f src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po + -rm -f src/tests/$(DEPDIR)/memalign_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po + -rm -f src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po + -rm -f src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po + -rm -f src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiledata_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po + -rm -f src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po + -rm -f src/tests/$(DEPDIR)/sampler_test-sampler_test.Po + -rm -f src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po + -rm -f src/tests/$(DEPDIR)/sampling_test-sampling_test.Po + -rm -f src/tests/$(DEPDIR)/simple_compat_test.Po + -rm -f src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po + -rm -f src/tests/$(DEPDIR)/stacktrace_unittest.Po + -rm -f src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po + -rm -f src/windows/$(DEPDIR)/addressmap_unittest-port.Po + -rm -f src/windows/$(DEPDIR)/ia32_modrm_map.Plo + -rm -f src/windows/$(DEPDIR)/ia32_opcode_map.Plo + -rm -f src/windows/$(DEPDIR)/mini_disassembler.Plo + -rm -f src/windows/$(DEPDIR)/patch_functions.Plo + -rm -f src/windows/$(DEPDIR)/port.Plo + -rm -f src/windows/$(DEPDIR)/preamble_patcher.Plo + -rm -f src/windows/$(DEPDIR)/preamble_patcher_with_stub.Plo + -rm -f src/windows/$(DEPDIR)/system-alloc.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA install-googleincludeHEADERS \ + install-man install-nodist_perftoolsincludeHEADERS \ + install-perftoolsincludeHEADERS install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-binSCRIPTS \ + install-exec-local install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f benchmark/$(DEPDIR)/binary_trees-binary_trees.Po + -rm -f benchmark/$(DEPDIR)/binary_trees_shared-binary_trees.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench_shared-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/malloc_bench_shared_full-malloc_bench.Po + -rm -f benchmark/$(DEPDIR)/run_benchmark.Plo + -rm -f src/$(DEPDIR)/fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-emergency_malloc_for_stacktrace.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-emergency_malloc_for_stacktrace.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-fake_stacktrace_scope.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profile-table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-heap-profiler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-memory_region_map.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-raw_printer.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker-bcad.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-heap-checker.Plo + -rm -f src/$(DEPDIR)/libtcmalloc_with_asserts_la-tcmalloc.Plo + -rm -f src/$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po + -rm -f src/$(DEPDIR)/maybe_threads.Plo + -rm -f src/$(DEPDIR)/profile-handler.Plo + -rm -f src/$(DEPDIR)/profiledata.Plo + -rm -f src/$(DEPDIR)/profiler.Plo + -rm -f src/$(DEPDIR)/stacktrace.Plo + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-central_freelist.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-common.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-internal_logging.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_extension.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-malloc_hook.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-memfs_malloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-page_heap.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-sampler.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-span.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-stack_trace_table.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-static_vars.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-symbolize.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-system-alloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc.Po + -rm -f src/$(DEPDIR)/tcm_min_asserts_unittest-thread_cache.Po + -rm -f src/base/$(DEPDIR)/atomicops-internals-x86.Plo + -rm -f src/base/$(DEPDIR)/dynamic_annotations.Plo + -rm -f src/base/$(DEPDIR)/elf_mem_image.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_internal_with_asserts_la-low_level_alloc.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/libtcmalloc_with_asserts_la-linuxthreads.Plo + -rm -f src/base/$(DEPDIR)/logging.Plo + -rm -f src/base/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po + -rm -f src/base/$(DEPDIR)/spinlock.Plo + -rm -f src/base/$(DEPDIR)/spinlock_internal.Plo + -rm -f src/base/$(DEPDIR)/sysinfo.Plo + -rm -f src/base/$(DEPDIR)/thread_lister.Plo + -rm -f src/base/$(DEPDIR)/vdso_support.Plo + -rm -f src/tests/$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po + -rm -f src/tests/$(DEPDIR)/atomicops_unittest.Po + -rm -f src/tests/$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po + -rm -f src/tests/$(DEPDIR)/debugallocation_test-debugallocation_test.Po + -rm -f src/tests/$(DEPDIR)/frag_unittest-frag_unittest.Po + -rm -f src/tests/$(DEPDIR)/getpc_test.Po + -rm -f src/tests/$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po + -rm -f src/tests/$(DEPDIR)/malloc_hook_test-testutil.Po + -rm -f src/tests/$(DEPDIR)/markidle_unittest-markidle_unittest.Po + -rm -f src/tests/$(DEPDIR)/markidle_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po + -rm -f src/tests/$(DEPDIR)/memalign_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/memalign_unittest-memalign_unittest.Po + -rm -f src/tests/$(DEPDIR)/memalign_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/packed_cache_test-packed-cache_test.Po + -rm -f src/tests/$(DEPDIR)/page_heap_test-page_heap_test.Po + -rm -f src/tests/$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po + -rm -f src/tests/$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiledata_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler1_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler1_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler2_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler2_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler3_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler3_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/profiler4_unittest-profiler_unittest.Po + -rm -f src/tests/$(DEPDIR)/profiler4_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/raw_printer_test-raw_printer_test.Po + -rm -f src/tests/$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/realloc_unittest-realloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/sampler_debug_test-sampler_test.Po + -rm -f src/tests/$(DEPDIR)/sampler_test-sampler_test.Po + -rm -f src/tests/$(DEPDIR)/sampling_debug_test-sampling_test.Po + -rm -f src/tests/$(DEPDIR)/sampling_test-sampling_test.Po + -rm -f src/tests/$(DEPDIR)/simple_compat_test.Po + -rm -f src/tests/$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po + -rm -f src/tests/$(DEPDIR)/stacktrace_unittest.Po + -rm -f src/tests/$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_asserts_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_asserts_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcm_min_asserts_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcm_min_asserts_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_both_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_large_heap_fragmentation_unittest-large_heap_fragmentation_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po + -rm -f src/tests/$(DEPDIR)/tcmalloc_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/thread_dealloc_unittest-testutil.Po + -rm -f src/tests/$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po + -rm -f src/windows/$(DEPDIR)/addressmap_unittest-port.Po + -rm -f src/windows/$(DEPDIR)/ia32_modrm_map.Plo + -rm -f src/windows/$(DEPDIR)/ia32_opcode_map.Plo + -rm -f src/windows/$(DEPDIR)/mini_disassembler.Plo + -rm -f src/windows/$(DEPDIR)/patch_functions.Plo + -rm -f src/windows/$(DEPDIR)/port.Plo + -rm -f src/windows/$(DEPDIR)/preamble_patcher.Plo + -rm -f src/windows/$(DEPDIR)/preamble_patcher_with_stub.Plo + -rm -f src/windows/$(DEPDIR)/system-alloc.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-dist_docDATA uninstall-googleincludeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man \ + uninstall-nodist_perftoolsincludeHEADERS \ + uninstall-perftoolsincludeHEADERS uninstall-pkgconfigDATA + +uninstall-man: uninstall-man1 + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles am--refresh \ + check check-TESTS check-am clean clean-binPROGRAMS \ + clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscope \ + cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ + dist-zip dist-zstd 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-binPROGRAMS install-binSCRIPTS install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-local \ + install-googleincludeHEADERS install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-man install-man1 \ + install-nodist_perftoolsincludeHEADERS install-pdf \ + install-pdf-am install-perftoolsincludeHEADERS \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-dist_docDATA uninstall-googleincludeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \ + uninstall-nodist_perftoolsincludeHEADERS \ + uninstall-perftoolsincludeHEADERS uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +@WITH_STACK_TRACE_TRUE@pprof-symbolize : $(top_srcdir)/src/pprof +@WITH_STACK_TRACE_TRUE@ cp -p $(top_srcdir)/src/pprof $@ +@WITH_STACK_TRACE_TRUE@pprof_unittest: $(top_srcdir)/src/pprof +@WITH_STACK_TRACE_TRUE@ $(top_srcdir)/src/pprof -test +# This script preloads libtcmalloc, and calls two other binaries as well +# TODO(csilvers): replace by 'if ! cmp $^ $@ >/dev/null 2>&; then ...; fi' +@ENABLE_STATIC_FALSE@@MINGW_FALSE@maybe_threads_unittest.sh$(EXEEXT): $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) \ +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(LIBTCMALLOC_MINIMAL) \ +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ low_level_alloc_unittest +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ rm -f $@ +@ENABLE_STATIC_FALSE@@MINGW_FALSE@ cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@ +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \ +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ debugallocation_test +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ rm -f $@ +@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@ cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest.sh$(EXEEXT): $(top_srcdir)/$(tcmalloc_unittest_sh_SOURCES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_unittest +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ cp -p $(top_srcdir)/$(tcmalloc_unittest_sh_SOURCES) $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@ +@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@ +@WITH_HEAP_PROFILER_TRUE@heap-profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \ +@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest +@WITH_HEAP_PROFILER_TRUE@ rm -f $@ +@WITH_HEAP_PROFILER_TRUE@ cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@ +@WITH_HEAP_CHECKER_TRUE@heap-checker_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \ +@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest +@WITH_HEAP_CHECKER_TRUE@ rm -f $@ +@WITH_HEAP_CHECKER_TRUE@ cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@ +@WITH_HEAP_CHECKER_TRUE@heap-checker-death_unittest.sh$(EXEEXT): $(heap_checker_death_unittest_sh_SOURCES) \ +@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest +@WITH_HEAP_CHECKER_TRUE@ rm -f $@ +@WITH_HEAP_CHECKER_TRUE@ cp -p $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap-profiler_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ heap-profiler_debug_unittest +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ rm -f $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap-checker_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ heap-checker_debug_unittest +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ rm -f $@ +@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@ +@WITH_CPU_PROFILER_TRUE@profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(profiler_unittest_sh_SOURCES) \ +@WITH_CPU_PROFILER_TRUE@ profiler1_unittest profiler2_unittest \ +@WITH_CPU_PROFILER_TRUE@ profiler3_unittest profiler4_unittest +@WITH_CPU_PROFILER_TRUE@ rm -f $@ +@WITH_CPU_PROFILER_TRUE@ cp -p $(top_srcdir)/$(profiler_unittest_sh_SOURCES) $@ + +# Do the weakening on some exported libtcmalloc symbols. +install-exec-local: all-local +all-local: $(LIBS_TO_WEAKEN) + for la in $(LIBS_TO_WEAKEN); do lib=".libs/`basename $$la .la`.a"; [ ! -f "$$lib" ] || $(WEAKEN) "$$lib"; done + +rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec + @cd packages && ./rpm.sh ${PACKAGE} ${VERSION} + +deb: dist-gzip packages/deb.sh packages/deb/* + @cd packages && ./deb.sh ${PACKAGE} ${VERSION} + +# I get the description and URL lines from the rpm spec. I use sed to +# try to rewrite exec_prefix, libdir, and includedir in terms of +# prefix, if possible. +libtcmalloc.pc: Makefile packages/rpm/rpm.spec + echo 'prefix=$(prefix)' > "$@".tmp + echo 'exec_prefix='`echo '$(exec_prefix)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp + echo 'libdir='`echo '$(libdir)' | sed 's@^$(exec_prefix)@$${exec_prefix}@'` >> "$@".tmp + echo 'includedir='`echo '$(includedir)' | sed 's@^$(prefix)@$${prefix}@'` >> "$@".tmp + echo '' >> "$@".tmp + echo 'Name: $(PACKAGE)' >> "$@".tmp + echo 'Version: $(VERSION)' >> "$@".tmp + -grep '^Summary:' $(top_srcdir)/packages/rpm/rpm.spec | sed s/^Summary:/Description:/ | head -n1 >> "$@".tmp + -grep '^URL: ' $(top_srcdir)/packages/rpm/rpm.spec >> "$@".tmp + echo 'Requires:' >> "$@".tmp + echo 'Libs: -L$${libdir} -ltcmalloc' >> "$@".tmp + echo 'Libs.private: $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)' >> "$@".tmp + echo 'Cflags: -I$${includedir}' >> "$@".tmp + mv -f "$@".tmp "$@" + +# The other versions are mostly the same. +libtcmalloc_minimal.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal/ > "$@" + +libtcmalloc_debug.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_debug/ > "$@" + +libtcmalloc_minimal_debug.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-ltcmalloc_minimal_debug/ > "$@" + +libprofiler.pc: libtcmalloc.pc + cat libtcmalloc.pc | sed s/-ltcmalloc/-lprofiler/ > "$@" + +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck + +@GENERATE_CHANGELOG_RULES@ + +# Windows wants write permission to .vcxproj files and maybe even sln files. +dist-hook: dist-ChangeLog + 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/trunk/3rdparty/gperftools-2-fit/NEWS b/trunk/3rdparty/gperftools-2-fit/NEWS new file mode 100644 index 000000000..44095ecf9 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/NEWS @@ -0,0 +1,1193 @@ +== 2 March 2021 == +gperftools 2.9.1 is out! + +Minor fixes landed since previous release: + +* OSX builds new prefer backtrace() and have somewhat working heap + sampling. + +* Incorrect assertion failure was fixed that crashed tcmalloc if + assertions were on and sized delete was used. More details in github + issue #1254. + +== 21 February 2021 == +gperftools 2.9 is out! + +Few more changes landed compared to rc: + +* Venkatesh Srinivas has contributed thread-safety annotations + support. + +* couple more unit test bugs that caused tcmalloc_unittest to fail on + recent clang has been fixed. + +* usage of unsupportable linux_syscall_support.h has been removed from + few places. Building with --disable-heap-checker now completely + avoids it. Expect complete death of this header in next major + release. + +== 14 February 2021 == +gperftools 2.9rc is out! + +Here are notable changes: + +* Jarno Rajahalme has contributed fix for crashing bug in syscalls + support for aarch64. + +* User SSE4 has contributed basic support for Elbrus 2000 architecture + (!) + +* Venkatesh Srinivas has contributed cleanup to atomic ops. + +* Đoàn Trần Công Danh has fixed cpu profiler compilation on musl. + +* there is now better backtracing support for aarch64 and + riscv. x86-64 with frame pointers now also defaults to this new + "generic" frame pointer backtracer. + +* emergency malloc is now enabled by default. Fixes hang on musl when + libgcc backtracer is enabled. + +* bunch of legacy config tests has been removed + +== 20 December 2020 == +gperftools 2.8.1 is out! + +Here are notable changes: + +* previous release contained change to release memory without page + heap lock, but this change had at least one bug that caused to + crashes and corruption when running under aggressive decommit mode + (this is not default). While we check for other bugs, this feature + was reverted. See github issue #1204 and issue #1227. + +* stack traces depth captured by gperftools is now up to 254 levels + deep. Thanks to Kerrick Staley for this small but useful tweak. + +* Levon Ter-Grigoryan has contributed small fix for compiler warning. + +* Grant Henke has contributed updated detection of program counter + register for OS X on arm64. + +* Tim Gates has contributed small typo fix. + +* Steve Langasek has contributed basic build fixes for riscv64 (!). + +* Isaac Hier and okhowang have contributed premiliminary port of build + infrastructure to cmake. This works, but it is very premiliminary. + Autotools-based build is the only officially supported build for + now. + +== 6 July 2020 == +gperftools 2.8 is out! + +Here are notable changes: + +* ProfilerGetStackTrace is now officially supported API for + libprofiler. Contributed by Kirill Müller. + +* Build failures on mingw were fixed. This fixed issue #1108. + +* Build failure of page_heap_test on MSVC was fixed. + +* Ryan Macnak contributed fix for compiling linux syscall support on + i386 and recent GCCs. This fixed issue #1076. + +* test failures caused by new gcc 10 optimizations were fixed. Same + change also fixed tests on clang. + +== 8 Mar 2020 == +gperftools 2.8rc is out! + +Here are notable changes: + +* building code now requires c++11 or later. Bundled MSVC project was + converted to Visual Studio 2015. + +* User obones contributed fix for windows x64 TLS callbacks. This + fixed leak of thread caches on thread exists in 64-bit windows. + +* releasing memory back to kernel is now made with page heap lock + dropped. + +* HoluWu contributed fix for correct malloc patching on debug builds + on windows. This configuration previously crashed. + +* Romain Geissler contributed fix for tls access during early tls + initialization on dlopen. + +* large allocation reports are now silenced by default. Since not all + programs want their stderr polluted by those messages. Contributed + by Junhao Li. + +* HolyWu contributed improvements to MSVC project files. Notably, + there is now project for "overriding" version of tcmalloc. + +* MS-specific _recalloc is now correctly zeroing only malloced + part. This fix was contributed by HolyWu. + +* Brian Silverman contributed correctness fix to sampler_test. + +* Gabriel Marin ported few fixes from chromium's fork. As part of + those fixes, we reduced number of static initializers (forbidden in + chromium). Also we now syscalls via syscall function instead of + reimplementing direct way to make syscalls on each platform. + +* Brian Silverman fixed flakiness in page heap test. + +* There is now configure flag to skip installing perl pprof, since + external golang pprof is much superior. --disable-deprecated-pprof + is the flag. + +* Fabric Fontaine contributed fixes to drop use of nonstandard + __off64_t type. + +* Fabrice Fontaine contributed build fix to check for presence of + nonstandard __sbrk functions. It is only used by mmap hooks code and + (rightfully) not available on musl. + +* Fabrice Fontaine contributed build fix around mmap64 macro and + function conflict in same cases. + +* there is now configure time option to enable aggressive decommit by + default. Contributed by Laurent + Stacul. --enable-aggressive-decommit-by-default is the flag. + +* Tulio Magno Quites Machado Filho contributed build fixes for ppc + around ucontext access. + +* User pkubaj contributed couple build fixes for FreeBSD/ppc. + +* configure now always assumes we have mmap. This fixes configure + failures on some linux guests inside virtualbox. This fixed issue + #1008. + +* User shipujin contributed syscall support fixes for mips64 (big and + little endian). + +* Henrik Edin contributed configurable support for wide range of + malloc page sizes. 4K, 8K, 16K, 32K, 64K, 128K and 256K are now + supported via existing --with-tcmalloc-pagesize flag to configure. + +* Jon Kohler added overheads fields to per-size-class textual + stats. Stats that are available via + MallocExtension::instance()->GetStats(). + +* tcmalloc can now avoid fallback from memfs to default sys + allocator. TCMALLOC_MEMFS_DISABLE_FALLBACK switches this on. This + was contributed by Jon Kohler. + +* Ilya Leoshkevich fixed mmap syscall support on s390. + +* Todd Lipcon contributed small build warning fix. + +* User prehistoricpenguin contributed misc source file mode fixes (we + still had few few c++ files marked executable). + +* User invalid_ms_user contributed fix for typo. + +* Jakub Wilk contributed typos fixes. + +== 29 Apr 2018 == +gperftools 2.7 is out! + +Few people contributed minor, but important fixes since rc. + +Changes: + +* bug in span stats printing introduced by new scalable page heap + change was fixed. + +* Christoph Müllner has contributed couple warnings fixes and initial + support for aarch64_ilp32 architecture. + +* Ben Dang contributed documentation fix for heap checker. + +* Fabrice Fontaine contributed fixed for linking benchmarks with + --disable-static. + +* Holy Wu has added sized deallocation unit tests. + +* Holy Wu has enabled support of sized deallocation (c++14) on recent + MSVC. + +* Holy Wu has fixed MSVC build in WIN32_OVERRIDE_ALLOCATORS mode. This + closed issue #716. + +* Holy Wu has contributed cleanup of config.h used on windows. + +* Mao Huang has contributed couple simple tcmalloc changes from + chromium code base. Making our tcmalloc forks a tiny bit closer. + +* issue #946 that caused compilation failures on some Linux clang + installations has been fixed. Much thanks to github user htuch for + helping to diagnose issue and proposing a fix. + +* Tulio Magno Quites Machado Filho has contributed build-time fix for + PPC (for problem introduced in one of commits since RC). + +== 18 Mar 2018 == +gperftools 2.7rc is out! + +Changes: + +* Most notable change in this release is that very large allocations + (>1MiB) are now handled be O(log n) implementation. This is + contributed by Todd Lipcon based on earlier work by Aliaksei + Kandratsenka and James Golick. Special thanks to Alexey Serbin for + contributing OSX fix for that commit. + +* detection of sized deallocation support is improved. Which should + fix another set of issues building on OSX. Much thanks to Alexey + Serbin for reporting the issue, suggesting a fix and verifying it. + +* Todd Lipcon made a change to extend page heaps freelists to 1 MiB + (up from 1MiB - 8KiB). This may help a little for some workloads. + +* Ishan Arora contributed typo fix to docs + +== 9 Dec 2017 == +gperftools 2.6.3 is out! + +Just two fixes were made in this release: + +* Stephan Zuercher has contributed a build fix for some recent XCode + versions. See issue #942 for more details. + +* assertion failure on some windows builds introduced by 2.6.2 was + fixed. Thanks to github user nkeemik for reporting it and testing + fix. See issue #944 for more details. + +== 30 Nov 2017 == +gperftools 2.6.2 is out! + +Most notable change is recently added support for C++17 over-aligned +allocation operators contributed by Andrey Semashev. I've extended his +implemention to have roughly same performance as malloc/new. This +release also has native support for C11 aligned_alloc. + +Rest is mostly bug fixes: + +* Jianbo Yang has contributed a fix for potentially severe data race + introduced by malloc fast-path work in gperftools 2.6. This race + could cause occasional violation of total thread cache size + constraint. See issue #929 for more details. + +* Correct behavior in out-of-memory condition in fast-path cases was + restored. This was another bug introduced by fast-path optimization + in gperftools 2.6 which caused operator new to silently return NULL + instead of doing correct C++ OOM handling (calling new_handler and + throwing bad_alloc). + +* Khem Raj has contributed couple build fixes for newer glibcs (ucontext_t vs + struct ucontext and loff_t definition) + +* Piotr Sikora has contributed build fix for OSX (not building unwind + benchmark). This was issue #910 (thanks to Yuriy Solovyov for + reporting it). + +* Dorin Lazăr has contributed fix for compiler warning + +* issue #912 (occasional deadlocking calling getenv too early on + windows) was fixed. Thanks to github user shangcangriluo for + reporting it. + +* Couple earlier lsan-related commits still causing occasional issues + linking on OSX has been reverted. See issue #901. + +* Volodimir Krylov has contributed GetProgramInvocationName for FreeBSD + +* changsu lee has contributed couple minor correctness fixes (missing + va_end() and missing free() call in rarely executed Symbolize path) + +* Andrew C. Morrow has contributed some more page heap stats. See issue + #935. + +* some cases of built-time warnings from various gcc/clang versions + about throw() declarations have been fixes. + +== 9 July 2017 == + +gperftools 2.6.1 is out! This is mostly bug-fixes release. + +* issue #901: build issue on OSX introduced in last-time commit in 2.6 + was fixed (contributed by Francis Ricci) + +* tcmalloc_minimal now works on 32-bit ABI of mips64. This is issue + #845. Much thanks to Adhemerval Zanella and github user mtone. + +* Romain Geissler contributed build fix for -std=c++17. This is pull + request #897. + +* As part of fixing issue #904, tcmalloc atfork handler is now + installed early. This should fix slight chance of hitting deadlocks + at fork in some cases. + +== 4 July 2017 == + +gperftools 2.6 is out! + +* Kim Gräsman contributed documentation update for HEAPPROFILESIGNAL + environment variable + +* KernelMaker contributed fix for population of min_object_size field + returned by MallocExtension::GetFreeListSizes + +* commit 8c3dc52fcfe0 "issue-654: [pprof] handle split text segments" + was reverted. Some OSX users reported issues with this commit. Given + our pprof implementation is strongly deprecated it is best to drop + recently introduced features rather than breaking it badly. + +* Francis Ricci contributed improvement for interaction with leak + sanitizer. + +== 22 May 2017 == + +gperftools 2.6rc4 is out! + +Dynamic sized delete is disabled by default again. There is no hope of +it working with eager dynamic symbols resolution (-z now linker +flag). More details in +https://bugzilla.redhat.com/show_bug.cgi?id=1452813 + +== 21 May 2017 == + +gperftools 2.6rc3 is out! + +gperftools compilation on older systems (e.g. rhel 5) was fixed. This +was originally reported in github issue #888. + +== 14 May 2017 == + +gperftools 2.6rc2 is out! + +Just 2 small fixes on top of 2.6rc. Particularly, Rajalakshmi +Srinivasaraghavan contributed build fix for ppc32. + +== 14 May 2017 == + +gperftools 2.6rc is out! + +Highlights of this release are performance work on malloc fast-path +and support for more modern visual studio runtimes, and deprecation of +bundled pprof. Another significant performance-affecting changes are +reverting central free list transfer batch size back to 32 and +disabling of aggressive decommit mode by default. + +Note, while we still ship perl implementation of pprof, everyone is +strongly advised to use golang reimplementation of pprof from +https://github.com/google/pprof. + +Here are notable changes in more details (and see ChangeLog for full +details): + +* a bunch of performance tweaks to tcmalloc fast-path were + merged. This speeds up critical path of tcmalloc by few tens of + %. Well tuned and allocation-heavy programs should see substantial + performance boost (should apply to all modern elf platforms). This + is based on Google-internal tcmalloc changes for fast-path (with + obvious exception of lacking per-cpu mode, of course). Original + changes were made by Aliaksei Kandratsenka. And Andrew Hunter, + Dmitry Vyukov and Sanjay Ghemawat contributed with reviews and + discussions. + +* Architectures with 48 bits address space (x86-64 and aarch64) now + use faster 2 level page map. This was ported from Google-internal + change by Sanjay Ghemawat. + +* Default value of TCMALLOC_TRANSFER_NUM_OBJ was returned back to + 32. Larger values have been found to hurt certain programs (but help + some other benchmarks). Value can still be tweaked at run time via + environment variable. + +* tcmalloc aggressive decommit mode is now disabled by default + again. It was found to degrade performance of certain tensorflow + benchmarks. Users who prefer smaller heap over small performance win + can still set environment variable TCMALLOC_AGGRESSIVE_DECOMMIT=t. + +* runtime switchable sized delete support has be fixed and re-enabled + (on GNU/Linux). Programs that use C++ 14 or later that use sized + delete can again be sped up by setting environment variable + TCMALLOC_ENABLE_SIZED_DELETE=t. Support for enabling sized + deallication support at compile-time is still present, of course. + +* tcmalloc now explicitly avoids use of MADV_FREE on Linux, unless + TCMALLOC_USE_MADV_FREE is defined at compile time. This is because + performance impact of MADV_FREE is not well known. Original issue + #780 raised by Mathias Stearn. + +* issue #786 with occasional deadlocks in stack trace capturing via + libunwind was fixed. It was originally reported as Ceph issue: + http://tracker.ceph.com/issues/13522 + +* ChangeLog is now automatically generated from git log. Old ChangeLog + is now ChangeLog.old. + +* tcmalloc now provides implementation of nallocx. Function was + originally introduced by jemalloc and can be used to return real + allocation size given allocation request size. This is ported from + Google-internal tcmalloc change contributed by Dmitry Vyukov. + +* issue #843 which made tcmalloc crash when used with erlang runtime + was fixed. + +* issue #839 which caused tcmalloc's aggressive decommit mode to + degrade performance in some corner cases was fixed. + +* Bryan Chan contributed support for 31-bit s390. + +* Brian Silverman contributed compilation fix for 32-bit ARMs + +* Issue #817 that was causing tcmalloc to fail on windows 10 and + later, as well as on recent msvc was fixed. We now patch _free_base + as well. + +* a bunch of minor documentaion/typos fixes by: Mike Gaffney + , iivlev , savefromgoogle + , John McDole + , zmertens , Kirill Müller + , Eugene , Ola Olsson + , Mostyn Bramley-Moore + +* Tulio Magno Quites Machado Filho has contributed removal of + deprecated glibc malloc hooks. + +* Issue #827 that caused intercepting malloc on osx 10.12 to fail was + fixed, by copying fix made by Mike Hommey to jemalloc. Much thanks + to Koichi Shiraishi and David Ribeiro Alves for reporting it and + testing fix. + +* Aman Gupta and Kenton Varda contributed minor fixes to pprof (but + note again that pprof is deprecated) + +* Ryan Macnak contributed compilation fix for aarch64 + +* Francis Ricci has fixed unaligned memory access in debug allocator + +* TCMALLOC_PAGE_FENCE_NEVER_RECLAIM now actually works thanks to + contribution by Andrew Morrow. + +== 12 Mar 2016 == + +gperftools 2.5 is out! + +Just single bugfix was merged after rc2. Which was fix for issue #777. + +== 5 Mar 2016 == + +gperftools 2.5rc2 is out! + +New release contains just few commits on top of first release +candidate. One of them is build fix for Visual Studio. Another +significant change is that dynamic sized delete is now disabled by +default. It turned out that IFUNC relocations are not supporting our +advanced use case on all platforms and in all cases. + +== 21 Feb 2016 == + +gperftools 2.5rc is out! + +Here are major changes since 2.4: + +* we've moved to github! + +* Bryan Chan has contributed s390x support + +* stacktrace capturing via libgcc's _Unwind_Backtrace was implemented + (for architectures with missing or broken libunwind). + +* "emergency malloc" was implemented. Which unbreaks recursive calls + to malloc/free from stacktrace capturing functions (such us glib'c + backtrace() or libunwind on arm). It is enabled by + --enable-emergency-malloc configure flag or by default on arm when + --enable-stacktrace-via-backtrace is given. It is another fix for a + number common issues people had on platforms with missing or broken + libunwind. + +* C++14 sized-deallocation is now supported (on gcc 5 and recent + clangs). It is off by default and can be enabled at configure time + via --enable-sized-delete. On GNU/Linux it can also be enabled at + run-time by either TCMALLOC_ENABLE_SIZED_DELETE environment variable + or by defining tcmalloc_sized_delete_enabled function which should + return 1 to enable it. + +* we've lowered default value of transfer batch size to 512. Previous + value (bumped up in 2.1) was too high and caused performance + regression for some users. 512 should still give us performance + boost for workloads that need higher transfer batch size while not + penalizing other workloads too much. + +* Brian Silverman's patch finally stopped arming profiling timer + unless profiling is started. + +* Andrew Morrow has contributed support for obtaining cache size of the + current thread and softer idling (for use in MongoDB). + +* we've implemented few minor performance improvements, particularly + on malloc fast-path. + +A number of smaller fixes were made. Many of them were contributed: + +* issue that caused spurious profiler_unittest.sh failures was fixed. + +* Jonathan Lambrechts contributed improved callgrind format support to + pprof. + +* Matt Cross contributed better support for debug symbols in separate + files to pprof. + +* Matt Cross contributed support for printing collapsed stack frame + from pprof aimed at producing flame graphs. + +* Angus Gratton has contributed documentation fix mentioning that on + windows only tcmalloc_minimal is supported. + +* Anton Samokhvalov has made tcmalloc use mi_force_{un,}lock on OSX + instead of pthread_atfork. Which apparently fixes forking + issues tcmalloc had on OSX. + +* Milton Chiang has contributed support for building 32-bit gperftools + on arm8. + +* Patrick LoPresti has contributed support for specifying alternative + profiling signal via CPUPROFILE_TIMER_SIGNAL environment variable. + +* Paolo Bonzini has contributed support configuring filename for + sending malloc tracing output via TCMALLOC_TRACE_FILE environment + variable. + +* user spotrh has enabled use of futex on arm. + +* user mitchblank has contributed better declaration for arg-less + profiler functions. + +* Tom Conerly contributed proper freeing of memory allocated in + HeapProfileTable::FillOrderedProfile on error paths. + +* user fdeweerdt has contributed curl arguments handling fix in pprof + +* Frederik Mellbin fixed tcmalloc's idea of mangled new and delete + symbols on windows x64 + +* Dair Grant has contributed cacheline alignment for ThreadCache + objects + +* Fredrik Mellbin has contributed updated windows/config.h for Visual + Studio 2015 and other windows fixes. + +* we're not linking libpthread to libtcmalloc_minimal anymore. Instead + libtcmalloc_minimal links to pthread symbols weakly. As a result + single-threaded programs remain single-threaded when linking to or + preloading libtcmalloc_minimal.so. + +* Boris Sazonov has contributed mips compilation fix and printf misue + in pprof. + +* Adhemerval Zanella has contributed alignment fixes for statically + allocated variables. + +* Jens Rosenboom has contributed fixes for heap-profiler_unittest.sh + +* gshirishfree has contributed better description for GetStats method. + +* cyshi has contributed spinlock pause fix. + +* Chris Mayo has contributed --docdir argument support for configure. + +* Duncan Sands has contributed fix for function aliases. + +* Simon Que contributed better include for malloc_hook_c.h + +* user wmamrak contributed struct timespec fix for Visual Studio 2015. + +* user ssubotin contributed typo in PrintAvailability code. + + +== 10 Jan 2015 == + +gperftools 2.4 is out! The code is exactly same as 2.4rc. + +== 28 Dec 2014 == + +gperftools 2.4rc is out! + +Here are changes since 2.3: + +* enabled aggressive decommit option by default. It was found to + significantly improve memory fragmentation with negligible impact on + performance. (Thanks to investigation work performed by Adhemerval + Zanella) + +* added ./configure flags for tcmalloc pagesize and tcmalloc + allocation alignment. Larger page sizes have been reported to + improve performance occasionally. (Patch by Raphael Moreira Zinsly) + +* sped-up hot-path of malloc/free. By about 5% on static library and + about 10% on shared library. Mainly due to more efficient checking + of malloc hooks. + +* improved stacktrace capturing in cpu profiler (due to issue found by + Arun Sharma). As part of that issue pprof's handling of cpu profiles + was also improved. + +== 7 Dec 2014 == + +gperftools 2.3 is out! + +Here are changes since 2.3rc: + +* (issue 658) correctly close socketpair fds on failure (patch by glider) + +* libunwind integration can be disabled at configure time (patch by + Raphael Moreira Zinsly) + +* libunwind integration is disabled by default for ppc64 (patch by + Raphael Moreira Zinsly) + +* libunwind integration is force-disabled for OSX. It was not used by + default anyways. Fixes compilation issue I saw. + +== 2 Nov 2014 == + +gperftools 2.3rc is out! + +Most small improvements in this release were made to pprof tool. + +New experimental Linux-only (for now) cpu profiling mode is a notable +big improvement. + +Here are notable changes since 2.2.1: + +* (issue-631) fixed debugallocation miscompilation on mmap-less + platforms (courtesy of user iamxujian) + +* (issue-630) reference to wrong PROFILE (vs. correct CPUPROFILE) + environment variable was fixed (courtesy of WenSheng He) + +* pprof now has option to display stack traces in output for heap + checker (courtesy of Michael Pasieka) + +* (issue-636) pprof web command now works on mingw + +* (issue-635) pprof now handles library paths that contain spaces + (courtesy of user mich...@sebesbefut.com) + +* (issue-637) pprof now has an option to not strip template arguments + (patch by jiakai) + +* (issue-644) possible out-of-bounds access in GetenvBeforeMain was + fixed (thanks to user abyss.7) + +* (issue-641) pprof now has an option --show_addresses (thanks to user + yurivict). New option prints instruction address in addition to + function name in stack traces + +* (issue-646) pprof now works around some issues of addr2line + reportedly when DWARF v4 format is used (patch by Adam McNeeney) + +* (issue-645) heap profiler exit message now includes remaining memory + allocated info (patch by user yurivict) + +* pprof code that finds location of /proc//maps in cpu profile + files is now fixed (patch by Ricardo M. Correia) + +* (issue-654) pprof now handles "split text segments" feature of + Chromium for Android. (patch by simonb) + +* (issue-655) potential deadlock on windows caused by early call to + getenv in malloc initialization code was fixed (bug reported and fix + proposed by user zndmitry) + +* incorrect detection of arm 6zk instruction set support + (-mcpu=arm1176jzf-s) was fixed. (Reported by pedronavf on old + issue-493) + +* new cpu profiling mode on Linux is now implemented. It sets up + separate profiling timers for separate threads. Which improves + accuracy of profiling on Linux a lot. It is off by default. And is + enabled if both librt.f is loaded and CPUPROFILE_PER_THREAD_TIMERS + environment variable is set. But note that all threads need to be + registered via ProfilerRegisterThread. + +== 21 Jun 2014 == + +gperftools 2.2.1 is out! + +Here's list of fixes: + +* issue-626 was closed. Which fixes initialization statically linked + tcmalloc. + +* issue 628 was closed. It adds missing header file into source + tarball. This fixes for compilation on PPC Linux. + +== 3 May 2014 == + +gperftools 2.2 is out! + +Here are notable changes since 2.2rc: + +* issue 620 (crash on windows when c runtime dll is reloaded) was + fixed + +== 19 Apr 2014 == + +gperftools 2.2rc is out! + +Here are notable changes since 2.1: + +* a number of fixes for a number compilers and platforms. Notably + Visual Studio 2013, recent mingw with c++ threads and some OSX + fixes. + +* we now have mips and mips64 support! (courtesy of Jovan Zelincevic, + Jean Lee, user xiaoyur347 and others) + +* we now have aarch64 (aka arm64) support! (contributed by Riku + Voipio) + +* there's now support for ppc64-le (by Raphael Moreira Zinsly and + Adhemerval Zanella) + +* there's now some support of uclibc (contributed by user xiaoyur347) + +* google/ headers will now give you deprecation warning. They are + deprecated since 2.0 + +* there's now new api: tc_malloc_skip_new_handler (ported from chromium + fork) + +* issue-557: added support for dumping heap profile via signal (by + Jean Lee) + +* issue-567: Petr Hosek contributed SysAllocator support for windows + +* Joonsoo Kim contributed several speedups for central freelist code + +* TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES environment variable now works + +* configure scripts are now using AM_MAINTAINER_MODE. It'll only + affect folks who modify source from .tar.gz and want automake to + automatically rebuild Makefile-s. See automake documentation for + that. + +* issue-586: detect main executable even if PIE is active (based on + patch by user themastermind1). Notably, it fixes profiler use with + ruby. + +* there is now support for switching backtrace capturing method at + runtime (via TCMALLOC_STACKTRACE_METHOD and + TCMALLOC_STACKTRACE_METHOD_VERBOSE environment variables) + +* there is new backtrace capturing method using -finstrument-functions + prologues contributed by user xiaoyur347 + +* few cases of crashes/deadlocks in profiler were addressed. See + (famous) issue-66, issue-547 and issue-579. + +* issue-464 (memory corruption in debugalloc's realloc after + memallign) is now fixed + +* tcmalloc is now able to release memory back to OS on windows + (issue-489). The code was ported from chromium fork (by a number of + authors). + +* Together with issue-489 we ported chromium's "aggressive decommit" + mode. In this mode (settable via malloc extension and via + environment variable TCMALLOC_AGGRESSIVE_DECOMMIT), free pages are + returned back to OS immediately. + +* MallocExtension::instance() is now faster (based on patch by + Adhemerval Zanella) + +* issue-610 (hangs on windows in multibyte locales) is now fixed + +The following people helped with ideas or patches (based on git log, +some contributions purely in bugtracker might be missing): Andrew +C. Morrow, yurivict, Wang YanQing, Thomas Klausner, +davide.italiano@10gen.com, Dai MIKURUBE, Joon-Sung Um, Jovan +Zelincevic, Jean Lee, Petr Hosek, Ben Avison, drussel, Joonsoo Kim, +Hannes Weisbach, xiaoyur347, Riku Voipio, Adhemerval Zanella, Raphael +Moreira Zinsly + +== 30 July 2013 == + +gperftools 2.1 is out! + +Just few fixes where merged after rc. Most notably: + +* Some fixes for debug allocation on POWER/Linux + +== 20 July 2013 == + +gperftools 2.1rc is out! + +As a result of more than a year of contributions we're ready for 2.1 +release. + +But before making that step I'd like to create RC and make sure people +have chance to test it. + +Here are notable changes since 2.0: + +* fixes for building on newer platforms. Notably, there's now initial + support for x32 ABI (--enable-minimal only at this time)) + +* new getNumericProperty stats for cache sizes + +* added HEAP_PROFILER_TIME_INTERVAL variable (see documentation) + +* added environment variable to control heap size (TCMALLOC_HEAP_LIMIT_MB) + +* added environment variable to disable release of memory back to OS + (TCMALLOC_DISABLE_MEMORY_RELEASE) + +* cpu profiler can now be switched on and off by sending it a signal + (specified in CPUPROFILESIGNAL) + +* (issue 491) fixed race-ful spinlock wake-ups + +* (issue 496) added some support for fork-ing of process that is using + tcmalloc + +* (issue 368) improved memory fragmentation when large chunks of + memory are allocated/freed + +== 03 February 2012 == + +I've just released gperftools 2.0 + +The `google-perftools` project has been renamed to `gperftools`. I +(csilvers) am stepping down as maintainer, to be replaced by +David Chappelle. Welcome to the team, David! David has been an +an active contributor to perftools in the past -- in fact, he's the +only person other than me that already has commit status. I am +pleased to have him take over as maintainer. + +I have both renamed the project (the Google Code site renamed a few +weeks ago), and bumped the major version number up to 2, to reflect +the new community ownership of the project. Almost all the +[http://gperftools.googlecode.com/svn/tags/gperftools-2.0/ChangeLog changes] +are related to the renaming. + +The main functional change from google-perftools 1.10 is that +I've renamed the `google/` include-directory to be `gperftools/` +instead. New code should `#include `/etc. +(Most users of perftools don't need any perftools-specific includes at +all, so this is mostly directed to "power users.") I've kept the old +names around as forwarding headers to the new, so `#include +` will continue to work. + +(The other functional change which I snuck in is getting rid of some +bash-isms in one of the unittest driver scripts, so it could run on +Solaris.) + +Note that some internal names still contain the text `google`, such as +the `google_malloc` internal linker section. I think that's a +trickier transition, and can happen in a future release (if at all). + + +=== 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://gperftools.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 +`gperftools`. In the coming weeks, I'll be stepping down as +maintainer for the perftools project, and as part of that Google is +relinquishing ownership of the project; it will now be entirely +community run. The name change reflects that shift. The 'g' in +'gperftools' stands for 'great'. :-) + +=== 23 December 2011 === + +I've just released perftools 1.9.1 + +I missed including a file in the tarball, that is needed to compile on +ARM. If you are not compiling on ARM, or have successfully compiled +perftools 1.9, there is no need to upgrade. + + +=== 22 December 2011 === + +I've just released perftools 1.9 + +This change has a slew of improvements, from better ARM and freebsd +support, to improved performance by moving some code outside of locks, +to better pprof reporting of code with overloaded functions. + +The full list of changes is in the +[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.9/ChangeLog ChangeLog]. + + +=== 26 August 2011 === + +I've just released perftools 1.8.3 + +The star-crossed 1.8 series continues; in 1.8.1, I had accidentally +removed some code that was needed for FreeBSD. (Without this code +many apps would crash at startup.) This release re-adds that code. +If you are not on FreeBSD, or are using FreeBSD with perftools 1.8 or +earlier, there is no need to upgrade. + +=== 11 August 2011 === + +I've just released perftools 1.8.2 + +I was incorrectly calculating the patch-level in the configuration +step, meaning the TC_VERSION_PATCH #define in tcmalloc.h was wrong. +Since the testing framework checks for this, it was failing. Now it +should work again. This time, I was careful to re-run my tests after +upping the version number. :-) + +If you don't care about the TC_VERSION_PATCH #define, there's no +reason to upgrae. + +=== 26 July 2011 === + +I've just released perftools 1.8.1 + +I was missing an #include that caused the build to break under some +compilers, especially newer gcc's, that wanted it. This only affects +people who build from source, so only the .tar.gz file is updated from +perftools 1.8. If you didn't have any problems compiling perftools +1.8, there's no reason to upgrade. + +=== 15 July 2011 === + +I've just released perftools 1.8 + +Of the many changes in this release, a good number pertain to porting. +I've revamped OS X support to use the malloc-zone framework; it should +now Just Work to link in tcmalloc, without needing +`DYLD_FORCE_FLAT_NAMESPACE` or the like. (This is a pretty major +change, so please feel free to report feedback at +google-perftools@googlegroups.com.) 64-bit Windows support is also +improved, as is ARM support, and the hooks are in place to improve +FreeBSD support as well. + +On the other hand, I'm seeing hanging tests on Cygwin. I see the same +hanging even with (the old) perftools 1.7, so I'm guessing this is +either a problem specific to my Cygwin installation, or nobody is +trying to use perftools under Cygwin. If you can reproduce the +problem, and even better have a solution, you can report it at +google-perftools@googlegroups.com. + +Internal changes include several performance and space-saving tweaks. +One is user-visible (but in "stealth mode", and otherwise +undocumented): you can compile with `-DTCMALLOC_SMALL_BUT_SLOW`. In +this mode, tcmalloc will use less memory overhead, at the cost of +running (likely not noticeably) slower. + +There are many other changes as well, too numerous to recount here, +but present in the +[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.8/ChangeLog ChangeLog]. + + +=== 7 February 2011 === + +Thanks to endlessr..., who +[http://code.google.com/p/google-perftools/issues/detail?id=307 identified] +why some tests were failing under MSVC 10 in release mode. It does not look +like these failures point toward any problem with tcmalloc itself; rather, the +problem is with the test, which made some assumptions that broke under the +some aggressive optimizations used in MSVC 10. I'll fix the test, but in +the meantime, feel free to use perftools even when compiled under MSVC +10. + +=== 4 February 2011 === + +I've just released perftools 1.7 + +I apologize for the delay since the last release; so many great new +patches and bugfixes kept coming in (and are still coming in; I also +apologize to those folks who have to slip until the next release). I +picked this arbitrary time to make a cut. + +Among the many new features in this release is a multi-megabyte +reduction in the amount of tcmalloc overhead uder x86_64, improved +performance in the case of contention, and many many bugfixes, +especially architecture-specific bugfixes. See the +[http://google-perftools.googlecode.com/svn/tags/google-perftools-1.7/ChangeLog ChangeLog] +for full details. + +One architecture-specific change of note is added comments in the +[http://google-perftools.googlecode.com/svn/tags/perftools-1.7/README README] +for using tcmalloc under OS X. I'm trying to get my head around the +exact behavior of the OS X linker, and hope to have more improvements +for the next release, but I hope these notes help folks who have been +having trouble with tcmalloc on OS X. + +*Windows users*: I've heard reports that some unittests fail on +Windows when compiled with MSVC 10 in Release mode. All tests pass in +Debug mode. I've not heard of any problems with earlier versions of +MSVC. I don't know if this is a problem with the runtime patching (so +the static patching discussed in README_windows.txt will still work), +a problem with perftools more generally, or a bug in MSVC 10. Anyone +with windows expertise that can debug this, I'd be glad to hear from! + + +=== 5 August 2010 === + +I've just released perftools 1.6 + +This version also has a large number of minor changes, including +support for `malloc_usable_size()` as a glibc-compatible alias to +`malloc_size()`, the addition of SVG-based output to `pprof`, and +experimental support for tcmalloc large pages, which may speed up +tcmalloc at the cost of greater memory use. To use tcmalloc large +pages, see the +[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/INSTALL +INSTALL file]; for all changes, see the +[http://google-perftools.googlecode.com/svn/tags/perftools-1.6/ChangeLog +ChangeLog]. + +OS X NOTE: improvements in the profiler unittest have turned up an OS +X issue: in multithreaded programs, it seems that OS X often delivers +the profiling signal (from sigitimer()) to the main thread, even when +it's sleeping, rather than spawned threads that are doing actual work. +If anyone knows details of how OS X handles SIGPROF events (from +setitimer) in threaded programs, and has insight into this problem, +please send mail to google-perftools@googlegroups.com. + +To see if you're affected by this, look for profiling time that pprof +attributes to `___semwait_signal`. This is work being done in other +threads, that is being attributed to sleeping-time in the main thread. + + +=== 20 January 2010 === + +I've just released perftools 1.5 + +This version has a slew of changes, leading to somewhat faster +performance and improvements in portability. It adds features like +`ITIMER_REAL` support to the cpu profiler, and `tc_set_new_mode` to +mimic the windows function of the same name. Full details are in the +[http://google-perftools.googlecode.com/svn/tags/perftools-1.5/ChangeLog +ChangeLog]. + + +=== 11 September 2009 === + +I've just released perftools 1.4 + +The major change this release is the addition of a debugging malloc +library! If you link with `libtcmalloc_debug.so` instead of +`libtcmalloc.so` (and likewise for the `minimal` variants) you'll get +a debugging malloc, which will catch double-frees, writes to freed +data, `free`/`delete` and `delete`/`delete[]` mismatches, and even +(optionally) writes past the end of an allocated block. + +We plan to do more with this library in the future, including +supporting it on Windows, and adding the ability to use the debugging +library with your default malloc in addition to using it with +tcmalloc. + +There are also the usual complement of bug fixes, documented in the +ChangeLog, and a few minor user-tunable knobs added to components like +the system allocator. + + +=== 9 June 2009 === + +I've just released perftools 1.3 + +Like 1.2, this has a variety of bug fixes, especially related to the +Windows build. One of my bugfixes is to undo the weird `ld -r` fix to +`.a` files that I introduced in perftools 1.2: it caused problems on +too many platforms. I've reverted back to normal `.a` files. To work +around the original problem that prompted the `ld -r` fix, I now +provide `libtcmalloc_and_profiler.a`, for folks who want to link in +both. + +The most interesting API change is that I now not only override +`malloc`/`free`/etc, I also expose them via a unique set of symbols: +`tc_malloc`/`tc_free`/etc. This enables clients to write their own +memory wrappers that use tcmalloc: +{{{ + void* malloc(size_t size) { void* r = tc_malloc(size); Log(r); return r; } +}}} + + +=== 17 April 2009 === + +I've just released perftools 1.2. + +This is mostly a bugfix release. The major change is internal: I have +a new system for creating packages, which allows me to create 64-bit +packages. (I still don't do that for perftools, because there is +still no great 64-bit solution, with libunwind still giving problems +and --disable-frame-pointers not practical in every environment.) + +Another interesting change involves Windows: a +[http://code.google.com/p/google-perftools/issues/detail?id=126 new +patch] allows users to choose to override malloc/free/etc on Windows +rather than patching, as is done now. This can be used to create +custom CRTs. + +My fix for this +[http://groups.google.com/group/google-perftools/browse_thread/thread/1ff9b50043090d9d/a59210c4206f2060?lnk=gst&q=dynamic#a59210c4206f2060 +bug involving static linking] ended up being to make libtcmalloc.a and +libperftools.a a big .o file, rather than a true `ar` archive. This +should not yield any problems in practice -- in fact, it should be +better, since the heap profiler, leak checker, and cpu profiler will +now all work even with the static libraries -- but if you find it +does, please file a bug report. + +Finally, the profile_handler_unittest provided in the perftools +testsuite (new in this release) is failing on FreeBSD. The end-to-end +test that uses the profile-handler is passing, so I suspect the +problem may be with the test, not the perftools code itself. However, +I do not know enough about how itimers work on FreeBSD to be able to +debug it. If you can figure it out, please let me know! + +=== 11 March 2009 === + +I've just released perftools 1.1! + +It has many changes since perftools 1.0 including + + * Faster performance due to dynamically sized thread caches + * Better heap-sampling for more realistic profiles + * Improved support on Windows (MSVC 7.1 and cygwin) + * Better stacktraces in linux (using VDSO) + * Many bug fixes and feature requests + +Note: if you use the CPU-profiler with applications that fork without +doing an exec right afterwards, please see the README. Recent testing +has shown that profiles are unreliable in that case. The problem has +existed since the first release of perftools. We expect to have a fix +for perftools 1.2. For more details, see +[http://code.google.com/p/google-perftools/issues/detail?id=105 issue 105]. + +Everyone who uses perftools 1.0 is encouraged to upgrade to perftools +1.1. If you see any problems with the new release, please file a bug +report at http://code.google.com/p/google-perftools/issues/list. + +Enjoy! diff --git a/trunk/3rdparty/gperftools-2-fit/README b/trunk/3rdparty/gperftools-2-fit/README new file mode 100644 index 000000000..2e604dd7c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/README @@ -0,0 +1,279 @@ +gperftools +---------- +(originally Google Performance Tools) + +The fastest malloc we’ve seen; works particularly well with threads +and STL. Also: thread-friendly heap-checker, heap-profiler, and +cpu-profiler. + + +OVERVIEW +--------- + +gperftools is a collection of a high-performance multi-threaded +malloc() implementation, plus some pretty nifty performance analysis +tools. + +gperftools is distributed under the terms of the BSD License. Join our +mailing list at gperftools@googlegroups.com for updates: +https://groups.google.com/forum/#!forum/gperftools + +gperftools was original home for pprof program. But do note that +original pprof (which is still included with gperftools) is now +deprecated in favor of golang version at https://github.com/google/pprof + + +TCMALLOC +-------- +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.txt for instructions on +using tcmalloc on Windows. + +when compiling. gcc makes some optimizations assuming it is using its +own, built-in malloc; that assumption obviously isn't true with +tcmalloc. In practice, we haven't seen any problems with this, but +the expected risk is highest for users who register their own malloc +hooks with tcmalloc (using gperftools/malloc_hook.h). The risk is +lowest for folks who use tcmalloc_minimal (or, of course, who pass in +the above flags :-) ). + + +HEAP PROFILER +------------- +See docs/heapprofile.html for information about how to use tcmalloc's +heap profiler and analyze its output. + +As a quick-start, do the following after installing this package: + +1) Link your executable with -ltcmalloc +2) Run your executable with the HEAPPROFILE environment var set: + $ HEAPPROFILE=/tmp/heapprof [binary args] +3) Run pprof to analyze the heap usage + $ pprof /tmp/heapprof.0045.heap # run 'ls' to see options + $ pprof --gv /tmp/heapprof.0045.heap + +You can also use LD_PRELOAD to heap-profile an executable that you +didn't compile. + +There are other environment variables, besides HEAPPROFILE, you can +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 +------------ +See docs/heap_checker.html for information about how to use tcmalloc's +heap checker. + +In order to catch all heap leaks, tcmalloc must be linked *last* into +your executable. The heap checker may mischaracterize some memory +accesses in libraries listed after it on the link line. For instance, +it may report these libraries as leaking memory when they're not. +(See the source code for more details.) + +Here's a quick-start for how to use: + +As a quick-start, do the following after installing this package: + +1) Link your executable with -ltcmalloc +2) Run your executable with the HEAPCHECK environment var set: + $ HEAPCHECK=1 [binary args] + +Other values for HEAPCHECK: normal (equivalent to "1"), strict, draconian + +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. + + +CPU PROFILER +------------ +See docs/cpuprofile.html for information about how to use the CPU +profiler and analyze its output. + +As a quick-start, do the following after installing this package: + +1) Link your executable with -lprofiler +2) Run your executable with the CPUPROFILE environment var set: + $ CPUPROFILE=/tmp/prof.out [binary args] +3) Run pprof to analyze the CPU usage + $ pprof /tmp/prof.out # -pg-like text output + $ pprof --gv /tmp/prof.out # really cool graphical output + +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. + +NOTE: CPU profiling doesn't work after fork (unless you immediately + do an exec()-like call afterwards). Furthermore, if you do + fork, and the child calls exit(), it may corrupt the profile + data. You can use _exit() to work around this. We hope to have + a fix for both problems in the next release of perftools + (hopefully perftools 1.2). + + +EVERYTHING IN ONE +----------------- +If you want the CPU profiler, heap profiler, and heap leak-checker to +all be available for your application, you can do: + gcc -o myapp ... -lprofiler -ltcmalloc + +However, if you have a reason to use the static versions of the +library, this two-library linking won't work: + gcc -o myapp ... /usr/lib/libprofiler.a /usr/lib/libtcmalloc.a # errors! + +Instead, use the special libtcmalloc_and_profiler library, which we +make for just this purpose: + gcc -o myapp ... /usr/lib/libtcmalloc_and_profiler.a + + +CONFIGURATION OPTIONS +--------------------- +For advanced users, there are several flags you can pass to +'./configure' that tweak tcmalloc performance. (These are in addition +to the environment variables you can set at runtime to affect +tcmalloc, described below.) See the INSTALL file for details. + + +ENVIRONMENT VARIABLES +--------------------- +The cpu profiler, heap checker, and heap profiler will lie dormant, +using no memory or CPU, until you turn them on. (Thus, there's no +harm in linking -lprofiler into every application, and also -ltcmalloc +assuming you're ok using the non-libc malloc library.) + +The easiest way to turn them on is by setting the appropriate +environment variables. We have several variables that let you +enable/disable features as well as tweak parameters. + +Here are some of the most important variables: + +HEAPPROFILE=
 -- turns on heap profiling and dumps data using this prefix
+HEAPCHECK=  -- turns on heap checking with strictness 'type'
+CPUPROFILE= -- turns on cpu profiling and dumps data to this file.
+PROFILESELECTED=1 -- if set, cpu-profiler will only profile regions of code
+                     surrounded with ProfilerEnable()/ProfilerDisable().
+CPUPROFILE_FREQUENCY=x-- how many interrupts/second the cpu-profiler samples.
+
+PERFTOOLS_VERBOSE= -- the higher level, the more messages malloc emits
+MALLOCSTATS=    -- prints memory-use stats at program-exit
+
+For a full list of variables, see the documentation pages:
+   docs/cpuprofile.html
+   docs/heapprofile.html
+   docs/heap_checker.html
+
+
+COMPILING ON NON-LINUX SYSTEMS
+------------------------------
+
+Perftools was developed and tested on x86 Linux systems, and it works
+in its full generality only on those systems.  However, we've
+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.txt for details on the Windows port.
+
+
+PERFORMANCE
+-----------
+
+If you're interested in some third-party comparisons of tcmalloc to
+other malloc libraries, here are a few web pages that have been
+brought to our attention.  The first discusses the effect of using
+various malloc libraries on OpenLDAP.  The second compares tcmalloc to
+win32's malloc.
+  http://www.highlandsun.com/hyc/malloc/
+  http://gaiacrtn.free.fr/articles/win32perftools.html
+
+It's possible to build tcmalloc in a way that trades off faster
+performance (particularly for deletes) at the cost of more memory
+fragmentation (that is, more unusable memory on your system).  See the
+INSTALL file for details.
+
+
+OLD SYSTEM ISSUES
+-----------------
+
+When compiling perftools on some old systems, like RedHat 8, you may
+get an error like this:
+    ___tls_get_addr: symbol not found
+
+This means that you have a system where some parts are updated enough
+to support Thread Local Storage, but others are not.  The perftools
+configure script can't always detect this kind of case, leading to
+that error.  To fix it, just comment out (or delete) the line
+   #define HAVE_TLS 1
+in your config.h file before building.
+
+
+64-BIT ISSUES
+-------------
+
+There are two issues that can cause program hangs or crashes on x86_64
+64-bit systems, which use the libunwind library to get stack-traces.
+Neither issue should affect the core tcmalloc library; they both
+affect the perftools tools such as cpu-profiler, heap-checker, and
+heap-profiler.
+
+1) Some libc's -- at least glibc 2.4 on x86_64 -- have a bug where the
+libc function dl_iterate_phdr() acquires its locks in the wrong
+order.  This bug should not affect tcmalloc, but may cause occasional
+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 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
+cause a segfault.  I'll explain the problem first, and then some
+workarounds.
+
+Note that this only affects the cpu-profiler, which is a
+gperftools feature you must turn on manually by setting the
+CPUPROFILE environment variable.  If you do not turn on cpu-profiling,
+you shouldn't see any crashes due to perftools.
+
+The gory details: The underlying problem is in the backtrace()
+function, which is a built-in function in libc.
+Backtracing is fairly straightforward in the normal case, but can run
+into problems when having to backtrace across a signal frame.
+Unfortunately, the cpu-profiler uses signals in order to register a
+profiling event, so every backtrace that the profiler does crosses a
+signal frame.
+
+In our experience, the only time there is trouble is when the signal
+fires in the middle of pthread_mutex_lock.  pthread_mutex_lock is
+called quite a bit from system libraries, particularly at program
+startup and when creating a new thread.
+
+The solution: The dwarf debugging format has support for 'cfi
+annotations', which make it easy to recognize a signal frame.  Some OS
+distributions, such as Fedora and gentoo 2007.0, already have added
+cfi annotations to their libc.  A future version of libunwind should
+recognize these annotations; these systems should not see any
+crashes.
+
+Workarounds: If you see problems with crashes when running the
+cpu-profiler, consider inserting ProfilerStart()/ProfilerStop() into
+your code, rather than setting CPUPROFILE.  This will profile only
+those sections of the codebase.  Though we haven't done much testing,
+in theory this should reduce the chance of crashes by limiting the
+signal generation to only a small part of the codebase.  Ideally, you
+would not use ProfilerStart()/ProfilerStop() around code that spawns
+new threads, or is otherwise likely to cause a call to
+pthread_mutex_lock!
+
+---
+17 May 2011
diff --git a/trunk/3rdparty/gperftools-2-fit/README_windows.txt b/trunk/3rdparty/gperftools-2-fit/README_windows.txt
new file mode 100644
index 000000000..7bba12201
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/README_windows.txt
@@ -0,0 +1,120 @@
+--- COMPILING
+
+This project has begun being ported to Windows, only tcmalloc_minimal
+is supported at this time.  A working solution file exists in this
+directory:
+    gperftools.sln
+
+You can load this solution file into VC++ 7.1 (Visual Studio 2003) or
+later -- in the latter case, it will automatically convert the files
+to the latest format for you.
+
+When you build the solution, it will create a number of unittests,
+which you can run by hand (or, more easily, under the Visual Studio
+debugger) to make sure everything is working properly on your system.
+The binaries will end up in a directory called "debug" or "release" in
+the top-level directory (next to the .sln file).  It will also create
+two binaries, nm-pdb and addr2line-pdb, which you should install in
+the same directory you install the 'pprof' perl script.
+
+I don't know very much about how to install DLLs on Windows, so you'll
+have to figure out that part for yourself.  If you choose to just
+re-use the existing .sln, make sure you set the IncludeDir's
+appropriately!  Look at the properties for libtcmalloc_minimal.dll.
+
+Note that these systems are set to build in Debug mode by default.
+You may want to change them to Release mode.
+
+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.  To use the dll, you need to add the following to
+the linker line of your executable:
+   "libtcmalloc_minimal.lib" /INCLUDE:"__tcmalloc" 
+
+Here is how to accomplish this in Visual Studio 2005 (VC8):
+
+1) Have your executable depend on the tcmalloc library by selecting
+   "Project Dependencies..." from the "Project" menu.  Your executable
+   should depend on "libtcmalloc_minimal".
+
+2) Have your executable depend on a tcmalloc symbol -- this is
+   necessary so the linker doesn't "optimize out" the libtcmalloc
+   dependency -- by right-clicking on your executable's project (in
+   the solution explorer), selecting Properties from the pull-down
+   menu, then selecting "Configuration Properties" -> "Linker" ->
+   "Input".  Then, in the "Force Symbol References" field, enter the
+   text "__tcmalloc" (without the quotes).  Be sure to do this for both
+   debug and release modes!
+
+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.  You do not need to depend on the
+tcmalloc symbol in this case (that is, you don't need to do either
+step 1 or step 2 from above).
+
+An alternative to all the above is to statically link your application
+with libc, and then replace its malloc with tcmalloc.  This allows you
+to just build and link your program normally; the tcmalloc support
+comes in a post-processing step.  This is more reliable than the above
+technique (which depends on run-time patching, which is inherently
+fragile), though more work to set up.  For details, see
+   https://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
+
+
+--- THE HEAP-PROFILER
+
+The heap-profiler has had a preliminary port to Windows but does not
+build on Windows by default.  It has not been well tested, and
+probably does not work at all when Frame Pointer Optimization (FPO) is
+enabled -- that is, in release mode.  The other features of perftools,
+such as the cpu-profiler and leak-checker, have not yet been ported to
+Windows at all.
+
+
+--- WIN64
+
+The function-patcher has to disassemble code, and is very
+x86-specific.  However, the rest of perftools should work fine for
+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
+
+NOTE FOR WIN2K USERS: According to reports
+(http://code.google.com/p/gperftools/issues/detail?id=127)
+the stack-tracing necessary for the heap-profiler does not work on
+Win2K.  The best workaround is, if you are building on a Win2k system
+is to add "/D NO_TCMALLOC_SAMPLES=" to your build, to turn off the
+stack-tracing.  You will not be able to use the heap-profiler if you
+do this.
+
+NOTE ON _MSIZE and _RECALLOC: The tcmalloc version of _msize returns
+the size of the region tcmalloc allocated for you -- which is at least
+as many bytes you asked for, but may be more.  (btw, these *are* bytes
+you own, even if you didn't ask for all of them, so it's correct code
+to access all of them if you want.)  Unfortunately, the Windows CRT
+_recalloc() routine assumes that _msize returns exactly as many bytes
+as were requested.  As a result, _recalloc() may not zero out new
+bytes correctly.  IT'S SAFEST NOT TO USE _RECALLOC WITH TCMALLOC.
+_recalloc() is a tricky routine to use in any case (it's not safe to
+use with realloc, for instance).
+
+
+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
+problems, please post to the google-perftools Google Group, or report
+them on the gperftools Google Code site:
+   http://groups.google.com/group/google-perftools
+   http://code.google.com/p/gperftools/issues/list
+
+-- craig
+
+Last modified: 2 February 2012
diff --git a/trunk/3rdparty/gperftools-2-fit/TODO b/trunk/3rdparty/gperftools-2-fit/TODO
new file mode 100644
index 000000000..550f7e09b
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/TODO
@@ -0,0 +1,47 @@
+HEAP PROFILER
+
+1) Fix heap profiling under all STLs
+   * Find out how to force non-glibc STL libraries to call new() and
+     delete() for every allocation / deallocation.
+   * Make heap profiler ignore STL-internal allocations for those
+     libraries under which we cannot profile accurately, so we only
+     see object-level leaks.
+2) Remove dependency on tcmalloc?
+3) Port to non-linux O/Ses (right now code uses /proc for library info)
+4) Port to non-x86 architectures (locking code in spinlock is x86-specific)
+5) Port to C?
+6) Figure out how to get setenv() to work properly before main() in
+   shared libaries, and get rid of the profile-naming hack once we
+   do.  (See HeapProfiler::Init().)
+
+
+HEAP CHECKER
+
+1) Remove requirement that the heap-checker must be linked last into
+   an application (hard! -- it needs its global constructor to run
+   first)
+
+TCMALLOC
+
+1) Implement mallinfo/mallopt
+2) Have tcmalloc work correctly when libpthread is not linked in
+   (currently working for glibc, could use other libc's too)
+3) Return memory to the system when requirements drop
+4) Explore coloring allocated objects to avoid cache conflicts
+5) Explore biasing reclamation to larger addresses
+6) Add contention stats to a synchronization.cc (can do spinlocks,
+   but threads? -- may have to provide our own thread implementation)
+
+CPU PROFILER
+
+1) Figure out how to get setenv() to work properly before main() in
+   shared libaries(), and get rid of the profile-naming hack once we
+   do.  (See Profiler::GetUniquePathFromEnv().)
+2) Resolve crashing problems on x86_64 (see README)
+
+STACKTRACE
+
+1) Remove dependency on linux/x86
+
+---
+11 March 2008
diff --git a/trunk/3rdparty/gperftools-2-fit/aclocal.m4 b/trunk/3rdparty/gperftools-2-fit/aclocal.m4
new file mode 100644
index 000000000..fe9a3c629
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/aclocal.m4
@@ -0,0 +1,1181 @@
+# generated automatically by aclocal 1.16.3 -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.16'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.16.3], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.16.3])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  AS_CASE([$CONFIG_FILES],
+          [*\'*], [eval set x "$CONFIG_FILES"],
+          [*], [set x $CONFIG_FILES])
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`AS_DIRNAME(["$am_mf"])`
+    am_filepart=`AS_BASENAME(["$am_mf"])`
+    AM_RUN_LOG([cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles]) || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE="gmake" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).])
+  fi
+  AS_UNSET([am_dirpart])
+  AS_UNSET([am_filepart])
+  AS_UNSET([am_mf])
+  AS_UNSET([am_rc])
+  rm -f conftest-deps.mk
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# 
+# 
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES([CC])],
+		  [m4_define([AC_PROG_CC],
+			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES([CXX])],
+		  [m4_define([AC_PROG_CXX],
+			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES([OBJC])],
+		  [m4_define([AC_PROG_OBJC],
+			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+		  [_AM_DEPENDENCIES([OBJCXX])],
+		  [m4_define([AC_PROG_OBJCXX],
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: 
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: .
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+      am_maintainer_other[ make rules and dependencies not useful
+      (and sometimes confusing) to the casual installer])],
+    [USE_MAINTAINER_MODE=$enableval],
+    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+      ['0:this is the am__doit target'],
+      [AS_CASE([$s],
+          [BSD], [am__include='.include' am__quote='"'],
+          [am__include='include' am__quote=''])])
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar /dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/ac_have_attribute.m4])
+m4_include([m4/acx_nanosleep.m4])
+m4_include([m4/acx_pthread.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_generate_changelog.m4])
+m4_include([m4/install_prefix.m4])
+m4_include([m4/libtool.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
+m4_include([m4/pc_from_ucontext.m4])
+m4_include([m4/program_invocation_name.m4])
diff --git a/trunk/3rdparty/gperftools-2-fit/benchmark/binary_trees.cc b/trunk/3rdparty/gperftools-2-fit/benchmark/binary_trees.cc
new file mode 100644
index 000000000..4c895b2e9
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/benchmark/binary_trees.cc
@@ -0,0 +1,108 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
+//
+// Copied from
+// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=gpp&id=2
+// and slightly modified (particularly by adding multi-threaded
+// operation to hit malloc harder).
+//
+// This version of binary trees is mostly new/delete benchmark
+//
+// NOTE: copyright of this code is unclear, but we only distribute
+// source.
+
+/* The Computer Language Benchmarks Game
+ * http://benchmarksgame.alioth.debian.org/
+ *
+ * Contributed by Jon Harrop
+ * Modified by Alex Mizrahi
+ * Adapted for gperftools and added threads by Aliaksei Kandratsenka
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct Node {
+  Node *l, *r;
+  int i;
+  Node(int i2) : l(0), r(0), i(i2) {}
+  Node(Node *l2, int i2, Node *r2) : l(l2), r(r2), i(i2) {}
+  ~Node() { delete l; delete r; }
+  int check() const {
+    if (l) {
+      return l->check() + i - r->check();
+    } else {
+      return i;
+    }
+  }
+};
+
+Node *make(int i, int d) {
+  if (d == 0) return new Node(i);
+  return new Node(make(2*i-1, d-1), i, make(2*i, d-1));
+}
+
+void run(int given_depth) {
+  int min_depth = 4,
+    max_depth = std::max(min_depth+2,
+			 given_depth),
+    stretch_depth = max_depth+1;
+
+  {
+    Node *c = make(0, stretch_depth);
+    std::cout << "stretch tree of depth " << stretch_depth << "\t "
+      << "check: " << c->check() << std::endl;
+    delete c;
+  }
+
+  Node *long_lived_tree=make(0, max_depth);
+
+  for (int d=min_depth; d<=max_depth; d+=2) {
+    int iterations = 1 << (max_depth - d + min_depth), c=0;
+    for (int i=1; i<=iterations; ++i) {
+      Node *a = make(i, d), *b = make(-i, d);
+      c += a->check() + b->check();
+      delete a;
+      delete b;
+    }
+    std::cout << (2*iterations) << "\t trees of depth " << d << "\t "
+	      << "check: " << c << std::endl;
+  }
+
+  std::cout << "long lived tree of depth " << max_depth << "\t "
+	    << "check: " << (long_lived_tree->check()) << "\n";
+
+  delete long_lived_tree;
+}
+
+static void *run_tramp(void *_a) {
+  intptr_t a = reinterpret_cast(_a);
+  run(a);
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  int given_depth = argc >= 2 ? atoi(argv[1]) : 20;
+  int thread_count = std::max(1, argc >= 3 ? atoi(argv[2]) : 1) - 1;
+  std::vector threads(thread_count);
+
+  for (int i = 0; i < thread_count; i++) {
+    int rv = pthread_create(&threads[i], NULL,
+                            run_tramp,
+                            reinterpret_cast(given_depth));
+    if (rv) {
+      errno = rv;
+      perror("pthread_create");
+    }
+  }
+  run_tramp(reinterpret_cast(given_depth));
+  for (int i = 0; i < thread_count; i++) {
+    pthread_join(threads[i], NULL);
+  }
+  return 0;
+}
diff --git a/trunk/3rdparty/gperftools-2-fit/benchmark/malloc_bench.cc b/trunk/3rdparty/gperftools-2-fit/benchmark/malloc_bench.cc
new file mode 100644
index 000000000..371b8c61a
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/benchmark/malloc_bench.cc
@@ -0,0 +1,293 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
+// 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.
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "run_benchmark.h"
+
+static void bench_fastpath_throughput(long iterations,
+                                      uintptr_t param)
+{
+  size_t sz = 32;
+  for (; iterations>0; iterations--) {
+    void *p = malloc(sz);
+    if (!p) {
+      abort();
+    }
+    free(p);
+    // this makes next iteration use different free list. So
+    // subsequent iterations may actually overlap in time.
+    sz = ((sz * 8191) & 511) + 16;
+  }
+}
+
+static void bench_fastpath_dependent(long iterations,
+                                     uintptr_t param)
+{
+  size_t sz = 32;
+  for (; iterations>0; iterations--) {
+    void *p = malloc(sz);
+    if (!p) {
+      abort();
+    }
+    free(p);
+    // this makes next iteration depend on current iteration. But this
+    // iteration's free may still overlap with next iteration's malloc
+    sz = ((sz | reinterpret_cast(p)) & 511) + 16;
+  }
+}
+
+static void bench_fastpath_simple(long iterations,
+                                  uintptr_t param)
+{
+  size_t sz = static_cast(param);
+  for (; iterations>0; iterations--) {
+    void *p = malloc(sz);
+    if (!p) {
+      abort();
+    }
+    free(p);
+    // next iteration will use same free list as this iteration. So it
+    // should be prevent next iterations malloc to go too far before
+    // free done. But using same size will make free "too fast" since
+    // we'll hit size class cache.
+  }
+}
+
+#ifdef __GNUC__
+#define HAVE_SIZED_FREE_OPTION
+
+extern "C" void tc_free_sized(void *ptr, size_t size) __attribute__((weak));
+extern "C" void *tc_memalign(size_t align, size_t size) __attribute__((weak));
+
+static bool is_sized_free_available(void)
+{
+  return tc_free_sized != NULL;
+}
+
+static bool is_memalign_available(void)
+{
+  return tc_memalign != NULL;
+}
+
+static void bench_fastpath_simple_sized(long iterations,
+                                        uintptr_t param)
+{
+  size_t sz = static_cast(param);
+  for (; iterations>0; iterations--) {
+    void *p = malloc(sz);
+    if (!p) {
+      abort();
+    }
+    tc_free_sized(p, sz);
+    // next iteration will use same free list as this iteration. So it
+    // should be prevent next iterations malloc to go too far before
+    // free done. But using same size will make free "too fast" since
+    // we'll hit size class cache.
+  }
+}
+
+static void bench_fastpath_memalign(long iterations,
+                                    uintptr_t param)
+{
+  size_t sz = static_cast(param);
+  for (; iterations>0; iterations--) {
+    void *p = tc_memalign(32, sz);
+    if (!p) {
+      abort();
+    }
+    free(p);
+    // next iteration will use same free list as this iteration. So it
+    // should be prevent next iterations malloc to go too far before
+    // free done. But using same size will make free "too fast" since
+    // we'll hit size class cache.
+  }
+}
+
+#endif // __GNUC__
+
+#define STACKSZ (1 << 16)
+
+static void bench_fastpath_stack(long iterations,
+                                 uintptr_t _param)
+{
+
+  void *stack[STACKSZ];
+  size_t sz = 64;
+  long param = static_cast(_param);
+  param &= STACKSZ - 1;
+  param = param ? param : 1;
+  for (; iterations>0; iterations -= param) {
+    for (long k = param-1; k >= 0; k--) {
+      void *p = malloc(sz);
+      if (!p) {
+        abort();
+      }
+      stack[k] = p;
+      // this makes next iteration depend on result of this iteration
+      sz = ((sz | reinterpret_cast(p)) & 511) + 16;
+    }
+    for (long k = 0; k < param; k++) {
+      free(stack[k]);
+    }
+  }
+}
+
+static void bench_fastpath_stack_simple(long iterations,
+                                        uintptr_t _param)
+{
+
+  void *stack[STACKSZ];
+  size_t sz = 128;
+  long param = static_cast(_param);
+  param &= STACKSZ - 1;
+  param = param ? param : 1;
+  for (; iterations>0; iterations -= param) {
+    for (long k = param-1; k >= 0; k--) {
+      void *p = malloc(sz);
+      if (!p) {
+        abort();
+      }
+      stack[k] = p;
+    }
+    for (long k = 0; k < param; k++) {
+      free(stack[k]);
+    }
+  }
+}
+
+static void bench_fastpath_rnd_dependent(long iterations,
+                                         uintptr_t _param)
+{
+  static const uintptr_t rnd_c = 1013904223;
+  static const uintptr_t rnd_a = 1664525;
+
+  void *ptrs[STACKSZ];
+  size_t sz = 128;
+  if ((_param & (_param - 1))) {
+    abort();
+  }
+  if (_param > STACKSZ) {
+    abort();
+  }
+  int param = static_cast(_param);
+
+  for (; iterations>0; iterations -= param) {
+    for (int k = param-1; k >= 0; k--) {
+      void *p = malloc(sz);
+      if (!p) {
+        abort();
+      }
+      ptrs[k] = p;
+      sz = ((sz | reinterpret_cast(p)) & 511) + 16;
+    }
+
+    // this will iterate through all objects in order that is
+    // unpredictable to processor's prefetchers
+    uint32_t rnd = 0;
+    uint32_t free_idx = 0;
+    do {
+      free(ptrs[free_idx]);
+      rnd = rnd * rnd_a + rnd_c;
+      free_idx = rnd & (param - 1);
+    } while (free_idx != 0);
+  }
+}
+
+static void *randomize_buffer[13<<20];
+
+
+void randomize_one_size_class(size_t size) {
+  int count = (100<<20) / size;
+  if (count * sizeof(randomize_buffer[0]) > sizeof(randomize_buffer)) {
+    abort();
+  }
+  for (int i = 0; i < count; i++) {
+    randomize_buffer[i] = malloc(size);
+  }
+  std::random_shuffle(randomize_buffer, randomize_buffer + count);
+  for (int i = 0; i < count; i++) {
+    free(randomize_buffer[i]);
+  }
+}
+
+void randomize_size_classes() {
+  randomize_one_size_class(8);
+  int i;
+  for (i = 16; i < 256; i += 16) {
+    randomize_one_size_class(i);
+  }
+  for (; i < 512; i += 32) {
+    randomize_one_size_class(i);
+  }
+  for (; i < 1024; i += 64) {
+    randomize_one_size_class(i);
+  }
+  for (; i < (4 << 10); i += 128) {
+    randomize_one_size_class(i);
+  }
+  for (; i < (32 << 10); i += 1024) {
+    randomize_one_size_class(i);
+  }
+}
+
+int main(void)
+{
+  randomize_size_classes();
+
+  report_benchmark("bench_fastpath_throughput", bench_fastpath_throughput, 0);
+  report_benchmark("bench_fastpath_dependent", bench_fastpath_dependent, 0);
+  report_benchmark("bench_fastpath_simple", bench_fastpath_simple, 64);
+  report_benchmark("bench_fastpath_simple", bench_fastpath_simple, 2048);
+  report_benchmark("bench_fastpath_simple", bench_fastpath_simple, 16384);
+
+#ifdef HAVE_SIZED_FREE_OPTION
+  if (is_sized_free_available()) {
+    report_benchmark("bench_fastpath_simple_sized", bench_fastpath_simple_sized, 64);
+    report_benchmark("bench_fastpath_simple_sized", bench_fastpath_simple_sized, 2048);
+  }
+
+  if (is_memalign_available()) {
+    report_benchmark("bench_fastpath_memalign", bench_fastpath_memalign, 64);
+    report_benchmark("bench_fastpath_memalign", bench_fastpath_memalign, 2048);
+  }
+
+#endif
+
+  for (int i = 8; i <= 512; i <<= 1) {
+    report_benchmark("bench_fastpath_stack", bench_fastpath_stack, i);
+  }
+  report_benchmark("bench_fastpath_stack_simple", bench_fastpath_stack_simple, 32);
+  report_benchmark("bench_fastpath_stack_simple", bench_fastpath_stack_simple, 8192);
+  report_benchmark("bench_fastpath_rnd_dependent", bench_fastpath_rnd_dependent, 32);
+  report_benchmark("bench_fastpath_rnd_dependent", bench_fastpath_rnd_dependent, 8192);
+  return 0;
+}
diff --git a/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.c b/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.c
new file mode 100644
index 000000000..9bf04f45a
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.c
@@ -0,0 +1,112 @@
+// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
+// 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.
+
+#include "run_benchmark.h"
+
+#include 
+#include 
+#include 
+#include 
+
+struct internal_bench {
+  bench_body body;
+  uintptr_t param;
+};
+
+static void run_body(struct internal_bench *b, long iterations)
+{
+  b->body(iterations, b->param);
+}
+
+static double measure_once(struct internal_bench *b, long iterations)
+{
+  struct timeval tv_before, tv_after;
+  int rv;
+  double time;
+
+  rv = gettimeofday(&tv_before, NULL);
+  if (rv) {
+    perror("gettimeofday");
+    abort();
+  }
+
+  run_body(b, iterations);
+
+  rv = gettimeofday(&tv_after, NULL);
+  if (rv) {
+    perror("gettimeofday");
+    abort();
+  }
+  tv_after.tv_sec -= tv_before.tv_sec;
+  time = tv_after.tv_sec * 1E6 + tv_after.tv_usec;
+  time -= tv_before.tv_usec;
+  time *= 1000;
+  return time;
+}
+
+#define TRIAL_NSEC 0.3E9
+#define TARGET_NSEC 3E9
+
+static double run_benchmark(struct internal_bench *b)
+{
+  long iterations = 128;
+  double nsec;
+  while (1) {
+    nsec = measure_once(b, iterations);
+    if (nsec > TRIAL_NSEC) {
+      break;
+    }
+    iterations <<= 1;
+  }
+  while (nsec < TARGET_NSEC) {
+    iterations = (long)(iterations * TARGET_NSEC * 1.1 / nsec);
+    nsec = measure_once(b, iterations);
+  }
+  return nsec / iterations;
+}
+
+void report_benchmark(const char *name, bench_body body, uintptr_t param)
+{
+  int i;
+  struct internal_bench b = {.body = body, .param = param};
+  for (i = 0; i < 3; i++) {
+    double nsec = run_benchmark(&b);
+    int slen;
+    int padding_size;
+
+    slen = printf("Benchmark: %s", name);
+    if (param && name[strlen(name)-1] != ')') {
+      slen += printf("(%lld)", (long long)param);
+    }
+    padding_size = 60 - slen;
+    if (padding_size < 1) {
+      padding_size = 1;
+    }
+    printf("%*c%f nsec\n", padding_size, ' ', nsec);
+    fflush(stdout);
+  }
+}
diff --git a/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.h b/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.h
new file mode 100644
index 000000000..e030d1efd
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/benchmark/run_benchmark.h
@@ -0,0 +1,43 @@
+// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*-
+// 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 _RUN_BENCHMARK_H_
+#define _RUN_BENCHMARK_H_
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*bench_body)(long iterations, uintptr_t param);
+
+void report_benchmark(const char *name, bench_body body, uintptr_t param);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _RUN_BENCHMARK_H_
diff --git a/trunk/3rdparty/gperftools-2-fit/compile b/trunk/3rdparty/gperftools-2-fit/compile
new file mode 100755
index 000000000..23fcba011
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/compile
@@ -0,0 +1,348 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+# Written by Tom Tromey .
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to  or send patches to
+# .
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""	$nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+	# lazily determine how to convert abs files
+	case `uname -s` in
+	  MINGW*)
+	    file_conv=mingw
+	    ;;
+	  CYGWIN* | MSYS*)
+	    file_conv=cygwin
+	    ;;
+	  *)
+	    file_conv=wine
+	    ;;
+	esac
+      fi
+      case $file_conv/,$2, in
+	*,$file_conv,*)
+	  ;;
+	mingw/*)
+	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+	  ;;
+	cygwin/* | msys/*)
+	  file=`cygpath -m "$file" || echo "$file"`
+	  ;;
+	wine/*)
+	  file=`winepath -w "$file" || echo "$file"`
+	  ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+	-o)
+	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
+	  eat=1
+	  case $2 in
+	    *.o | *.[oO][bB][jJ])
+	      func_file_conv "$2"
+	      set x "$@" -Fo"$file"
+	      shift
+	      ;;
+	    *)
+	      func_file_conv "$2"
+	      set x "$@" -Fe"$file"
+	      shift
+	      ;;
+	  esac
+	  ;;
+	-I)
+	  eat=1
+	  func_file_conv "$2" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-I*)
+	  func_file_conv "${1#-I}" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-l)
+	  eat=1
+	  func_cl_dashl "$2"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-l*)
+	  func_cl_dashl "${1#-l}"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-L)
+	  eat=1
+	  func_cl_dashL "$2"
+	  ;;
+	-L*)
+	  func_cl_dashL "${1#-L}"
+	  ;;
+	-static)
+	  shared=false
+	  ;;
+	-Wl,*)
+	  arg=${1#-Wl,}
+	  save_ifs="$IFS"; IFS=','
+	  for flag in $arg; do
+	    IFS="$save_ifs"
+	    linker_opts="$linker_opts $flag"
+	  done
+	  IFS="$save_ifs"
+	  ;;
+	-Xlinker)
+	  eat=1
+	  linker_opts="$linker_opts $2"
+	  ;;
+	-*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+	  func_file_conv "$1"
+	  set x "$@" -Tp"$file"
+	  shift
+	  ;;
+	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+	  func_file_conv "$1" mingw
+	  set x "$@" "$file"
+	  shift
+	  ;;
+	*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to .
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+  icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as 'compile cc -o foo foo.c'.
+	# So we strip '-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/trunk/3rdparty/gperftools-2-fit/config.guess b/trunk/3rdparty/gperftools-2-fit/config.guess
new file mode 100755
index 000000000..f50dcdb6d
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/config.guess
@@ -0,0 +1,1480 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-02-24'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see .
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to .
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to ."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > "$dummy.c" ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "$UNAME_SYSTEM" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval "$set_cc_for_build"
+	cat <<-EOF > "$dummy.c"
+	#include 
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+
+	# If ldd exists, use it to detect musl libc.
+	if command -v ldd >/dev/null && \
+		ldd --version 2>&1 | grep -q ^musl
+	then
+	    LIBC=musl
+	fi
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    "/sbin/$sysctl" 2>/dev/null || \
+	    "/usr/sbin/$sysctl" 2>/dev/null || \
+	    echo unknown)`
+	case "$UNAME_MACHINE_ARCH" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine="${arch}${endian}"-unknown
+		;;
+	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently (or will in the future) and ABI.
+	case "$UNAME_MACHINE_ARCH" in
+	    earm*)
+		os=netbsdelf
+		;;
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval "$set_cc_for_build"
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# Determine ABI tags.
+	case "$UNAME_MACHINE_ARCH" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "$UNAME_VERSION" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "$machine-${os}${release}${abi}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+	exit ;;
+    *:LibertyBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+	exit ;;
+    *:MidnightBSD:*:*)
+	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
+	exit ;;
+    *:SolidBSD:*:*)
+	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
+	exit ;;
+    *:MirBSD:*:*)
+	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
+	exit ;;
+    *:Sortix:*:*)
+	echo "$UNAME_MACHINE"-unknown-sortix
+	exit ;;
+    *:Redox:*:*)
+	echo "$UNAME_MACHINE"-unknown-redox
+	exit ;;
+    mips:OSF1:*.*)
+        echo mips-dec-osf1
+        exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE=alpha ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE=alphaev5 ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE=alphaev56 ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE=alphapca56 ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE=alphapca57 ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE=alphaev6 ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE=alphaev67 ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE=alphaev69 ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE=alphaev7 ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE=alphaev79 ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo "$UNAME_MACHINE"-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo "$UNAME_MACHINE"-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix"$UNAME_RELEASE"
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux"$UNAME_RELEASE"
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval "$set_cc_for_build"
+	SUN_ARCH=i386
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH=x86_64
+	    fi
+	fi
+	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos"$UNAME_RELEASE"
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos"$UNAME_RELEASE"
+		;;
+	    sun4)
+		echo sparc-sun-sunos"$UNAME_RELEASE"
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos"$UNAME_RELEASE"
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint"$UNAME_RELEASE"
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint"$UNAME_RELEASE"
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint"$UNAME_RELEASE"
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint"$UNAME_RELEASE"
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint"$UNAME_RELEASE"
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint"$UNAME_RELEASE"
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten"$UNAME_RELEASE"
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten"$UNAME_RELEASE"
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix"$UNAME_RELEASE"
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix"$UNAME_RELEASE"
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix"$UNAME_RELEASE"
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval "$set_cc_for_build"
+	sed 's/^	//' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include   /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos"$UNAME_RELEASE"
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+	then
+	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+	       [ "$TARGET_BINARY_INTERFACE"x = x ]
+	    then
+		echo m88k-dg-dgux"$UNAME_RELEASE"
+	    else
+		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+	    fi
+	else
+	    echo i586-dg-dgux"$UNAME_RELEASE"
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+	fi
+	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval "$set_cc_for_build"
+		sed 's/^		//' << EOF > "$dummy.c"
+		#include 
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+	else
+		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+	fi
+	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+	case "$UNAME_MACHINE" in
+	    9000/31?)            HP_ARCH=m68000 ;;
+	    9000/[34]??)         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "$sc_cpu_version" in
+		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "$sc_kernel_bits" in
+			  32) HP_ARCH=hppa2.0n ;;
+			  64) HP_ARCH=hppa2.0w ;;
+			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "$HP_ARCH" = "" ]; then
+		    eval "$set_cc_for_build"
+		    sed 's/^		//' << EOF > "$dummy.c"
+
+		#define _HPUX_SOURCE
+		#include 
+		#include 
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ "$HP_ARCH" = hppa2.0w ]
+	then
+	    eval "$set_cc_for_build"
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH=hppa2.0w
+	    else
+		HP_ARCH=hppa64
+	    fi
+	fi
+	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux"$HPUX_REV"
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval "$set_cc_for_build"
+	sed 's/^	//' << EOF > "$dummy.c"
+	#include 
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo "$UNAME_MACHINE"-unknown-osf1mk
+	else
+	    echo "$UNAME_MACHINE"-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi"$UNAME_RELEASE"
+	exit ;;
+    *:BSD/OS:*:*)
+	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case "$UNAME_PROCESSOR" in
+	    amd64)
+		UNAME_PROCESSOR=x86_64 ;;
+	    i386)
+		UNAME_PROCESSOR=i586 ;;
+	esac
+	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+	exit ;;
+    i*:CYGWIN*:*)
+	echo "$UNAME_MACHINE"-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo "$UNAME_MACHINE"-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo "$UNAME_MACHINE"-pc-mingw32
+	exit ;;
+    *:MSYS*:*)
+	echo "$UNAME_MACHINE"-pc-msys
+	exit ;;
+    i*:PW*:*)
+	echo "$UNAME_MACHINE"-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case "$UNAME_MACHINE" in
+	    x86)
+		echo i586-pc-interix"$UNAME_RELEASE"
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix"$UNAME_RELEASE"
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix"$UNAME_RELEASE"
+		exit ;;
+	esac ;;
+    i*:UWIN*:*)
+	echo "$UNAME_MACHINE"-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
+	exit ;;
+    i*86:Minix:*:*)
+	echo "$UNAME_MACHINE"-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    arm*:Linux:*:*)
+	eval "$set_cc_for_build"
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+	    else
+		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    cris:Linux:*:*)
+	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+	exit ;;
+    crisv32:Linux:*:*)
+	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+	exit ;;
+    e2k:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    frv:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    hexagon:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    i*86:Linux:*:*)
+	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+	exit ;;
+    ia64:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    k1om:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    m32r*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    m68*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval "$set_cc_for_build"
+	sed 's/^	//' << EOF > "$dummy.c"
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+	test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+	;;
+    mips64el:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-"$LIBC"
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-"$LIBC"
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-"$LIBC"
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+	  *)    echo hppa-unknown-linux-"$LIBC" ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-"$LIBC"
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-"$LIBC"
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-"$LIBC"
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-"$LIBC"
+	exit ;;
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
+	exit ;;
+    sh64*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    sh*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    tile*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    vax:Linux:*:*)
+	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
+	exit ;;
+    x86_64:Linux:*:*)
+	if objdump -f /bin/sh | grep -q elf32-x86-64; then
+	    echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32
+	else
+	    echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+	fi
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo "$UNAME_MACHINE"-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo "$UNAME_MACHINE"-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo "$UNAME_MACHINE"-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo "$UNAME_MACHINE"-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos"$UNAME_RELEASE"
+	exit ;;
+    i*86:*DOS:*:*)
+	echo "$UNAME_MACHINE"-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:*)
+	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+	else
+		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+	else
+		echo "$UNAME_MACHINE"-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configure will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos"$UNAME_RELEASE"
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos"$UNAME_RELEASE"
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv"$UNAME_RELEASE"
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo "$UNAME_MACHINE"-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says 
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes .
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo "$UNAME_MACHINE"-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux"$UNAME_RELEASE"
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv"$UNAME_RELEASE"
+	else
+		echo mips-unknown-sysv"$UNAME_RELEASE"
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    SX-ACE:SUPER-UX:*:*)
+	echo sxace-nec-superux"$UNAME_RELEASE"
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
+	exit ;;
+    *:Rhapsody:*:*)
+	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval "$set_cc_for_build"
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		       grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+		# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+		if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+		       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		       grep IS_PPC >/dev/null
+		then
+		    UNAME_PROCESSOR=powerpc
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = x86; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-*:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSR-*:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSV-*:NONSTOP_KERNEL:*:*)
+	echo nsv-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    NSX-*:NONSTOP_KERNEL:*:*)
+	echo nsx-tandem-nsk"$UNAME_RELEASE"
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = 386; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo "$UNAME_MACHINE"-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux"$UNAME_RELEASE"
+	exit ;;
+    *:DragonFly:*:*)
+	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "$UNAME_MACHINE" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
+	exit ;;
+    i*86:rdos:*:*)
+	echo "$UNAME_MACHINE"-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo "$UNAME_MACHINE"-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo "$UNAME_MACHINE"-unknown-esx
+	exit ;;
+    amd64:Isilon\ OneFS:*:*)
+	echo x86_64-unknown-onefs
+	exit ;;
+esac
+
+echo "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+    mips:Linux | mips64:Linux)
+	# If we got here on MIPS GNU/Linux, output extra information.
+	cat >&2 <&2 </dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM  = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-functions 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/trunk/3rdparty/gperftools-2-fit/config.sub b/trunk/3rdparty/gperftools-2-fit/config.sub
new file mode 100755
index 000000000..1d8e98bce
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/config.sub
@@ -0,0 +1,1801 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-02-22'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see .
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to .
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to ."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo "$1"
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+  kopensolaris*-gnu* | cloudabi*-eabi* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
+    if [ "$basic_machine" != "$1" ]
+    then os=`echo "$1" | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze*)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| ba \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia16 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 | or1k | or1knd | or32 \
+	| pdp10 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
+	| pyramid \
+	| riscv32 | riscv64 \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
+	| wasm32 \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| ba-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| e2k-* | elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
+	| pyramid-* \
+	| riscv32-* | riscv64-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| visium-* \
+	| wasm32-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-pc
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	asmjs)
+		basic_machine=asmjs-unknown
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2*)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next)
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	nsv-tandem)
+		basic_machine=nsv-tandem
+		;;
+	nsx-tandem)
+		basic_machine=nsx-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	x64)
+		basic_machine=x86_64-pc
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases that might get confused
+	# with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# es1800 is here to avoid being matched by es* (a different OS)
+	-es1800*)
+		os=-ose
+		;;
+	# Now accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST end in a * to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* | -cloudabi* | -sortix* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
+	      | -midnightbsd*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -xray | -os68k* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo "$os" | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2)
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-pikeos*)
+		# Until real need of OS specific support for
+		# particular features comes up, bare metal
+		# configurations are quite functional.
+		case $basic_machine in
+		    arm*)
+			os=-eabi
+			;;
+		    *)
+			os=-elf
+			;;
+		esac
+		;;
+	-nacl*)
+		;;
+	-ios)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	pru-*)
+		os=-elf
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next)
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo "$basic_machine$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-functions 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/trunk/3rdparty/gperftools-2-fit/configure b/trunk/3rdparty/gperftools-2-fit/configure
new file mode 100755
index 000000000..14d382902
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/configure
@@ -0,0 +1,22674 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for gperftools 2.9.1.
+#
+# Report bugs to .
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: gperftools@googlegroups.com about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 &1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='gperftools'
+PACKAGE_TARNAME='gperftools'
+PACKAGE_VERSION='2.9.1'
+PACKAGE_STRING='gperftools 2.9.1'
+PACKAGE_BUGREPORT='gperftools@googlegroups.com'
+PACKAGE_URL=''
+
+ac_unique_file="README"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include 
+#ifdef HAVE_SYS_TYPES_H
+# include 
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include 
+#endif
+#ifdef STDC_HEADERS
+# include 
+# include 
+#else
+# ifdef HAVE_STDLIB_H
+#  include 
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include 
+# endif
+# include 
+#endif
+#ifdef HAVE_STRINGS_H
+# include 
+#endif
+#ifdef HAVE_INTTYPES_H
+# include 
+#endif
+#ifdef HAVE_STDINT_H
+# include 
+#endif
+#ifdef HAVE_UNISTD_H
+# include 
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+WITH_STACK_TRACE_FALSE
+WITH_STACK_TRACE_TRUE
+WITH_HEAP_PROFILER_OR_CHECKER_FALSE
+WITH_HEAP_PROFILER_OR_CHECKER_TRUE
+WITH_DEBUGALLOC_FALSE
+WITH_DEBUGALLOC_TRUE
+WITH_HEAP_CHECKER_FALSE
+WITH_HEAP_CHECKER_TRUE
+WITH_HEAP_PROFILER_FALSE
+WITH_HEAP_PROFILER_TRUE
+WITH_CPU_PROFILER_FALSE
+WITH_CPU_PROFILER_TRUE
+OSX_FALSE
+OSX_TRUE
+MINGW_FALSE
+MINGW_TRUE
+HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE
+HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE
+PTHREAD_CFLAGS
+PTHREAD_LIBS
+PTHREAD_CC
+acx_pthread_config
+LIBSTDCXX_LA_LINKER_FLAG
+NANOSLEEP_LIBS
+BUILD_EMERGENCY_MALLOC_FALSE
+BUILD_EMERGENCY_MALLOC_TRUE
+ac_cv_have_std_align_val_t
+HAVE_F_ALIGNED_NEW_FALSE
+HAVE_F_ALIGNED_NEW_TRUE
+HAVE_SIZED_DEALLOCATION_FALSE
+HAVE_SIZED_DEALLOCATION_TRUE
+INSTALL_PPROF_FALSE
+INSTALL_PPROF_TRUE
+HAVE_W_NO_UNUSED_RESULT_FALSE
+HAVE_W_NO_UNUSED_RESULT_TRUE
+I386_FALSE
+I386_TRUE
+OMIT_FP_BY_DEFAULT_FALSE
+OMIT_FP_BY_DEFAULT_TRUE
+ENABLE_FRAME_POINTERS_FALSE
+ENABLE_FRAME_POINTERS_TRUE
+UNWIND_LIBS
+ENABLE_STATIC_FALSE
+ENABLE_STATIC_TRUE
+ac_cv_have_struct_mallinfo
+CXXCPP
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+ac_ct_AR
+AR
+DLLTOOL
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+LIBTOOL
+HAVE_OBJCOPY_WEAKEN_FALSE
+HAVE_OBJCOPY_WEAKEN_TRUE
+OBJCOPY
+HAVE_CXX11
+GCC_FALSE
+GCC_TRUE
+CPP
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+GENERATE_CHANGELOG_RULES
+GIT
+TC_VERSION_PATCH
+TC_VERSION_MINOR
+TC_VERSION_MAJOR
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+TCMALLOC_AND_PROFILER_SO_VERSION
+PROFILER_SO_VERSION
+TCMALLOC_SO_VERSION
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_maintainer_mode
+enable_dependency_tracking
+enable_cpu_profiler
+enable_heap_profiler
+enable_heap_checker
+enable_debugalloc
+enable_minimal
+enable_stacktrace_via_backtrace
+enable_libunwind
+with_tcmalloc_pagesize
+with_tcmalloc_alignment
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_frame_pointers
+enable_deprecated_pprof
+enable_dynamic_sized_delete_support
+enable_sized_delete
+enable_emergency_malloc
+enable_large_alloc_report
+enable_aggressive_decommit_by_default
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP
+LT_SYS_LIBRARY_PATH
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir runstatedir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # 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 gperftools 2.9.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/gperftools]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of gperftools 2.9.1:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-maintainer-mode
+                          enable make rules and dependencies not useful (and
+                          sometimes confusing) to the casual installer
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --disable-cpu-profiler  do not build the cpu profiler
+  --disable-heap-profiler do not build the heap profiler
+  --disable-heap-checker  do not build the heap checker
+  --disable-debugalloc    do not build versions of libs with debugalloc
+  --enable-minimal        build only tcmalloc-minimal (and maybe
+                          tcmalloc-minimal-debug)
+  --enable-stacktrace-via-backtrace
+                          enable use of backtrace() for stacktrace capturing
+                          (may deadlock)
+  --enable-libunwind      enable libunwind linking
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-frame-pointers On x86_64 systems, compile with
+                          -fno-omit-frame-pointer (see INSTALL)
+  --disable-deprecated-pprof
+                          do not install old deprecated and unmaintained
+                          bundled pprof (see github.com/google/pprof for
+                          supported version)
+  --enable-dynamic-sized-delete-support
+                          try to build run-time switch for sized delete
+                          operator
+  --enable-sized-delete   build sized delete operator
+  --enable-emergency-malloc
+                          build emergency malloc feature
+  --enable-large-alloc-report
+                          report very large allocations to stderr
+  --enable-aggressive-decommit-by-default
+                          enable aggressive decommit by default
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-tcmalloc-pagesize
+                          Set the tcmalloc internal page size to 4K, 8K, 16K,
+                          32K, 64K, 128K or 256K
+  --with-tcmalloc-alignment
+                          Set the tcmalloc allocation alignment to 8 or 16
+                          bytes
+  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-aix-soname=aix|svr4|both
+                          shared library versioning (aka "SONAME") variant to
+                          provide on AIX, [default=aix].
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot[=DIR]    Search for dependent libraries within DIR (or the
+                          compiler's sysroot if not specified).
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L if you have libraries in a
+              nonstandard directory 
+  LIBS        libraries to pass to the linker, e.g. -l
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I if
+              you have headers in a nonstandard directory 
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+  LT_SYS_LIBRARY_PATH
+              User-defined run-time library search path.
+  CXXCPP      C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to .
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+gperftools configure 2.9.1
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case  declares $2.
+   For example, HP-UX 11i  declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer  to  if __STDC__ is defined, since
+     exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include 
+#else
+# include 
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ------------------------------------------ ##
+## Report this to gperftools@googlegroups.com ##
+## ------------------------------------------ ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by gperftools $as_me 2.9.1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+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=9:9:5
+PROFILER_SO_VERSION=5:4:5
+TCMALLOC_AND_PROFILER_SO_VERSION=10:4:6
+
+
+
+
+
+# The argument here is just something that should be in the current directory
+# (for sanity checking)
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+am__api_version='1.16'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+	&& test "$*" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='gperftools'
+ VERSION='2.9.1'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# 
+# 
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: 
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: .
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+
+ac_config_headers="$ac_config_headers src/config.h"
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+# Export the version information (for tc_version and friends)
+TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([0-9]*\)'`
+TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[0-9]*\.\([0-9]*\)'`
+TC_VERSION_PATCH=`expr "$PACKAGE_VERSION" : '[0-9]*\.[0-9]*\(.*\)$'`
+
+
+
+
+
+
+	# Find git, defaulting to the 'missing' script so the user gets a nice
+	# message if git is missing, rather than a plain 'command not found'.
+	# Extract the first word of "git", so it can be a program name with args.
+set dummy git; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GIT in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GIT="$GIT" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GIT="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_GIT" && ac_cv_path_GIT="${am_missing_run}git"
+  ;;
+esac
+fi
+GIT=$ac_cv_path_GIT
+if test -n "$GIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GIT" >&5
+$as_echo "$GIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+	# Build the ChangeLog rules.
+
+GENERATE_CHANGELOG_RULES='
+# Generate ChangeLog
+#
+# Optional:
+#  - CHANGELOG_START: git commit ID or tag name to output changelogs from
+#    (exclusive). (Default: include all commits)
+#  - CHANGELOG_GIT_FLAGS: General flags to pass to git-log when generating the
+#    ChangeLog. (Default: various)
+#  - CHANGELOG_GIT_DIR: .git directory to use. (Default: $(top_srcdir)/.git)
+
+# git-specific
+CHANGELOG_GIT_FLAGS ?= --stat -M -C --name-status --no-color
+CHANGELOG_GIT_DIR ?= $(top_srcdir)/.git
+
+ifeq ($(CHANGELOG_START),)
+CHANGELOG_GIT_RANGE =
+else
+CHANGELOG_GIT_RANGE = $(CHANGELOG_START)..
+endif
+
+# Generate a ChangeLog in $(top_distdir)
+dist-ChangeLog:
+	$(AM_V_GEN)if $(GIT) \
+		--git-dir=$(CHANGELOG_GIT_DIR) --work-tree=$(top_srcdir) log \
+		$(CHANGELOG_GIT_FLAGS) $(CHANGELOG_GIT_RANGE) \
+		| fmt --split-only >.ChangeLog.tmp; \
+	then mv -f .ChangeLog.tmp "$(top_distdir)/ChangeLog"; \
+	else rm -f .ChangeLog.tmp; exit 1; fi
+
+.PHONY: dist-ChangeLog
+'
+
+
+
+
+
+# The user can choose not to compile in the heap-profiler, the
+# heap-checker, or the cpu-profiler.  There's also the possibility
+# for a 'fully minimal' compile, which leaves out the stacktrace
+# code as well.  By default, we include all of these that the
+# target system supports.
+default_enable_cpu_profiler=yes
+default_enable_heap_profiler=yes
+default_enable_heap_checker=yes
+default_enable_debugalloc=yes
+default_enable_minimal=no
+default_tcmalloc_alignment=16
+need_nanosleep=yes   # Used later, to decide if to run ACX_NANOSLEEP
+case "$host" in
+   *-mingw*) default_enable_minimal=yes; default_enable_debugalloc=no;
+             need_nanosleep=no;;
+   *-cygwin*) default_enable_heap_checker=no; default_enable_cpu_profiler=no;;
+   *-freebsd*) default_enable_heap_checker=no;;
+   *-darwin*) default_enable_heap_checker=no;;
+esac
+
+# Currently only backtrace works on s390 and OSX.
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+   (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+  case $?:`cat confinc.out 2>/dev/null` in #(
+  '0:this is the am__doit target') :
+    case $s in #(
+  BSD) :
+    am__include='.include' am__quote='"' ;; #(
+  *) :
+    am__include='include' am__quote='' ;;
+esac ;; #(
+  *) :
+     ;;
+esac
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+$as_echo "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+#if !defined(__s390__) && !defined(__APPLE__)
+#error not s390 and not osx
+#endif
+return 1
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  default_enable_libunwind=no
+                   default_enable_backtrace=yes
+else
+  default_enable_libunwind=yes
+                   default_enable_backtrace=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Disable libunwind linking on ppc64 by default.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return __PPC64__
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  default_enable_libunwind=no
+                   default_tcmalloc_pagesize=64
+else
+  default_enable_libunwind=yes
+                   default_tcmalloc_pagesize=8
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Check whether --enable-cpu-profiler was given.
+if test "${enable_cpu_profiler+set}" = set; then :
+  enableval=$enable_cpu_profiler;
+else
+  enable_cpu_profiler="$default_enable_cpu_profiler"
+fi
+
+# Check whether --enable-heap-profiler was given.
+if test "${enable_heap_profiler+set}" = set; then :
+  enableval=$enable_heap_profiler;
+else
+  enable_heap_profiler="$default_enable_heap_profiler"
+fi
+
+# Check whether --enable-heap-checker was given.
+if test "${enable_heap_checker+set}" = set; then :
+  enableval=$enable_heap_checker;
+else
+  enable_heap_checker="$default_enable_heap_checker"
+fi
+
+# Check whether --enable-debugalloc was given.
+if test "${enable_debugalloc+set}" = set; then :
+  enableval=$enable_debugalloc;
+else
+  enable_debugalloc="$default_enable_debugalloc"
+fi
+
+# Check whether --enable-minimal was given.
+if test "${enable_minimal+set}" = set; then :
+  enableval=$enable_minimal;
+else
+  enable_minimal="$default_enable_minimal"
+fi
+
+if test "$enable_minimal" = yes; then
+  enable_cpu_profiler=no
+  enable_heap_profiler=no
+  enable_heap_checker=no
+fi
+# Check whether --enable-stacktrace-via-backtrace was given.
+if test "${enable_stacktrace_via_backtrace+set}" = set; then :
+  enableval=$enable_stacktrace_via_backtrace; enable_backtrace=yes
+else
+  enable_backtrace="$default_enable_backtrace"
+fi
+
+# Check whether --enable-libunwind was given.
+if test "${enable_libunwind+set}" = set; then :
+  enableval=$enable_libunwind;
+else
+  enable_libunwind="$default_enable_libunwind"
+fi
+
+
+# Check whether --with-tcmalloc-pagesize was given.
+if test "${with_tcmalloc_pagesize+set}" = set; then :
+  withval=$with_tcmalloc_pagesize;
+else
+  with_tcmalloc_pagesize=$default_tcmalloc_pagesize
+fi
+
+
+# Check whether --with-tcmalloc-alignment was given.
+if test "${with_tcmalloc_alignment+set}" = set; then :
+  withval=$with_tcmalloc_alignment;
+else
+  with_tcmalloc_alignment=$default_tcmalloc_alignment
+fi
+
+
+case "$with_tcmalloc_pagesize" in
+  4)
+       $as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 12" >>confdefs.h
+;;
+  8)
+       #Default tcmalloc page size.
+       ;;
+  16)
+       $as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 14" >>confdefs.h
+;;
+  32)
+       $as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 15" >>confdefs.h
+;;
+  64)
+       $as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 16" >>confdefs.h
+;;
+  128)
+       $as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 17" >>confdefs.h
+;;
+  256)
+
+$as_echo "#define TCMALLOC_PAGE_SIZE_SHIFT 18" >>confdefs.h
+;;
+  *)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ${with_tcmalloc_pagesize}K size not supported, using default tcmalloc page size." >&5
+$as_echo "$as_me: WARNING: ${with_tcmalloc_pagesize}K size not supported, using default tcmalloc page size." >&2;}
+esac
+case "$with_tcmalloc_alignment" in
+  8)
+
+$as_echo "#define TCMALLOC_ALIGN_8BYTES 1" >>confdefs.h
+;;
+  16)
+       #Default tcmalloc allocation alignment.
+       ;;
+  *)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ${with_tcmalloc_alignment} bytes not supported, using default tcmalloc allocation alignment." >&5
+$as_echo "$as_me: WARNING: ${with_tcmalloc_alignment} bytes not supported, using default tcmalloc allocation alignment." >&2;}
+esac
+
+# Checks for programs.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer  to  if __STDC__ is defined, since
+  #  exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include 
+#else
+# include 
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer  to  if __STDC__ is defined, since
+  #  exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include 
+#else
+# include 
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ if test "$GCC" = yes; then
+  GCC_TRUE=
+  GCC_FALSE='#'
+else
+  GCC_TRUE='#'
+  GCC_FALSE=
+fi
+   # let the Makefile know if we're gcc
+      # shrug: autogen.sh suddenly needs this for some reason
+
+
+  ax_cxx_compile_alternatives="11 0x"    ax_cxx_compile_cxx11_required=true
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+  ac_success=no
+
+    if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
+if eval \${$cachevar+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template 
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check single_type;
+    typedef check> double_type;
+    typedef check>> triple_type;
+    typedef check>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same::value == true, "");
+      static_assert(is_same::value == false, "");
+      static_assert(is_same::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same::value == true, "");
+      static_assert(is_same::value == true, "");
+      static_assert(is_same::value == true, "");
+      static_assert(is_same::value == false, "");
+      static_assert(is_same::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template 
+    struct sum;
+
+    template 
+    struct sum
+    {
+      static constexpr auto value = N0 + sum::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template
+    using member = typename T::member_type;
+
+    template
+    void func(...) {}
+
+    template
+    void func(member*) {}
+
+    void test();
+
+    void test() { func(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval $cachevar=yes
+else
+  eval $cachevar=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+         CXX="$ac_save_CXX"
+fi
+eval ac_res=\$$cachevar
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi
+
+
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
+    if test x$ac_success = xno; then
+      as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX11=0
+    { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5
+$as_echo "$as_me: No compiler with C++11 support was found" >&6;}
+  else
+    HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+  fi
+
+
+
+# Check if we have an objcopy installed that supports -W
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objcopy; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJCOPY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCOPY" >&5
+$as_echo "$OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJCOPY"; then
+  ac_ct_OBJCOPY=$OBJCOPY
+  # Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJCOPY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJCOPY"; then
+  ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJCOPY="objcopy"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY
+if test -n "$ac_ct_OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJCOPY" >&5
+$as_echo "$ac_ct_OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJCOPY" = x; then
+    OBJCOPY=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJCOPY=$ac_ct_OBJCOPY
+  fi
+else
+  OBJCOPY="$ac_cv_prog_OBJCOPY"
+fi
+
+if test -n "$OBJCOPY"; then :
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $OBJCOPY supports -W" >&5
+$as_echo_n "checking if $OBJCOPY supports -W... " >&6; }
+if ${gpt_cv_objcopy_weaken+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+void foo() {} int main() {return 0;}
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+        if "$OBJCOPY" -W foo conftest$ac_exeext /dev/null; then :
+  gpt_cv_objcopy_weaken=yes
+else
+  gpt_cv_objcopy_weaken=no
+fi
+else
+  gpt_cv_objcopy_weaken=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gpt_cv_objcopy_weaken" >&5
+$as_echo "$gpt_cv_objcopy_weaken" >&6; }
+else
+  gpt_cv_objcopy_weaken=no
+fi
+ if test $gpt_cv_objcopy_weaken = yes; then
+  HAVE_OBJCOPY_WEAKEN_TRUE=
+  HAVE_OBJCOPY_WEAKEN_FALSE='#'
+else
+  HAVE_OBJCOPY_WEAKEN_TRUE='#'
+  HAVE_OBJCOPY_WEAKEN_FALSE=
+fi
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.6'
+macro_revision='2.4.6'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case $ECHO in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return, which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD=$ac_prog
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test yes = "$with_gnu_ld"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD=$ac_dir/$ac_prog
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 &5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 &5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM=$NM
+else
+  lt_nm_to_check=${ac_tool_prefix}nm
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS=$lt_save_ifs
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm=$ac_dir/$lt_tmp_nm
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+	case $build_os in
+	mingw*) lt_bad_file=conftest.nm/nofile ;;
+	*) lt_bad_file=/dev/null ;;
+	esac
+	case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+	*$lt_bad_file* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break 2
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break 2
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS=$lt_save_ifs
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test no != "$lt_cv_path_NM"; then
+  NM=$lt_cv_path_NM
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols -headers"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test : != "$DUMPBIN"; then
+    NM=$DUMPBIN
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring=ABCD
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test 17 != "$i" # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test yes != "$GCC"; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test yes = "$GCC"; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd* | bitrig*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+os2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh;
+  # decide which one to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd=$ECHO
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cr}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test 0 -eq "$ac_status"; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	if test 0 -ne "$ac_status"; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test no = "$lt_cv_ar_at_file"; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  bitrig* | openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test ia64 = "$host_cpu"; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  # Gets list of data symbols to import.
+  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+  # Adjust the below global symbol transforms to fixup imported variables.
+  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+  lt_c_name_lib_hook="\
+  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+else
+  # Disable hooks by default.
+  lt_cv_sys_global_symbol_to_import=
+  lt_cdecl_hook=
+  lt_c_name_hook=
+  lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function,
+    # D for any global variable and I for any imported variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
+	  LIBS=conftstm.$ac_objext
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest$ac_exeext; then
+	    pipe_works=yes
+	  fi
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test yes = "$pipe_works"; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot;
+else
+  with_sysroot=no
+fi
+
+
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+   if test yes = "$GCC"; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+$as_echo "$with_sysroot" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+$as_echo_n "checking for a working dd... " >&6; }
+if ${ac_cv_path_lt_DD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+  ac_path_lt_DD_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in dd; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+      $ac_path_lt_DD_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_lt_DD"; then
+    :
+  fi
+else
+  ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+$as_echo "$ac_cv_path_lt_DD" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+$as_echo_n "checking how to truncate binary pipes... " >&6; }
+if ${lt_cv_truncate_bin+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+$as_echo "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in $*""; do
+      case $cc_temp in
+        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out what ABI is being produced by ac_compile, and set mode
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE=32
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE=64
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test yes = "$lt_cv_prog_gnu_ld"; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+mips64*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    emul=elf
+    case `/usr/bin/file conftest.$ac_objext` in
+      *32-bit*)
+	emul="${emul}32"
+	;;
+      *64-bit*)
+	emul="${emul}64"
+	;;
+    esac
+    case `/usr/bin/file conftest.$ac_objext` in
+      *MSB*)
+	emul="${emul}btsmip"
+	;;
+      *LSB*)
+	emul="${emul}ltsmip"
+	;;
+    esac
+    case `/usr/bin/file conftest.$ac_objext` in
+      *N32*)
+	emul="${emul}n32"
+	;;
+    esac
+    LD="${LD-ld} -m $emul"
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.  Note that the listed cases only cover the
+  # situations where additional linker options are needed (such as when
+  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+  # vice versa); the common cases where no linker options are needed do
+  # not appear in the list.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    case `/usr/bin/file conftest.o` in
+	      *x86-64*)
+		LD="${LD-ld} -m elf32_x86_64"
+		;;
+	      *)
+		LD="${LD-ld} -m elf_i386"
+		;;
+	    esac
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test yes != "$lt_cv_cc_needs_belf"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS=$SAVE_CFLAGS
+  fi
+  ;;
+*-*solaris*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*|x86_64-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD=${LD-ld}_sol2
+        fi
+        ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks=$enable_libtool_lock
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+  fi
+else
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test yes != "$lt_cv_path_mainfest_tool"; then
+  MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "$LT_MULTI_MODULE"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	# If there is a non-empty error log, and "single_module"
+	# appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+	  cat conftest.err >&5
+	# Otherwise, if the output was created with a 0 exit code from
+	# the compiler, it worked.
+	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cr libconftest.a conftest.o" >&5
+      $AR cr libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+	cat conftest.err >&5
+      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[912]*)
+	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+	10.[012][,.]*)
+	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+	10.*|11.*)
+	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test yes = "$lt_cv_apple_cc_single_mod"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+    fi
+    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x$2 in
+    x)
+        ;;
+    *:)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+        ;;
+    x:*)
+        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+        ;;
+    *)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+#include 
+#include 
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+func_stripname_cnf ()
+{
+  case $2 in
+  .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;;
+  *)  func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;;
+  esac
+} # func_stripname_cnf
+
+
+
+
+
+# Set options
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for lt_pkg in $withval; do
+	IFS=$lt_save_ifs
+	if test "X$lt_pkg" = "X$lt_p"; then
+	  pic_mode=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else
+  pic_mode=default
+fi
+
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+  shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+$as_echo_n "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test "${with_aix_soname+set}" = set; then :
+  withval=$with_aix_soname; case $withval in
+    aix|svr4|both)
+      ;;
+    *)
+      as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+      ;;
+    esac
+    lt_cv_with_aix_soname=$with_aix_soname
+else
+  if ${lt_cv_with_aix_soname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_with_aix_soname=aix
+fi
+
+    with_aix_soname=$lt_cv_with_aix_soname
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+$as_echo "$with_aix_soname" >&6; }
+  if test aix != "$with_aix_soname"; then
+    # For the AIX way of multilib, we name the shared archive member
+    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+    if test 64 = "${OBJECT_MODE-32}"; then
+      shared_archive_member_spec=shr_64
+    else
+      shared_archive_member_spec=shr
+    fi
+  fi
+  ;;
+*)
+  with_aix_soname=aix
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test set != "${COLLECT_NAMES+set}"; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/${ac_tool_prefix}file"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/file"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC=$CC
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test yes = "$GCC"; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+  if test yes = "$GCC"; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      case $host_os in
+      os2*)
+	lt_prog_compiler_static='$wl-static'
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      if test -n "$lt_prog_compiler_pic"; then
+        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      case $cc_basename in
+      nagfor*)
+        # NAG Fortran compiler
+        lt_prog_compiler_wl='-Wl,-Wl,,'
+        lt_prog_compiler_pic='-PIC'
+        lt_prog_compiler_static='-Bstatic'
+        ;;
+      esac
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      case $host_os in
+      os2*)
+	lt_prog_compiler_static='$wl-static'
+	;;
+      esac
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='$wl-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64, which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # flang / f18. f95 an alias for gfortran or flang on Debian
+      flang* | f18* | f95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      nagfor*)
+	# NAG Fortran compiler
+	lt_prog_compiler_wl='-Wl,-Wl,,'
+	lt_prog_compiler_pic='-PIC'
+	lt_prog_compiler_static='-Bstatic'
+	;;
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ F* | *Sun*Fortran*)
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Qoption ld '
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+        *Intel*\ [CF]*Compiler*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fPIC'
+	  lt_prog_compiler_static='-static'
+	  ;;
+	*Portland\ Group*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fpic'
+	  lt_prog_compiler_static='-Bstatic'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms that do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works"; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works"; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test no = "$hard_links"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+  # as well as any symbol that contains 'd'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test yes != "$GCC"; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd* | bitrig*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    link_all_deplibs=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test yes = "$with_gnu_ld"; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test yes = "$lt_use_gnu_ld_interface"; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='$wl'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+    export_dynamic_flag_spec='$wl--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test ia64 != "$host_cpu"; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach  says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='$wl--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file, use it as
+	# is; otherwise, prepend EXPORTS...
+	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+          cp $export_symbols $output_objdir/$soname.def;
+        else
+          echo EXPORTS > $output_objdir/$soname.def;
+          cat $export_symbols >> $output_objdir/$soname.def;
+        fi~
+        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      shrext_cmds=.dll
+      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+      export_dynamic_flag_spec='$wl-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test linux-dietlibc = "$host_os"; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test no = "$tmp_diet"
+      then
+	tmp_addflag=' $pic_flag'
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+        nagfor*)                        # NAGFOR 5.3
+          tmp_sharedflag='-Wl,-shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+        if test yes = "$supports_anon_versioning"; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            echo "local: *; };" >> $output_objdir/$libname.ver~
+            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	tcc*)
+	  export_dynamic_flag_spec='-rdynamic'
+	  ;;
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+	  if test yes = "$supports_anon_versioning"; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              echo "local: *; };" >> $output_objdir/$libname.ver~
+              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test no = "$ld_shlibs"; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test ia64 = "$host_cpu"; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
+	# Without the "-l" option, or with the "-B" option, AIX nm treats
+	# weak defined symbols like other global defined symbols, whereas
+	# GNU nm marks them as "W".
+	# While the 'weak' keyword is ignored in the Export File, we need
+	# it in the Import File for the 'aix-soname' feature, so we have
+	# to replace the "-B" option with "-P" for AIX nm.
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# have runtime linking enabled, and use it for executables.
+	# For shared libraries, we enable/disable runtime linking
+	# depending on the kind of the shared library created -
+	# when "with_aix_soname,aix_use_runtimelinking" is:
+	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "aix,yes"  lib.so          shared, rtl:yes, for executables
+	#            lib.a           static archive
+	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
+	#            lib.a(lib.so.V) shared, rtl:no,  for executables
+	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a(lib.so.V) shared, rtl:no
+	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+	#            lib.a           static archive
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
+	    # so we don't have lib.a shared libs to link our executables.
+	    # We have to force runtime linking in this case.
+	    aix_use_runtimelinking=yes
+	    LDFLAGS="$LDFLAGS -Wl,-brtl"
+	  fi
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='$wl-f,'
+      case $with_aix_soname,$aix_use_runtimelinking in
+      aix,*) ;; # traditional, no import file
+      svr4,* | *,yes) # use import file
+	# The Import File defines what to hardcode.
+	hardcode_direct=no
+	hardcode_direct_absolute=no
+	;;
+      esac
+
+      if test yes = "$GCC"; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`$CC -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test yes = "$aix_use_runtimelinking"; then
+	  shared_flag="$shared_flag "'$wl-G'
+	fi
+	# Need to ensure runtime linking is disabled for the traditional
+	# shared library, or the linker may eventually find shared libraries
+	# /with/ Import File - we do not want to mix them.
+	shared_flag_aix='-shared'
+	shared_flag_svr4='-shared $wl-G'
+      else
+	# not using gcc
+	if test ia64 = "$host_cpu"; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test yes = "$aix_use_runtimelinking"; then
+	    shared_flag='$wl-G'
+	  else
+	    shared_flag='$wl-bM:SRE'
+	  fi
+	  shared_flag_aix='$wl-bM:SRE'
+	  shared_flag_svr4='$wl-G'
+	fi
+      fi
+
+      export_dynamic_flag_spec='$wl-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=/usr/lib:/lib
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+      else
+	if test ia64 = "$host_cpu"; then
+	  hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=/usr/lib:/lib
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+	 hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' $wl-bernotok'
+	  allow_undefined_flag=' $wl-berok'
+	  if test yes = "$with_gnu_ld"; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+	  # -brtl affects multiple linker settings, -berok does not and is overridden later
+	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+	  if test svr4 != "$with_aix_soname"; then
+	    # This is similar to how AIX traditionally builds its shared libraries.
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+	  fi
+	  if test aix != "$with_aix_soname"; then
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+	  else
+	    # used by -dlpreopen to get the symbols
+	    archive_expsym_cmds="$archive_expsym_cmds"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+	  fi
+	  archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+	# Native MSVC
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	always_export_symbols=yes
+	file_list_spec='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+            cp "$export_symbols" "$output_objdir/$soname.def";
+            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+          else
+            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+          fi~
+          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+          linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+	enable_shared_with_static_runtimes=yes
+	exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	old_postinstall_cmds='chmod 644 $oldlib'
+	postlink_cmds='lt_outputfile="@OUTPUT@"~
+          lt_tool_outputfile="@TOOL_OUTPUT@"~
+          case $lt_outputfile in
+            *.exe|*.EXE) ;;
+            *)
+              lt_outputfile=$lt_outputfile.exe
+              lt_tool_outputfile=$lt_tool_outputfile.exe
+              ;;
+          esac~
+          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+            $RM "$lt_outputfile.manifest";
+          fi'
+	;;
+      *)
+	# Assume MSVC wrapper
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=.dll
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	old_archive_from_new_cmds='true'
+	# FIXME: Should let the user specify the lib program.
+	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	enable_shared_with_static_runtimes=yes
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test yes = "$lt_cv_ld_force_load"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag=$_lt_dar_allow_undefined
+  case $cc_basename in
+     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test yes = "$_lt_dar_can_shared"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+    archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test yes = "$GCC"; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='$wl-E'
+      ;;
+
+    hpux10*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test no = "$with_gnu_ld"; then
+	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='$wl-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test yes = "$lt_cv_prog_compiler__b"; then
+    archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test no = "$with_gnu_ld"; then
+	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='$wl-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+	# This should be the same for all languages, so no per-tag cache variable.
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_LDFLAGS=$LDFLAGS
+	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_irix_exported_symbol=yes
+else
+  lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+           LDFLAGS=$save_LDFLAGS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+	if test yes = "$lt_cv_irix_exported_symbol"; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+	fi
+	link_all_deplibs=no
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    linux*)
+      case $cc_basename in
+      tcc*)
+	# Fabrice Bellard et al's Tiny C Compiler
+	ld_shlibs=yes
+	archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	;;
+      esac
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd* | bitrig*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+	  export_dynamic_flag_spec='$wl-E'
+	else
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      shrext_cmds=.dll
+      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	$ECHO EXPORTS >> $output_objdir/$libname.def~
+	prefix_cmds="$SED"~
+	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	  prefix_cmds="$prefix_cmds -e 1d";
+	fi~
+	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	emximp -o $lib $output_objdir/$libname.def'
+      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+      enable_shared_with_static_runtimes=yes
+      ;;
+
+    osf3*)
+      if test yes = "$GCC"; then
+	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test yes = "$GCC"; then
+	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+	archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test yes = "$GCC"; then
+	wlarc='$wl'
+	archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='$wl'
+	  archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands '-z linker_flag'.  GCC discards it without '$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test yes = "$GCC"; then
+	  whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test sequent = "$host_vendor"; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='$wl-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We CANNOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='$wl-z,text'
+      allow_undefined_flag='$wl-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='$wl-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='$wl-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test sni = "$host_vendor"; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='$wl-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test no = "$ld_shlibs" && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test yes,yes = "$GCC,$enable_shared"; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test yes = "$GCC"; then
+  case $host_os in
+    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+    *) lt_awk_arg='/^libraries:/' ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+    *) lt_sed_strip_eq='s|=/|/|g' ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary...
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  # ...but if some path component already ends with the multilib dir we assume
+  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+  case "$lt_multi_os_dir; $lt_search_path_spec " in
+  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+    lt_multi_os_dir=
+    ;;
+  esac
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+    elif test -n "$lt_multi_os_dir"; then
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+  lt_foo = "";
+  lt_count = 0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo = "/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='$libname$release$shared_ext$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test ia64 = "$host_cpu"; then
+    # AIX 5 supports IA64
+    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line '#! .'.  This would cause the generated library to
+    # depend on '.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # Using Import Files as archive members, it is possible to support
+    # filename-based versioning of shared library archives on AIX. While
+    # this would work for both with and without runtime linking, it will
+    # prevent static linking of such archives. So we do filename-based
+    # shared library versioning with .so extension only, which is used
+    # when both runtime linking and shared linking is enabled.
+    # Unfortunately, runtime linking may impact performance, so we do
+    # not want this to be the default eventually. Also, we use the
+    # versioned .so libs for executables only if there is the -brtl
+    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+    # To allow for filename-based versioning support, we need to create
+    # libNAME.so.V as an archive file, containing:
+    # *) an Import File, referring to the versioned filename of the
+    #    archive as well as the shared archive member, telling the
+    #    bitwidth (32 or 64) of that shared object, and providing the
+    #    list of exported symbols of that shared object, eventually
+    #    decorated with the 'weak' keyword
+    # *) the shared object with the F_LOADONLY flag set, to really avoid
+    #    it being seen by the linker.
+    # At run time we better use the real file rather than another symlink,
+    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+    case $with_aix_soname,$aix_use_runtimelinking in
+    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    aix,yes) # traditional libtool
+      dynamic_linker='AIX unversionable lib.so'
+      # If using run time linking (on AIX 4.2 or later) use lib.so
+      # instead of lib.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      ;;
+    aix,no) # traditional AIX only
+      dynamic_linker='AIX lib.a(lib.so.V)'
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      ;;
+    svr4,*) # full svr4 only
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,yes) # both, prefer svr4
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # unpreferred sharedlib libNAME.a needs extra handling
+      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,no) # both, prefer aix
+      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+      ;;
+    esac
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='$libname$shared_ext'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+    library_names_spec='$libname.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec=$LIB
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$major$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      soname_spec='$libname$release$shared_ext$major'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    if test 32 = "$HPUX_IA64_MODE"; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+    fi
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test yes = "$lt_cv_prog_gnu_ld"; then
+		version_type=linux # correct to gnu/linux during the next big refactor
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+linux*android*)
+  version_type=none # Android doesn't support versioned libraries.
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext'
+  soname_spec='$libname$release$shared_ext'
+  finish_cmds=
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  dynamic_linker='Android linker'
+  # Don't embed -rpath directories since the linker doesn't support them.
+  hardcode_libdir_flag_spec='-L$libdir'
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Ideally, we could use ldconfig to report *all* directores which are
+  # searched for libraries, however this is still not possible.  Aside from not
+  # being certain /sbin/ldconfig is available, command
+  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+  # even though it is searched at run-time.  Try to do the best guess by
+  # appending ld.so.conf contents (and includes) to the search path.
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd* | bitrig*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec=/usr/lib
+  need_lib_prefix=no
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    need_version=no
+  else
+    need_version=yes
+  fi
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+os2*)
+  libname_spec='$name'
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+  # OS/2 can only load a DLL with a base name of 8 characters or less.
+  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+    v=$($ECHO $release$versuffix | tr -d .-);
+    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+    $ECHO $n$v`$shared_ext'
+  library_names_spec='${libname}_dll.$libext'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=BEGINLIBPATH
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  postinstall_cmds='base_file=`basename \$file`~
+    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+    dldir=$destdir/`dirname \$dlpath`~
+    test -d \$dldir || mkdir -p \$dldir~
+    $install_prog $dir/$dlname \$dldir/$dlname~
+    chmod a+x \$dldir/$dlname~
+    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+    fi'
+  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+    dlpath=$dir/\$dldll~
+    $RM \$dlpath'
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test yes = "$with_gnu_ld"; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec; then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+    soname_spec='$libname$shared_ext.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=sco
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test yes = "$with_gnu_ld"; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test yes = "$hardcode_automatic"; then
+
+  # We can hardcode non-existent directories.
+  if test no != "$hardcode_direct" &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+     test no != "$hardcode_minus_L"; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test relink = "$hardcode_action" ||
+   test yes = "$inherit_rpath"; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+     test no = "$enable_shared"; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test yes != "$enable_dlopen"; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen=load_add_on
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen=LoadLibrary
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+    # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else
+
+    lt_cv_dlopen=dyld
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  tpf*)
+    # Don't try to run any link tests for TPF.  We know it's impossible
+    # because TPF is a cross-compiler, and we know how we open DSOs.
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=no
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+  lt_cv_dlopen=shl_load
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+  lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+  lt_cv_dlopen=dlopen
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+  lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test no = "$lt_cv_dlopen"; then
+    enable_dlopen=no
+  else
+    enable_dlopen=yes
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS=$CPPFLAGS
+    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS=$LDFLAGS
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS=$LIBS
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test yes = "$cross_compiling"; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include 
+#endif
+
+#include 
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test yes = "$lt_cv_dlopen_self"; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test yes = "$cross_compiling"; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include 
+#endif
+
+#include 
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS=$save_CPPFLAGS
+    LDFLAGS=$save_LDFLAGS
+    LIBS=$save_LIBS
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP"; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report what library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test no = "$can_build_shared" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test yes = "$enable_shared" && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test ia64 != "$host_cpu"; then
+      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+      yes,aix,yes) ;;			# shared object as lib.so file only
+      yes,svr4,*) ;;			# shared object as lib.so archive member only
+      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+      esac
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test yes = "$enable_shared" || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+
+      if test -n "$CXX" && ( test no != "$CXX" &&
+    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+    (test g++ != "$CXX"))); then
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if ${ac_cv_prog_CXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer  to  if __STDC__ is defined, since
+  #  exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include 
+#else
+# include 
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer  to  if __STDC__ is defined, since
+  #  exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include 
+#else
+# include 
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+  _lt_caught_CXX_error=yes
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+compiler_needs_object_CXX=no
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_direct_absolute_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+inherit_rpath_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+reload_flag_CXX=$reload_flag
+reload_cmds_CXX=$reload_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+  # save warnings/boilerplate of simple test code
+  ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+  ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
+  compiler=$CC
+  compiler_CXX=$CC
+  func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test yes = "$GXX"; then
+      lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+    else
+      lt_prog_compiler_no_builtin_flag_CXX=
+    fi
+
+    if test yes = "$GXX"; then
+      # Set up default GNU C++ configuration
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return, which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD=$ac_prog
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test yes = "$with_gnu_ld"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD=$ac_dir/$ac_prog
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 &5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 &5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test yes = "$with_gnu_ld"; then
+        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+
+        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+        export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='$wl'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+        else
+          whole_archive_flag_spec_CXX=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+    ld_shlibs_CXX=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+      aix[4-9]*)
+        if test ia64 = "$host_cpu"; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # have runtime linking enabled, and use it for executables.
+          # For shared libraries, we enable/disable runtime linking
+          # depending on the kind of the shared library created -
+          # when "with_aix_soname,aix_use_runtimelinking" is:
+          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "aix,yes"  lib.so          shared, rtl:yes, for executables
+          #            lib.a           static archive
+          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+          #            lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a(lib.so.V) shared, rtl:no
+          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a           static archive
+          case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
+	      # so we don't have lib.a shared libs to link our executables.
+	      # We have to force runtime linking in this case.
+	      aix_use_runtimelinking=yes
+	      LDFLAGS="$LDFLAGS -Wl,-brtl"
+	    fi
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        archive_cmds_CXX=''
+        hardcode_direct_CXX=yes
+        hardcode_direct_absolute_CXX=yes
+        hardcode_libdir_separator_CXX=':'
+        link_all_deplibs_CXX=yes
+        file_list_spec_CXX='$wl-f,'
+        case $with_aix_soname,$aix_use_runtimelinking in
+        aix,*) ;;	# no import file
+        svr4,* | *,yes) # use import file
+          # The Import File defines what to hardcode.
+          hardcode_direct_CXX=no
+          hardcode_direct_absolute_CXX=no
+          ;;
+        esac
+
+        if test yes = "$GXX"; then
+          case $host_os in aix4.[012]|aix4.[012].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`$CC -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    hardcode_direct_CXX=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    hardcode_minus_L_CXX=yes
+	    hardcode_libdir_flag_spec_CXX='-L$libdir'
+	    hardcode_libdir_separator_CXX=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test yes = "$aix_use_runtimelinking"; then
+	    shared_flag=$shared_flag' $wl-G'
+	  fi
+	  # Need to ensure runtime linking is disabled for the traditional
+	  # shared library, or the linker may eventually find shared libraries
+	  # /with/ Import File - we do not want to mix them.
+	  shared_flag_aix='-shared'
+	  shared_flag_svr4='-shared $wl-G'
+        else
+          # not using gcc
+          if test ia64 = "$host_cpu"; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test yes = "$aix_use_runtimelinking"; then
+	      shared_flag='$wl-G'
+	    else
+	      shared_flag='$wl-bM:SRE'
+	    fi
+	    shared_flag_aix='$wl-bM:SRE'
+	    shared_flag_svr4='$wl-G'
+          fi
+        fi
+
+        export_dynamic_flag_spec_CXX='$wl-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        always_export_symbols_CXX=yes
+	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          # The "-G" linker flag allows undefined symbols.
+          no_undefined_flag_CXX='-bernotok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath__CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=/usr/lib:/lib
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath__CXX
+fi
+
+          hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
+
+          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+        else
+          if test ia64 = "$host_cpu"; then
+	    hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib'
+	    allow_undefined_flag_CXX="-z nodefs"
+	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath__CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=/usr/lib:/lib
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath__CXX
+fi
+
+	    hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    no_undefined_flag_CXX=' $wl-bernotok'
+	    allow_undefined_flag_CXX=' $wl-berok'
+	    if test yes = "$with_gnu_ld"; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      whole_archive_flag_spec_CXX='$convenience'
+	    fi
+	    archive_cmds_need_lc_CXX=yes
+	    archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+	    # -brtl affects multiple linker settings, -berok does not and is overridden later
+	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+	    if test svr4 != "$with_aix_soname"; then
+	      # This is similar to how AIX traditionally builds its shared
+	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+	    fi
+	    if test aix != "$with_aix_soname"; then
+	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+	    else
+	      # used by -dlpreopen to get the symbols
+	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+	    fi
+	    archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  allow_undefined_flag_CXX=unsupported
+	  # Joseph Beckenbach  says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	else
+	  ld_shlibs_CXX=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  ld_shlibs_CXX=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+	case $GXX,$cc_basename in
+	,cl* | no,cl*)
+	  # Native MSVC
+	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+	  # no search path for DLLs.
+	  hardcode_libdir_flag_spec_CXX=' '
+	  allow_undefined_flag_CXX=unsupported
+	  always_export_symbols_CXX=yes
+	  file_list_spec_CXX='@'
+	  # Tell ltmain to make .lib files, not .a files.
+	  libext=lib
+	  # Tell ltmain to make .dll files, not .so files.
+	  shrext_cmds=.dll
+	  # FIXME: Setting linknames here is a bad hack.
+	  archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+	  archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+              cp "$export_symbols" "$output_objdir/$soname.def";
+              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+            else
+              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+            fi~
+            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+            linknames='
+	  # The linker will not automatically build a static lib if we build a DLL.
+	  # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true'
+	  enable_shared_with_static_runtimes_CXX=yes
+	  # Don't use ranlib
+	  old_postinstall_cmds_CXX='chmod 644 $oldlib'
+	  postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~
+            lt_tool_outputfile="@TOOL_OUTPUT@"~
+            case $lt_outputfile in
+              *.exe|*.EXE) ;;
+              *)
+                lt_outputfile=$lt_outputfile.exe
+                lt_tool_outputfile=$lt_tool_outputfile.exe
+                ;;
+            esac~
+            func_to_tool_file "$lt_outputfile"~
+            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+              $RM "$lt_outputfile.manifest";
+            fi'
+	  ;;
+	*)
+	  # g++
+	  # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+	  # as there is no search path for DLLs.
+	  hardcode_libdir_flag_spec_CXX='-L$libdir'
+	  export_dynamic_flag_spec_CXX='$wl--export-all-symbols'
+	  allow_undefined_flag_CXX=unsupported
+	  always_export_symbols_CXX=no
+	  enable_shared_with_static_runtimes_CXX=yes
+
+	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+	    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	    # If the export-symbols file already is a .def file, use it as
+	    # is; otherwise, prepend EXPORTS...
+	    archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+              cp $export_symbols $output_objdir/$soname.def;
+            else
+              echo EXPORTS > $output_objdir/$soname.def;
+              cat $export_symbols >> $output_objdir/$soname.def;
+            fi~
+            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	  else
+	    ld_shlibs_CXX=no
+	  fi
+	  ;;
+	esac
+	;;
+      darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc_CXX=no
+  hardcode_direct_CXX=no
+  hardcode_automatic_CXX=yes
+  hardcode_shlibpath_var_CXX=unsupported
+  if test yes = "$lt_cv_ld_force_load"; then
+    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec_CXX=''
+  fi
+  link_all_deplibs_CXX=yes
+  allow_undefined_flag_CXX=$_lt_dar_allow_undefined
+  case $cc_basename in
+     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test yes = "$_lt_dar_can_shared"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+    module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+    archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+       if test yes != "$lt_cv_apple_cc_single_mod"; then
+      archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+      archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+    fi
+
+  else
+  ld_shlibs_CXX=no
+  fi
+
+	;;
+
+      os2*)
+	hardcode_libdir_flag_spec_CXX='-L$libdir'
+	hardcode_minus_L_CXX=yes
+	allow_undefined_flag_CXX=unsupported
+	shrext_cmds=.dll
+	archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	  emximp -o $lib $output_objdir/$libname.def'
+	archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+	  prefix_cmds="$SED"~
+	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
+	    prefix_cmds="$prefix_cmds -e 1d";
+	  fi~
+	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+	  emximp -o $lib $output_objdir/$libname.def'
+	old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+	enable_shared_with_static_runtimes_CXX=yes
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        ld_shlibs_CXX=no
+        ;;
+
+      freebsd-elf*)
+        archive_cmds_need_lc_CXX=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        ld_shlibs_CXX=yes
+        ;;
+
+      haiku*)
+        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+        link_all_deplibs_CXX=yes
+        ;;
+
+      hpux9*)
+        hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
+        hardcode_libdir_separator_CXX=:
+        export_dynamic_flag_spec_CXX='$wl-E'
+        hardcode_direct_CXX=yes
+        hardcode_minus_L_CXX=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            ld_shlibs_CXX=no
+            ;;
+          aCC*)
+            archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test yes = "$GXX"; then
+              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              ld_shlibs_CXX=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test no = "$with_gnu_ld"; then
+	  hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
+	  hardcode_libdir_separator_CXX=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      export_dynamic_flag_spec_CXX='$wl-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            hardcode_direct_CXX=no
+            hardcode_shlibpath_var_CXX=no
+            ;;
+          *)
+            hardcode_direct_CXX=yes
+            hardcode_direct_absolute_CXX=yes
+            hardcode_minus_L_CXX=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+          *)
+	    if test yes = "$GXX"; then
+	      if test no = "$with_gnu_ld"; then
+	        case $host_cpu in
+	          hppa*64*)
+	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      ld_shlibs_CXX=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[3-9]*)
+	hardcode_direct_CXX=no
+	hardcode_shlibpath_var_CXX=no
+	hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+	export_dynamic_flag_spec_CXX='$wl-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test yes = "$GXX"; then
+	      if test no = "$with_gnu_ld"; then
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	      else
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+	      fi
+	    fi
+	    link_all_deplibs_CXX=yes
+	    ;;
+        esac
+        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+        hardcode_libdir_separator_CXX=:
+        inherit_rpath_CXX=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+		archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+		archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    archive_cmds_need_lc_CXX=no
+	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+	    whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
+	      prelink_cmds_CXX='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+	      old_archive_cmds_CXX='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+                $RANLIB $oldlib'
+	      archive_cmds_CXX='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	      archive_expsym_cmds_CXX='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 and above use weak symbols
+	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir'
+	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+	    whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+	    archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+	    hardcode_libdir_separator_CXX=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+	    ;;
+	  xl* | mpixl* | bgxl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+	    archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+	    if test yes = "$supports_anon_versioning"; then
+	      archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
+                cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+                echo "local: *; };" >> $output_objdir/$libname.ver~
+                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      no_undefined_flag_CXX=' -zdefs'
+	      archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+	      hardcode_libdir_flag_spec_CXX='-R$libdir'
+	      whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+	      compiler_needs_object_CXX=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='func_echo_all'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	ld_shlibs_CXX=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  hardcode_libdir_flag_spec_CXX='-R$libdir'
+	  hardcode_direct_CXX=yes
+	  hardcode_shlibpath_var_CXX=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        ld_shlibs_CXX=yes
+	;;
+
+      openbsd* | bitrig*)
+	if test -f /usr/libexec/ld.so; then
+	  hardcode_direct_CXX=yes
+	  hardcode_shlibpath_var_CXX=no
+	  hardcode_direct_absolute_CXX=yes
+	  archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+	    archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+	    export_dynamic_flag_spec_CXX='$wl-E'
+	    whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=func_echo_all
+	else
+	  ld_shlibs_CXX=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+	    hardcode_libdir_separator_CXX=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
+	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+		;;
+	      *)
+	        allow_undefined_flag_CXX=' -expect_unresolved \*'
+	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+	        archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+                  echo "-hidden">> $lib.exp~
+                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+                  $RM $lib.exp'
+	        hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+		;;
+	    esac
+
+	    hardcode_libdir_separator_CXX=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+	  *)
+	    if test yes,no = "$GXX,$with_gnu_ld"; then
+	      allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
+	      case $host in
+	        osf3*)
+	          archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+		  ;;
+	        *)
+	          archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+	      hardcode_libdir_separator_CXX=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      ld_shlibs_CXX=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC* | sunCC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            archive_cmds_need_lc_CXX=yes
+	    no_undefined_flag_CXX=' -zdefs'
+	    archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    hardcode_libdir_flag_spec_CXX='-R$libdir'
+	    hardcode_shlibpath_var_CXX=no
+	    case $host_os in
+	      solaris2.[0-5] | solaris2.[0-5].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands '-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    link_all_deplibs_CXX=yes
+
+	    output_verbose_link_cmd='func_echo_all'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test yes,no = "$GXX,$with_gnu_ld"; then
+	      no_undefined_flag_CXX=' $wl-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	      else
+	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
+	        # platform.
+	        archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+	      fi
+
+	      hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir'
+	      case $host_os in
+		solaris2.[0-5] | solaris2.[0-5].*) ;;
+		*)
+		  whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_CXX='$wl-z,text'
+      archive_cmds_need_lc_CXX=no
+      hardcode_shlibpath_var_CXX=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We CANNOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	no_undefined_flag_CXX='$wl-z,text'
+	allow_undefined_flag_CXX='$wl-z,nodefs'
+	archive_cmds_need_lc_CXX=no
+	hardcode_shlibpath_var_CXX=no
+	hardcode_libdir_flag_spec_CXX='$wl-R,$libdir'
+	hardcode_libdir_separator_CXX=':'
+	link_all_deplibs_CXX=yes
+	export_dynamic_flag_spec_CXX='$wl-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
+              '"$old_archive_cmds_CXX"
+	    reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
+              '"$reload_cmds_CXX"
+	    ;;
+	  *)
+	    archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+    esac
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+    test no = "$ld_shlibs_CXX" && can_build_shared=no
+
+    GCC_CXX=$GXX
+    LD_CXX=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    # Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $prev$p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test x-L = "$p" ||
+          test x-R = "$p"; then
+	 prev=$p
+	 continue
+       fi
+
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
+       if test no = "$pre_test_object_deps_done"; then
+	 case $prev in
+	 -L | -R)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$compiler_lib_search_path_CXX"; then
+	     compiler_lib_search_path_CXX=$prev$p
+	   else
+	     compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$postdeps_CXX"; then
+	   postdeps_CXX=$prev$p
+	 else
+	   postdeps_CXX="${postdeps_CXX} $prev$p"
+	 fi
+       fi
+       prev=
+       ;;
+
+    *.lto.$objext) ;; # Ignore GCC LTO objects
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test no = "$pre_test_object_deps_done"; then
+	 if test -z "$predep_objects_CXX"; then
+	   predep_objects_CXX=$p
+	 else
+	   predep_objects_CXX="$predep_objects_CXX $p"
+	 fi
+       else
+	 if test -z "$postdep_objects_CXX"; then
+	   postdep_objects_CXX=$p
+	 else
+	   postdep_objects_CXX="$postdep_objects_CXX $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  predep_objects_CXX=
+  postdep_objects_CXX=
+  postdeps_CXX=
+  ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+ compiler_lib_search_dirs_CXX=
+if test -n "${compiler_lib_search_path_CXX}"; then
+ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+
+  # C++ specific cases for pic, static, wl, etc.
+  if test yes = "$GXX"; then
+    lt_prog_compiler_wl_CXX='-Wl,'
+    lt_prog_compiler_static_CXX='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static_CXX='-Bstatic'
+      fi
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic_CXX='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+      case $host_os in
+      os2*)
+	lt_prog_compiler_static_CXX='$wl-static'
+	;;
+      esac
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_CXX='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      lt_prog_compiler_pic_CXX=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static_CXX=
+      ;;
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic_CXX=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	lt_prog_compiler_pic_CXX='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic_CXX='-fPIC -shared'
+      ;;
+    *)
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[4-9]*)
+	# All AIX code is PIC.
+	if test ia64 = "$host_cpu"; then
+	  # AIX 5 now supports IA64 processor
+	  lt_prog_compiler_static_CXX='-Bstatic'
+	else
+	  lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+	# This hack is so that the source file can tell whether it is being
+	# built for inclusion in a dll (and should export symbols for example).
+	lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
+	    if test ia64 != "$host_cpu"; then
+	      lt_prog_compiler_pic_CXX='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      lt_prog_compiler_pic_CXX='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    lt_prog_compiler_wl_CXX='--backend -Wl,'
+	    lt_prog_compiler_pic_CXX='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64, which still supported -KPIC.
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-fPIC'
+	    lt_prog_compiler_static_CXX='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-fpic'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    lt_prog_compiler_pic_CXX=
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    ;;
+	  xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-qpic'
+	    lt_prog_compiler_static_CXX='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      lt_prog_compiler_pic_CXX='-KPIC'
+	      lt_prog_compiler_static_CXX='-Bstatic'
+	      lt_prog_compiler_wl_CXX='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    lt_prog_compiler_pic_CXX='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd* | netbsdelf*-gnu)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        lt_prog_compiler_pic_CXX='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    lt_prog_compiler_wl_CXX='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    lt_prog_compiler_pic_CXX=
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC* | sunCC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    lt_prog_compiler_wl_CXX='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    lt_prog_compiler_pic_CXX='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    lt_prog_compiler_pic_CXX='-pic'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	lt_prog_compiler_can_build_shared_CXX=no
+	;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms that do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_CXX=
+    ;;
+  *)
+    lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+    ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; }
+lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works_CXX=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works_CXX=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then
+    case $lt_prog_compiler_pic_CXX in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+     esac
+else
+    lt_prog_compiler_pic_CXX=
+     lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works_CXX=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works_CXX=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works_CXX=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then
+    :
+else
+    lt_prog_compiler_static_CXX=
+fi
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -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:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $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
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test no = "$hard_links"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  case $host_os in
+  aix[4-9]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+    # Without the "-l" option, or with the "-B" option, AIX nm treats
+    # weak defined symbols like other global defined symbols, whereas
+    # GNU nm marks them as "W".
+    # While the 'weak' keyword is ignored in the Export File, we need
+    # it in the Import File for the 'aix-soname' feature, so we have
+    # to replace the "-B" option with "-P" for AIX nm.
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+    else
+      export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    export_symbols_cmds_CXX=$ltdll_cmds
+    ;;
+  cygwin* | mingw* | cegcc*)
+    case $cc_basename in
+    cl*)
+      exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+      ;;
+    *)
+      export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+      ;;
+    esac
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    link_all_deplibs_CXX=no
+    ;;
+  *)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+    ;;
+  esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+test no = "$ld_shlibs_CXX" && can_build_shared=no
+
+with_gnu_ld_CXX=$with_gnu_ld
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_CXX=yes
+
+  if test yes,yes = "$GCC,$enable_shared"; then
+    case $archive_cmds_CXX in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl_CXX
+	  pic_flag=$lt_prog_compiler_pic_CXX
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+	  allow_undefined_flag_CXX=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc_CXX=no
+	  else
+	    lt_cv_archive_cmds_need_lc_CXX=yes
+	  fi
+	  allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+      archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='$libname$release$shared_ext$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test ia64 = "$host_cpu"; then
+    # AIX 5 supports IA64
+    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line '#! .'.  This would cause the generated library to
+    # depend on '.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # Using Import Files as archive members, it is possible to support
+    # filename-based versioning of shared library archives on AIX. While
+    # this would work for both with and without runtime linking, it will
+    # prevent static linking of such archives. So we do filename-based
+    # shared library versioning with .so extension only, which is used
+    # when both runtime linking and shared linking is enabled.
+    # Unfortunately, runtime linking may impact performance, so we do
+    # not want this to be the default eventually. Also, we use the
+    # versioned .so libs for executables only if there is the -brtl
+    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+    # To allow for filename-based versioning support, we need to create
+    # libNAME.so.V as an archive file, containing:
+    # *) an Import File, referring to the versioned filename of the
+    #    archive as well as the shared archive member, telling the
+    #    bitwidth (32 or 64) of that shared object, and providing the
+    #    list of exported symbols of that shared object, eventually
+    #    decorated with the 'weak' keyword
+    # *) the shared object with the F_LOADONLY flag set, to really avoid
+    #    it being seen by the linker.
+    # At run time we better use the real file rather than another symlink,
+    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+    case $with_aix_soname,$aix_use_runtimelinking in
+    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    aix,yes) # traditional libtool
+      dynamic_linker='AIX unversionable lib.so'
+      # If using run time linking (on AIX 4.2 or later) use lib.so
+      # instead of lib.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      ;;
+    aix,no) # traditional AIX only
+      dynamic_linker='AIX lib.a(lib.so.V)'
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      ;;
+    svr4,*) # full svr4 only
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,yes) # both, prefer svr4
+      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # unpreferred sharedlib libNAME.a needs extra handling
+      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,no) # both, prefer aix
+      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+      ;;
+    esac
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='$libname$shared_ext'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+    library_names_spec='$libname.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec=$LIB
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$major$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+      soname_spec='$libname$release$shared_ext$major'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    if test 32 = "$HPUX_IA64_MODE"; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+    fi
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test yes = "$lt_cv_prog_gnu_ld"; then
+		version_type=linux # correct to gnu/linux during the next big refactor
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+linux*android*)
+  version_type=none # Android doesn't support versioned libraries.
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext'
+  soname_spec='$libname$release$shared_ext'
+  finish_cmds=
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  dynamic_linker='Android linker'
+  # Don't embed -rpath directories since the linker doesn't support them.
+  hardcode_libdir_flag_spec_CXX='-L$libdir'
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Ideally, we could use ldconfig to report *all* directores which are
+  # searched for libraries, however this is still not possible.  Aside from not
+  # being certain /sbin/ldconfig is available, command
+  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+  # even though it is searched at run-time.  Try to do the best guess by
+  # appending ld.so.conf contents (and includes) to the search path.
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd* | bitrig*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec=/usr/lib
+  need_lib_prefix=no
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    need_version=no
+  else
+    need_version=yes
+  fi
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+os2*)
+  libname_spec='$name'
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+  # OS/2 can only load a DLL with a base name of 8 characters or less.
+  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+    v=$($ECHO $release$versuffix | tr -d .-);
+    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+    $ECHO $n$v`$shared_ext'
+  library_names_spec='${libname}_dll.$libext'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=BEGINLIBPATH
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  postinstall_cmds='base_file=`basename \$file`~
+    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+    dldir=$destdir/`dirname \$dlpath`~
+    test -d \$dldir || mkdir -p \$dldir~
+    $install_prog $dir/$dlname \$dldir/$dlname~
+    chmod a+x \$dldir/$dlname~
+    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+    fi'
+  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+    dlpath=$dir/\$dldll~
+    $RM \$dlpath'
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test yes = "$with_gnu_ld"; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec; then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+    soname_spec='$libname$shared_ext.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=sco
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test yes = "$with_gnu_ld"; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" ||
+   test -n "$runpath_var_CXX" ||
+   test yes = "$hardcode_automatic_CXX"; then
+
+  # We can hardcode non-existent directories.
+  if test no != "$hardcode_direct_CXX" &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" &&
+     test no != "$hardcode_minus_L_CXX"; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_CXX=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_CXX=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_CXX=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
+$as_echo "$hardcode_action_CXX" >&6; }
+
+if test relink = "$hardcode_action_CXX" ||
+   test yes = "$inherit_rpath_CXX"; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+     test no = "$enable_shared"; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5
+$as_echo_n "checking for __attribute__... " >&6; }
+  if ${ac_cv___attribute__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+       static void foo(void) __attribute__ ((unused));
+       void foo(void) { exit(1); }
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv___attribute__=yes
+else
+  ac_cv___attribute__=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+  if test "$ac_cv___attribute__" = "yes"; then
+
+$as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h
+
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__" >&5
+$as_echo "$ac_cv___attribute__" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((aligned(N))) on functions" >&5
+$as_echo_n "checking for __attribute__((aligned(N))) on functions... " >&6; }
+if ${ac_cv___attribute__aligned_fn+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+     void foo(void) __attribute__((aligned(128)));
+     void foo(void) { exit(1); }
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv___attribute__aligned_fn=yes
+else
+  ac_cv___attribute__aligned_fn=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "$ac_cv___attribute__aligned_fn" = "yes"; then
+
+$as_echo "#define HAVE___ATTRIBUTE__ALIGNED_FN 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__aligned_fn" >&5
+$as_echo "$ac_cv___attribute__aligned_fn" >&6; }
+
+
+# Check whether some low-level functions/files are available
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+#include 
+#include 
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+# TODO(csilvers): we could remove a lot when WITH_CPU_PROFILER etc is "no".
+ac_fn_c_check_type "$LINENO" "struct mallinfo" "ac_cv_type_struct_mallinfo" "#include 
+"
+if test "x$ac_cv_type_struct_mallinfo" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MALLINFO 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "Elf32_Versym" "ac_cv_type_Elf32_Versym" "#include 
+"
+if test "x$ac_cv_type_Elf32_Versym" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ELF32_VERSYM 1
+_ACEOF
+
+
+fi
+   # for vdso_support.h
+for ac_func in sbrk
+do :
+  ac_fn_c_check_func "$LINENO" "sbrk" "ac_cv_func_sbrk"
+if test "x$ac_cv_func_sbrk" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SBRK 1
+_ACEOF
+
+fi
+done
+            # for tcmalloc to get memory
+for ac_func in __sbrk
+do :
+  ac_fn_c_check_func "$LINENO" "__sbrk" "ac_cv_func___sbrk"
+if test "x$ac_cv_func___sbrk" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE___SBRK 1
+_ACEOF
+
+fi
+done
+          # for tcmalloc to get memory
+for ac_func in geteuid
+do :
+  ac_fn_c_check_func "$LINENO" "geteuid" "ac_cv_func_geteuid"
+if test "x$ac_cv_func_geteuid" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETEUID 1
+_ACEOF
+
+fi
+done
+         # for turning off services when run as root
+for ac_func in fork
+do :
+  ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
+if test "x$ac_cv_func_fork" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FORK 1
+_ACEOF
+
+fi
+done
+            # for the pthread_atfork setup
+for ac_header in features.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "features.h" "ac_cv_header_features_h" "$ac_includes_default"
+if test "x$ac_cv_header_features_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FEATURES_H 1
+_ACEOF
+
+fi
+
+done
+    # for vdso_support.h, __GLIBC__ macros
+for ac_header in malloc.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_malloc_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+      # some systems define stuff there, others not
+for ac_header in glob.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
+if test "x$ac_cv_header_glob_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GLOB_H 1
+_ACEOF
+
+fi
+
+done
+        # for heap-profile-table (cleaning up profiles)
+for ac_header in execinfo.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_execinfo_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_EXECINFO_H 1
+_ACEOF
+
+fi
+
+done
+    # for stacktrace? and heapchecker_unittest
+for ac_header in unwind.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "unwind.h" "ac_cv_header_unwind_h" "$ac_includes_default"
+if test "x$ac_cv_header_unwind_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UNWIND_H 1
+_ACEOF
+
+fi
+
+done
+      # for stacktrace
+for ac_header in sched.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default"
+if test "x$ac_cv_header_sched_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SCHED_H 1
+_ACEOF
+
+fi
+
+done
+       # for being nice in our spinlock code
+for ac_header in conflict-signal.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "conflict-signal.h" "ac_cv_header_conflict_signal_h" "$ac_includes_default"
+if test "x$ac_cv_header_conflict_signal_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CONFLICT_SIGNAL_H 1
+_ACEOF
+
+fi
+
+done
+      # defined on some windows platforms?
+for ac_header in sys/prctl.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_prctl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PRCTL_H 1
+_ACEOF
+
+fi
+
+done
+   # for thread_lister (needed by leak-checker)
+for ac_header in linux/ptrace.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/ptrace.h" "ac_cv_header_linux_ptrace_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_ptrace_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_PTRACE_H 1
+_ACEOF
+
+fi
+
+done
+# also needed by leak-checker
+for ac_header in sys/syscall.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/syscall.h" "ac_cv_header_sys_syscall_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_syscall_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_SYSCALL_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/socket.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socket_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_SOCKET_H 1
+_ACEOF
+
+fi
+
+done
+  # optional; for forking out to symbolizer
+for ac_header in sys/wait.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_wait_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_WAIT_H 1
+_ACEOF
+
+fi
+
+done
+    # optional; for forking out to symbolizer
+for ac_header in poll.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default"
+if test "x$ac_cv_header_poll_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_POLL_H 1
+_ACEOF
+
+fi
+
+done
+        # optional; for forking out to symbolizer
+for ac_header in fcntl.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcntl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FCNTL_H 1
+_ACEOF
+
+fi
+
+done
+       # for tcmalloc_unittest
+for ac_header in grp.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "grp.h" "ac_cv_header_grp_h" "$ac_includes_default"
+if test "x$ac_cv_header_grp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GRP_H 1
+_ACEOF
+
+fi
+
+done
+         # for heapchecker_unittest
+for ac_header in pwd.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pwd.h" "ac_cv_header_pwd_h" "$ac_includes_default"
+if test "x$ac_cv_header_pwd_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PWD_H 1
+_ACEOF
+
+fi
+
+done
+         # for heapchecker_unittest
+for ac_header in sys/resource.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_resource_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_RESOURCE_H 1
+_ACEOF
+
+fi
+
+done
+         # for memalign_unittest.cc
+for ac_header in sys/cdefs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/cdefs.h" "ac_cv_header_sys_cdefs_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_cdefs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_CDEFS_H 1
+_ACEOF
+
+fi
+
+done
+   # Where glibc defines __THROW
+# We also need /, but we get those from
+# AC_PC_FROM_UCONTEXT, below.
+
+# 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_fn_c_check_decl "$LINENO" "cfree" "ac_cv_have_decl_cfree" "#define _XOPEN_SOURCE 600
+                #include 
+                #include 
+"
+if test "x$ac_cv_have_decl_cfree" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_CFREE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "posix_memalign" "ac_cv_have_decl_posix_memalign" "#define _XOPEN_SOURCE 600
+                #include 
+                #include 
+"
+if test "x$ac_cv_have_decl_posix_memalign" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_POSIX_MEMALIGN $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "memalign" "ac_cv_have_decl_memalign" "#define _XOPEN_SOURCE 600
+                #include 
+                #include 
+"
+if test "x$ac_cv_have_decl_memalign" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_MEMALIGN $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "valloc" "ac_cv_have_decl_valloc" "#define _XOPEN_SOURCE 600
+                #include 
+                #include 
+"
+if test "x$ac_cv_have_decl_valloc" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_VALLOC $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "pvalloc" "ac_cv_have_decl_pvalloc" "#define _XOPEN_SOURCE 600
+                #include 
+                #include 
+"
+if test "x$ac_cv_have_decl_pvalloc" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_PVALLOC $ac_have_decl
+_ACEOF
+
+
+if test "$ac_cv_type_struct_mallinfo" = yes; then
+  ac_cv_have_struct_mallinfo=1
+   # gperftools/tcmalloc.h needs this
+else
+  ac_cv_have_struct_mallinfo=0
+
+fi
+
+# We hardcode HAVE_MMAP to 1. There are no interesting systems anymore
+# without functional mmap. And our windows (except mingw) builds
+# aren't using autoconf. So we keep HAVE_MMAP define, but only to
+# distingush windows and rest.
+case "$host" in
+   *-mingw*) default_emergency_malloc=no;;
+   *) default_emergency_malloc=yes
+
+$as_echo "#define HAVE_MMAP 1" >>confdefs.h
+
+esac
+
+# If AtomicWord != Atomic32, we need to define two versions of all the
+# atomicops functions.  If they're the same, we want to define only one.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if int32_t is the same type as intptr_t" >&5
+$as_echo_n "checking if int32_t is the same type as intptr_t... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+int32_t v1 = 0; intptr_t v2 = 0; return (&v1 - &v2)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define INT32_EQUALS_INTPTR 1" >>confdefs.h
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core 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).  But don't
+# bother if we're not doing cpu-profiling.
+# [*] means that we've not actually tested one of these systems
+if test "$enable_cpu_profiler" = yes; then
+  for ac_header in ucontext.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ucontext.h" "ac_cv_header_ucontext_h" "$ac_includes_default"
+if test "x$ac_cv_header_ucontext_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UCONTEXT_H 1
+_ACEOF
+
+fi
+
+done
+
+   # Redhat 7 has , but it barfs if we #include it directly
+   # (this was fixed in later redhats).   works fine, so use that.
+   if grep "Red Hat Linux release 7" /etc/redhat-release >/dev/null 2>&1; then
+
+$as_echo "#define HAVE_SYS_UCONTEXT_H 0" >>confdefs.h
+
+     ac_cv_header_sys_ucontext_h=no
+   else
+     for ac_header in sys/ucontext.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/ucontext.h" "ac_cv_header_sys_ucontext_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ucontext_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_UCONTEXT_H 1
+_ACEOF
+
+fi
+
+done
+       # ucontext on OS X 10.6 (at least)
+   fi
+   for ac_header in cygwin/signal.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "cygwin/signal.h" "ac_cv_header_cygwin_signal_h" "$ac_includes_default"
+if test "x$ac_cv_header_cygwin_signal_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CYGWIN_SIGNAL_H 1
+_ACEOF
+
+fi
+
+done
+        # ucontext on cywgin
+   for ac_header in asm/ptrace.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "asm/ptrace.h" "ac_cv_header_asm_ptrace_h" "$ac_includes_default"
+if test "x$ac_cv_header_asm_ptrace_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ASM_PTRACE_H 1
+_ACEOF
+
+fi
+
+done
+           # get ptrace macros, e.g. PT_NIP
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to access the program counter from a struct ucontext" >&5
+$as_echo_n "checking how to access the program counter from a struct ucontext... " >&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.pc"               # Linux (mips)
+   pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[PT_NIP]" # Linux (ppc)
+   pc_fields="$pc_fields uc_mcontext.__gregs[REG_PC]"  # Linux (riscv64)
+   pc_fields="$pc_fields uc_mcontext.psw.addr"         # Linux (s390)
+   pc_fields="$pc_fields uc_mcontext.gregs[R15]"     # Linux (arm old [untested])
+   pc_fields="$pc_fields uc_mcontext.arm_pc"           # Linux (arm arch 5)
+   pc_fields="$pc_fields uc_mcontext.cr0_hi"           # Linux (e2k)
+   pc_fields="$pc_fields uc_mcontext.gp_regs[PT_NIP]"  # Suse SLES 11 (ppc64)
+   pc_fields="$pc_fields uc_mcontext.mc_eip"           # FreeBSD (i386)
+   pc_fields="$pc_fields uc_mcontext.mc_srr0"          # FreeBSD (powerpc, powerpc64)
+   pc_fields="$pc_fields uc_mcontext.mc_rip"           # FreeBSD (x86_64 [untested])
+   pc_fields="$pc_fields uc_mcontext.__gregs[_REG_EIP]"  # NetBSD (i386)
+   pc_fields="$pc_fields uc_mcontext.__gregs[_REG_RIP]"  # NetBSD (x86_64)
+   pc_fields="$pc_fields uc_mcontext->ss.eip"          # OS X (i386, <=10.4)
+   pc_fields="$pc_fields uc_mcontext->__ss.__eip"      # OS X (i386, >=10.5)
+   pc_fields="$pc_fields uc_mcontext->ss.rip"          # OS X (x86_64)
+   pc_fields="$pc_fields uc_mcontext->__ss.__rip"      # OS X (>=10.5 [untested])
+   pc_fields="$pc_fields uc_mcontext->ss.srr0"         # OS X (ppc, ppc64 [untested])
+   pc_fields="$pc_fields uc_mcontext->__ss.__srr0"     # OS X (>=10.5 [untested])
+   pc_fields="$pc_fields uc_mcontext->__ss.__pc"       # OS X (arm64)
+   pc_field_found=false
+   for pc_field in $pc_fields; do
+     if ! $pc_field_found; then
+       # Prefer sys/ucontext.h to ucontext.h, for OS X's sake.
+       if test "x$ac_cv_header_cygwin_signal_h" = xyes; then
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+                         #include 
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       elif test "x$ac_cv_header_asm_ptrace_h" = xyes -a "x$ac_cv_header_sys_ucontext_h" = xyes; then
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+                         #include 
+                         #include 
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       elif test "x$ac_cv_header_sys_ucontext_h" = xyes; then
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+                        #include 
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       elif test "x$ac_cv_header_ucontext_h" = xyes; then
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+                         #include 
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       else     # hope some standard header gives it to us
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       fi
+     fi
+   done
+   if ! $pc_field_found; then
+     pc_fields="           sc_eip"  # OpenBSD (i386)
+     pc_fields="$pc_fields sc_rip"  # OpenBSD (x86_64)
+     for pc_field in $pc_fields; do
+       if ! $pc_field_found; then
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pc_field" >&5
+$as_echo "$pc_field" >&6; }
+                        pc_field_found=true
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       fi
+     done
+   fi
+   if ! $pc_field_found; then
+     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find the PC.  Will not try to compile libprofiler..." >&5
+$as_echo "$as_me: WARNING: Could not find the PC.  Will not try to compile libprofiler..." >&2;};
+                      enable_cpu_profiler=no
+   fi
+fi
+
+# Some tests test the behavior of .so files, and only make sense for dynamic.
+ if test "$enable_static" = yes; then
+  ENABLE_STATIC_TRUE=
+  ENABLE_STATIC_FALSE='#'
+else
+  ENABLE_STATIC_TRUE='#'
+  ENABLE_STATIC_FALSE=
+fi
+
+
+# We want to link in libunwind if it is enabled and exists.
+UNWIND_LIBS=
+if test "$enable_libunwind" = yes; then
+  for ac_header in libunwind.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libunwind.h" "ac_cv_header_libunwind_h" "$ac_includes_default"
+if test "x$ac_cv_header_libunwind_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUNWIND_H 1
+_ACEOF
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lunwind" >&5
+$as_echo_n "checking for backtrace in -lunwind... " >&6; }
+if ${ac_cv_lib_unwind_backtrace+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lunwind  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char backtrace ();
+int
+main ()
+{
+return backtrace ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_unwind_backtrace=yes
+else
+  ac_cv_lib_unwind_backtrace=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unwind_backtrace" >&5
+$as_echo "$ac_cv_lib_unwind_backtrace" >&6; }
+if test "x$ac_cv_lib_unwind_backtrace" = xyes; then :
+  UNWIND_LIBS=-lunwind
+fi
+
+                    will_use_libunwind=yes
+fi
+
+done
+
+fi
+
+
+# On x86_64, instead of libunwind, we can choose to compile with frame-pointers.
+# Check whether --enable-frame_pointers was given.
+if test "${enable_frame_pointers+set}" = set; then :
+  enableval=$enable_frame_pointers;
+else
+  enable_frame_pointers=no
+fi
+
+ if test "$enable_frame_pointers" = yes; then
+  ENABLE_FRAME_POINTERS_TRUE=
+  ENABLE_FRAME_POINTERS_FALSE='#'
+else
+  ENABLE_FRAME_POINTERS_TRUE='#'
+  ENABLE_FRAME_POINTERS_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 without frame pointers" >&5
+$as_echo_n "checking for x86 without frame pointers... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return __x86_64__ == 1 ? 0 : 1
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_x86_64=yes
+else
+  is_x86_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+omit_fp_by_default=no
+if test "$is_x86_64" = yes; then :
+  omit_fp_by_default=yes
+fi
+ if test "$omit_fp_by_default" = yes; then
+  OMIT_FP_BY_DEFAULT_TRUE=
+  OMIT_FP_BY_DEFAULT_FALSE='#'
+else
+  OMIT_FP_BY_DEFAULT_TRUE='#'
+  OMIT_FP_BY_DEFAULT_FALSE=
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $omit_fp_by_default" >&5
+$as_echo "$omit_fp_by_default" >&6; }
+
+# We need to know if we're i386 so we can turn on -mmms, which is not
+# on by default for i386 (it is for x86_64).
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return __i386__ == 1 ? 0 : 1
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  is_i386=yes
+else
+  is_i386=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test "$is_i386" = yes; then
+  I386_TRUE=
+  I386_FALSE='#'
+else
+  I386_TRUE='#'
+  I386_FALSE=
+fi
+
+
+# See if the compiler supports -Wno-unused-result.
+# Newer ubuntu's turn on -D_FORTIFY_SOURCE=2, enabling
+# __attribute__((warn_unused_result)) for things like write(),
+# which we don't care about.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports -Wno-unused-result" >&5
+$as_echo_n "checking if the compiler supports -Wno-unused-result... " >&6; }
+if ${perftools_cv_w_no_unused_result+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  OLD_CFLAGS="$CFLAGS"
+	        CFLAGS="$CFLAGS -Wno-error -Wunused-result"
+		# gcc doesn't warn about unknown flags unless it's
+		# also warning for some other purpose, hence the
+		# divide-by-0.  (We use -Wno-error to make sure the
+		# divide-by-0 doesn't cause this test to fail!)
+                #
+                # Also gcc is giving only warning for unknown flags of
+                # -Wno-XXX form. So in order to detect support we're
+                # using -Wunused-result which will cause gcc to give
+                # error which we can detect.
+	        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 1/0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  perftools_cv_w_no_unused_result=yes
+else
+  perftools_cv_w_no_unused_result=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	        CFLAGS="$OLD_CFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_w_no_unused_result" >&5
+$as_echo "$perftools_cv_w_no_unused_result" >&6; }
+ if test "$perftools_cv_w_no_unused_result" = yes; then
+  HAVE_W_NO_UNUSED_RESULT_TRUE=
+  HAVE_W_NO_UNUSED_RESULT_FALSE='#'
+else
+  HAVE_W_NO_UNUSED_RESULT_TRUE='#'
+  HAVE_W_NO_UNUSED_RESULT_FALSE=
+fi
+
+
+# Check whether --enable-deprecated-pprof was given.
+if test "${enable_deprecated_pprof+set}" = set; then :
+  enableval=$enable_deprecated_pprof; enable_pprof="$enableval"
+else
+  enable_pprof=yes
+fi
+
+
+ if test "x$enable_pprof" = xyes; then
+  INSTALL_PPROF_TRUE=
+  INSTALL_PPROF_FALSE='#'
+else
+  INSTALL_PPROF_TRUE='#'
+  INSTALL_PPROF_FALSE=
+fi
+
+
+# Check whether --enable-dynamic-sized-delete-support was given.
+if test "${enable_dynamic_sized_delete_support+set}" = set; then :
+  enableval=$enable_dynamic_sized_delete_support; enable_dyn_sized_delete="$enableval"
+else
+  enable_dyn_sized_delete=no
+fi
+
+
+if test "x$enable_dyn_sized_delete" = xyes; then :
+
+$as_echo "#define ENABLE_DYNAMIC_SIZED_DELETE 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-sized-delete was given.
+if test "${enable_sized_delete+set}" = set; then :
+  enableval=$enable_sized_delete; enable_sized_delete="$enableval"
+else
+  enable_sized_delete="no"
+fi
+
+if test "x$enable_sized_delete" = xyes; then :
+
+$as_echo "#define ENABLE_SIZED_DELETE 1" >>confdefs.h
+
+         { $as_echo "$as_me:${as_lineno-$LINENO}: Will build sized deallocation operators" >&5
+$as_echo "$as_me: Will build sized deallocation operators" >&6;}
+else
+  if test "x$enable_dyn_sized_delete" = xyes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Will build dynamically detected sized deallocation operators" >&5
+$as_echo "$as_me: Will build dynamically detected sized deallocation operators" >&6;}
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Will build sized deallocation operators that ignore size" >&5
+$as_echo "$as_me: Will build sized deallocation operators that ignore size" >&6;}
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++ compiler supports -fsized-deallocation" >&5
+$as_echo_n "checking if C++ compiler supports -fsized-deallocation... " >&6; }
+if ${perftools_cv_sized_deallocation_result+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+                OLD_CXXFLAGS="$CXXFLAGS"
+                CXXFLAGS="$CXXFLAGS -fsized-deallocation"
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#include 
+int
+main ()
+{
+static void (* volatile ptr)(void *, size_t) = ::operator delete; (*ptr)(0, 256);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  perftools_cv_sized_deallocation_result=yes
+else
+  perftools_cv_sized_deallocation_result=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+                CXXFLAGS="$OLD_CXXFLAGS"
+                ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_sized_deallocation_result" >&5
+$as_echo "$perftools_cv_sized_deallocation_result" >&6; }
+
+ if test "$perftools_cv_sized_deallocation_result" = yes; then
+  HAVE_SIZED_DEALLOCATION_TRUE=
+  HAVE_SIZED_DEALLOCATION_FALSE='#'
+else
+  HAVE_SIZED_DEALLOCATION_TRUE='#'
+  HAVE_SIZED_DEALLOCATION_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++ compiler supports std::align_val_t without options" >&5
+$as_echo_n "checking if C++ compiler supports std::align_val_t without options... " >&6; }
+if ${perftools_cv_have_align_val_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+(::operator delete)((::operator new)(256, std::align_val_t(16)), std::align_val_t(16))
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  perftools_cv_have_align_val_t=yes
+else
+  perftools_cv_have_align_val_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+                ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_have_align_val_t" >&5
+$as_echo "$perftools_cv_have_align_val_t" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++ compiler supports -faligned-new" >&5
+$as_echo_n "checking if C++ compiler supports -faligned-new... " >&6; }
+if ${perftools_cv_have_f_aligned_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+                OLD_CXXFLAGS="$CXXFLAGS"
+                CXXFLAGS="$CXXFLAGS -faligned-new"
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+(::operator delete)((::operator new)(256, std::align_val_t(16)), std::align_val_t(16))
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  perftools_cv_have_f_aligned_new=yes
+else
+  perftools_cv_have_f_aligned_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+                CXXFLAGS="$OLD_CXXFLAGS"
+                ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_have_f_aligned_new" >&5
+$as_echo "$perftools_cv_have_f_aligned_new" >&6; }
+
+ if test "$perftools_cv_have_f_aligned_new" = yes; then
+  HAVE_F_ALIGNED_NEW_TRUE=
+  HAVE_F_ALIGNED_NEW_FALSE='#'
+else
+  HAVE_F_ALIGNED_NEW_TRUE='#'
+  HAVE_F_ALIGNED_NEW_FALSE=
+fi
+
+
+if test "$perftools_cv_have_align_val_t" = yes || test "$perftools_cv_have_f_aligned_new" = yes; then :
+
+$as_echo "#define ENABLE_ALIGNED_NEW_DELETE 1" >>confdefs.h
+
+         { $as_echo "$as_me:${as_lineno-$LINENO}: Will build new/delete operators for overaligned types" >&5
+$as_echo "$as_me: Will build new/delete operators for overaligned types" >&6;}
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Will not build new/delete operators for overaligned types" >&5
+$as_echo "$as_me: Will not build new/delete operators for overaligned types" >&6;}
+fi
+
+if test "$perftools_cv_have_align_val_t" = yes || test "$perftools_cv_have_f_aligned_new" = yes; then
+  ac_cv_have_std_align_val_t=1
+   # gperftools/tcmalloc.h and windows/gperftools/tcmalloc.h need this
+else
+  ac_cv_have_std_align_val_t=0
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if target has _Unwind_Backtrace" >&5
+$as_echo_n "checking if target has _Unwind_Backtrace... " >&6; }
+if ${perftools_cv_have_unwind_backtrace+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+                cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+#if defined(__APPLE__)
+#error OSX _Unwind_Backtrace recurses back to malloc
+#endif
+
+int
+main ()
+{
+&_Unwind_Backtrace
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  perftools_cv_have_unwind_backtrace=yes
+else
+  perftools_cv_have_unwind_backtrace=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+                ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perftools_cv_have_unwind_backtrace" >&5
+$as_echo "$perftools_cv_have_unwind_backtrace" >&6; }
+if test "x$perftools_cv_have_unwind_backtrace" = xyes; then :
+
+$as_echo "#define HAVE_UNWIND_BACKTRACE 1" >>confdefs.h
+
+fi
+
+if test "x$will_use_libunwind" = xyes; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return __arm__
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  default_emergency_malloc=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+# Check whether --enable-emergency-malloc was given.
+if test "${enable_emergency_malloc+set}" = set; then :
+  enableval=$enable_emergency_malloc; enable_emergency_malloc="$enableval"
+else
+  enable_emergency_malloc="$default_emergency_malloc"
+fi
+
+
+ if test "x$enable_emergency_malloc" = xyes; then
+  BUILD_EMERGENCY_MALLOC_TRUE=
+  BUILD_EMERGENCY_MALLOC_FALSE='#'
+else
+  BUILD_EMERGENCY_MALLOC_TRUE='#'
+  BUILD_EMERGENCY_MALLOC_FALSE=
+fi
+
+
+# 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 __environ is available (for GetenvBeforeMain)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __environ" >&5
+$as_echo_n "checking for __environ... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+char **env = __environ
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE___ENVIRON 1" >>confdefs.h
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# If we support __thread, that can speed up tcmalloc a bit.
+# Note, however, that our code tickles a bug in gcc < 4.1.2
+# involving TLS and -fPIC (which our libraries will use) on x86:
+#   http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
+#
+# And mingw also does compile __thread but resultant code actually
+# fails to work correctly at least in some not so ancient version:
+# http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html
+#
+# Also it was reported that earlier gcc versions for mips compile
+# __thread but it doesn't really work
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __thread" >&5
+$as_echo_n "checking for __thread... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2))
+#error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
+#elif defined(__MINGW32__)
+#error mingw doesnt really support tls
+#elif defined(__APPLE__)
+#error OSX __thread support is known to call malloc which makes it unsafe to use from malloc replacement
+#endif
+
+int
+main ()
+{
+static __thread int p = 0
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_TLS 1" >>confdefs.h
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# Nanosleep requires extra libraries on some architectures (solaris).
+# This sets NANOSLEEP_LIBS.  nanosleep doesn't exist on mingw, which
+# is fine for us because we don't compile libspinlock, which uses it.
+if test "$need_nanosleep" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if nanosleep requires any libraries" >&5
+$as_echo_n "checking if nanosleep requires any libraries... " >&6; }
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ acx_nanosleep_ok="no"
+ NANOSLEEP_LIBS=
+ # For most folks, this should just work
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+static struct timespec ts; nanosleep(&ts, NULL);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  acx_nanosleep_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+ # For solaris, we may  need -lrt
+ if test "x$acx_nanosleep_ok" != "xyes"; then
+   OLD_LIBS="$LIBS"
+   LIBS="-lrt $LIBS"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+static struct timespec ts; nanosleep(&ts, NULL);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  acx_nanosleep_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+   if test "x$acx_nanosleep_ok" = "xyes"; then
+     NANOSLEEP_LIBS="-lrt"
+   fi
+   LIBS="$OLD_LIBS"
+ fi
+ if test "x$acx_nanosleep_ok" != "xyes"; then
+   as_fn_error $? "cannot find the nanosleep function" "$LINENO" 5
+ else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${NANOSLEEP_LIBS:-no}" >&5
+$as_echo "${NANOSLEEP_LIBS:-no}" >&6; }
+ fi
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+fi
+
+# Solaris 10 6/06 has a bug where /usr/sfw/lib/libstdc++.la is empty.
+# If so, we replace it with our own version.
+LIBSTDCXX_LA_LINKER_FLAG=
+if test -f /usr/sfw/lib/libstdc++.la && ! test -s /usr/sfw/lib/libstdc++.la
+then
+  LIBSTDCXX_LA_LINKER_FLAG='-L$(top_srcdir)/src/solaris'
+fi
+
+
+# In fact, a lot of the code in this directory depends on pthreads
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5
+$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; }
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_join ();
+int
+main ()
+{
+return pthread_join ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  acx_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5
+$as_echo "$acx_pthread_ok" >&6; }
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
+$as_echo_n "checking whether pthreads work without any flags... " >&6; }
+                ;;
+
+                -*)
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5
+$as_echo_n "checking whether pthreads work with $flag... " >&6; }
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		# Extract the first word of "pthread-config", so it can be a program name with args.
+set dummy pthread-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_acx_pthread_config+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$acx_pthread_config"; then
+  ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_acx_pthread_config="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no"
+fi
+fi
+acx_pthread_config=$ac_cv_prog_acx_pthread_config
+if test -n "$acx_pthread_config"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5
+$as_echo "$acx_pthread_config" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5
+$as_echo_n "checking for the pthreads library -l$flag... " >&6; }
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  acx_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5
+$as_echo "$acx_pthread_ok" >&6; }
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+$as_echo_n "checking for joinable pthread attribute... " >&6; }
+	attr_name=unknown
+	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+int attr=$attr; return attr;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  attr_name=$attr; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	done
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5
+$as_echo "$attr_name" >&6; }
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+
+cat >>confdefs.h <<_ACEOF
+#define PTHREAD_CREATE_JOINABLE $attr_name
+_ACEOF
+
+        fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5
+$as_echo_n "checking if more special flags are required for pthreads... " >&6; }
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
+$as_echo "${flag}" >&6; }
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+        # More AIX lossage: must compile with xlc_r or cc_r
+	if test x"$GCC" != xyes; then
+          for ac_prog in xlc_r cc_r
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PTHREAD_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$PTHREAD_CC"; then
+  ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_PTHREAD_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
+if test -n "$PTHREAD_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
+$as_echo "$PTHREAD_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$PTHREAD_CC" && break
+done
+test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
+
+        else
+          PTHREAD_CC=$CC
+	fi
+
+	# The next part tries to detect GCC inconsistency with -shared on some
+	# architectures and systems. The problem is that in certain
+	# configurations, when -shared is specified, GCC "forgets" to
+	# internally use various flags which are still necessary.
+
+	#
+	# Prepare the flags
+	#
+	save_CFLAGS="$CFLAGS"
+	save_LIBS="$LIBS"
+	save_CC="$CC"
+
+	# Try with the flags determined by the earlier checks.
+	#
+	# -Wl,-z,defs forces link-time symbol resolution, so that the
+	# linking checks with -shared actually have any value
+	#
+	# FIXME: -fPIC is required for -shared on many architectures,
+	# so we specify it here, but the right way would probably be to
+	# properly detect whether it is actually required.
+	CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+	LIBS="$PTHREAD_LIBS $LIBS"
+	CC="$PTHREAD_CC"
+
+	# In order not to create several levels of indentation, we test
+	# the value of "$done" until we find the cure or run out of ideas.
+	done="no"
+
+	# First, make sure the CFLAGS we added are actually accepted by our
+	# compiler.  If not (and OS X's ld, for instance, does not accept -z),
+	# then we can't do this test.
+	if test x"$done" = xno; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to check for GCC pthread/shared inconsistencies" >&5
+$as_echo_n "checking whether to check for GCC pthread/shared inconsistencies... " >&6; }
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+else
+  done=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	   if test "x$done" = xyes ; then
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	   else
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	   fi
+	fi
+
+	if test x"$done" = xno; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -pthread is sufficient with -shared" >&5
+$as_echo_n "checking whether -pthread is sufficient with -shared... " >&6; }
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  done=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	   if test "x$done" = xyes; then
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	   else
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	   fi
+	fi
+
+	#
+	# Linux gcc on some architectures such as mips/mipsel forgets
+	# about -lpthread
+	#
+	if test x"$done" = xno; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lpthread fixes that" >&5
+$as_echo_n "checking whether -lpthread fixes that... " >&6; }
+	   LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+	      pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	      pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  done=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	   if test "x$done" = xyes; then
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	      PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+	   else
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	   fi
+	fi
+	#
+	# FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+	#
+	if test x"$done" = xno; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc_r fixes that" >&5
+$as_echo_n "checking whether -lc_r fixes that... " >&6; }
+	   LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+	        pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	        pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  done=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	   if test "x$done" = xyes; then
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	      PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+	   else
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	   fi
+	fi
+	if test x"$done" = xno; then
+	   # OK, we have run out of ideas
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Impossible to determine how to use pthreads with shared libraries" >&5
+$as_echo "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries" >&2;}
+
+	   # so it's not safe to assume that we may use pthreads
+	   acx_pthread_ok=no
+	fi
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether what we have so far is sufficient with -nostdlib" >&5
+$as_echo_n "checking whether what we have so far is sufficient with -nostdlib... " >&6; }
+	CFLAGS="-nostdlib $CFLAGS"
+	# we need c with nostdlib
+	LIBS="$LIBS -lc"
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+	       pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	       pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  done=yes
+else
+  done=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	if test "x$done" = xyes; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	fi
+
+	if test x"$done" = xno; then
+	   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lpthread saves the day" >&5
+$as_echo_n "checking whether -lpthread saves the day... " >&6; }
+	   LIBS="-lpthread $LIBS"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+int
+main ()
+{
+pthread_t th; pthread_join(th, 0);
+	       pthread_attr_init(0); pthread_cleanup_push(0, 0);
+	       pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  done=yes
+else
+  done=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+	   if test "x$done" = xyes; then
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	      PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+	   else
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Impossible to determine how to use pthreads with shared libraries and -nostdlib" >&5
+$as_echo "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries and -nostdlib" >&2;}
+	   fi
+	fi
+
+	CFLAGS="$save_CFLAGS"
+	LIBS="$save_LIBS"
+	CC="$save_CC"
+else
+        PTHREAD_CC="$CC"
+fi
+
+
+
+
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+
+$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h
+
+        :
+else
+        acx_pthread_ok=no
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread symbols are available in C++ without including pthread.h" >&5
+$as_echo_n "checking whether pthread symbols are available in C++ without including pthread.h... " >&6; }
+acx_pthread_despite_asking_for=no
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+      #include 
+      #include 
+
+int
+main ()
+{
+
+      pthread_t th; pthread_join(th, 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+    acx_pthread_despite_asking_for=yes
+
+$as_echo "#define HAVE_PTHREAD_DESPITE_ASKING_FOR 1" >>confdefs.h
+
+    $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_despite_asking_for" >&5
+$as_echo "$acx_pthread_despite_asking_for" >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ if test x"$acx_pthread_despite_asking_for" = xyes; then
+  HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE=
+  HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE='#'
+else
+  HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE='#'
+  HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE=
+fi
+
+
+# Figure out where libc has program_invocation_name
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for program_invocation_name" >&5
+$as_echo_n "checking for program_invocation_name... " >&6; }
+if ${ac_cv_have_program_invocation_name+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+extern char* program_invocation_name;
+int
+main ()
+{
+return *program_invocation_name;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_have_program_invocation_name=yes
+else
+  ac_cv_have_program_invocation_name=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_program_invocation_name" >&5
+$as_echo "$ac_cv_have_program_invocation_name" >&6; }
+   if test "$ac_cv_have_program_invocation_name" = "yes"; then
+
+$as_echo "#define HAVE_PROGRAM_INVOCATION_NAME 1" >>confdefs.h
+
+   fi
+
+
+# Make the install prefix available, to figure out where to look for pprof
+ac_cv_install_prefix="$prefix";
+   if test x"$ac_cv_install_prefix" = x"NONE" ; then
+     ac_cv_install_prefix="$ac_default_prefix";
+   fi
+
+cat >>confdefs.h <<_ACEOF
+#define INSTALL_PREFIX "$ac_cv_install_prefix"
+_ACEOF
+
+
+
+case "$host" in
+   *-mingw*)
+     ac_fn_c_check_decl "$LINENO" "sleep" "ac_cv_have_decl_sleep" "#include 
+"
+if test "x$ac_cv_have_decl_sleep" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SLEEP $ac_have_decl
+_ACEOF
+
+     ac_fn_c_check_decl "$LINENO" "nanosleep" "ac_cv_have_decl_nanosleep" "#include 
+"
+if test "x$ac_cv_have_decl_nanosleep" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_NANOSLEEP $ac_have_decl
+_ACEOF
+
+   ;;
+esac
+
+if test "x$enable_backtrace" = xyes; then
+  ac_fn_c_check_decl "$LINENO" "backtrace" "ac_cv_have_decl_backtrace" "#include 
+"
+if test "x$ac_cv_have_decl_backtrace" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_BACKTRACE $ac_have_decl
+_ACEOF
+
+  save_LIBS=$LIBS
+  LIBS=$UNWIND_LIBS
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5
+$as_echo_n "checking for library containing backtrace... " >&6; }
+if ${ac_cv_search_backtrace+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char backtrace ();
+int
+main ()
+{
+return backtrace ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' execinfo; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_backtrace=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_backtrace+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_backtrace+:} false; then :
+
+else
+  ac_cv_search_backtrace=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5
+$as_echo "$ac_cv_search_backtrace" >&6; }
+ac_res=$ac_cv_search_backtrace
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+  UNWIND_LIBS=$LIBS
+  LIBS=$save_LIBS
+fi
+
+# For windows, this has a non-trivial value (__declspec(export)), but any
+# system that uses configure wants this to be the empty string.
+
+$as_echo "#define PERFTOOLS_DLL_DECL /**/" >>confdefs.h
+
+
+# In theory, config.h files shouldn't need a header guard, but we do,
+# because we (maybe) #include windows/mingw.h from within config.h,
+# and it #includes other .h files.  These all have header guards, so
+# the end result is if config.h is #included twice, its #undefs get
+# evaluated twice, but all the ones in mingw.h/etc only get evaluated
+# once, potentially causing trouble.  c.f.
+#   http://code.google.com/p/gperftools/issues/detail?id=246
+
+
+
+
+# MinGW uses autoconf, but also needs the windows shim routines
+# (since it doesn't have its own support for, say, pthreads).
+# This requires us to #include a special header file, and also to
+# link in some windows versions of .o's instead of the unix versions.
+#
+# Also, manually mark systems where we have to be careful how early
+# we run pthreads.  TODO(csilvers): turn this into an autoconf check.
+
+ if expr $host : '.*-mingw' >/dev/null 2>&1; then
+  MINGW_TRUE=
+  MINGW_FALSE='#'
+else
+  MINGW_TRUE='#'
+  MINGW_FALSE=
+fi
+
+ if expr $host : '.*-apple-darwin.*' >/dev/null 2>&1; then
+  OSX_TRUE=
+  OSX_FALSE='#'
+else
+  OSX_TRUE='#'
+  OSX_FALSE=
+fi
+
+
+# Export the --enable flags we set above.  We do this at the end so
+# other configure rules can enable or disable targets based on what
+# they find.
+ if test "$enable_cpu_profiler" = yes; then
+  WITH_CPU_PROFILER_TRUE=
+  WITH_CPU_PROFILER_FALSE='#'
+else
+  WITH_CPU_PROFILER_TRUE='#'
+  WITH_CPU_PROFILER_FALSE=
+fi
+
+ if test "$enable_heap_profiler" = yes; then
+  WITH_HEAP_PROFILER_TRUE=
+  WITH_HEAP_PROFILER_FALSE='#'
+else
+  WITH_HEAP_PROFILER_TRUE='#'
+  WITH_HEAP_PROFILER_FALSE=
+fi
+
+ if test "$enable_heap_checker" = yes; then
+  WITH_HEAP_CHECKER_TRUE=
+  WITH_HEAP_CHECKER_FALSE='#'
+else
+  WITH_HEAP_CHECKER_TRUE='#'
+  WITH_HEAP_CHECKER_FALSE=
+fi
+
+ if test "$enable_debugalloc" = yes; then
+  WITH_DEBUGALLOC_TRUE=
+  WITH_DEBUGALLOC_FALSE='#'
+else
+  WITH_DEBUGALLOC_TRUE='#'
+  WITH_DEBUGALLOC_FALSE=
+fi
+
+# We make tcmalloc.so if either heap-profiler or heap-checker is asked for.
+ if test "$enable_heap_profiler" = yes -o \
+                    "$enable_heap_checker" = yes; then
+  WITH_HEAP_PROFILER_OR_CHECKER_TRUE=
+  WITH_HEAP_PROFILER_OR_CHECKER_FALSE='#'
+else
+  WITH_HEAP_PROFILER_OR_CHECKER_TRUE='#'
+  WITH_HEAP_PROFILER_OR_CHECKER_FALSE=
+fi
+
+# If we don't use any profilers, we don't need stack traces (or pprof)
+ if test "$enable_cpu_profiler" = yes -o \
+                                      "$enable_heap_profiler" = yes -o \
+                                      "$enable_heap_checker" = yes; then
+  WITH_STACK_TRACE_TRUE=
+  WITH_STACK_TRACE_FALSE='#'
+else
+  WITH_STACK_TRACE_TRUE='#'
+  WITH_STACK_TRACE_FALSE=
+fi
+
+
+have_linux_sigev_thread_id=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux SIGEV_THREAD_ID" >&5
+$as_echo_n "checking for Linux SIGEV_THREAD_ID... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include 
+                           #include 
+int
+main ()
+{
+return SIGEV_THREAD_ID || CLOCK_THREAD_CPUTIME_ID || __linux;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_LINUX_SIGEV_THREAD_ID 1" >>confdefs.h
+
+         have_linux_sigev_thread_id=yes
+         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Disable large allocation report by default.
+# Check whether --enable-large-alloc-report was given.
+if test "${enable_large_alloc_report+set}" = set; then :
+  enableval=$enable_large_alloc_report; enable_large_alloc_report="$enableval"
+else
+  enable_large_alloc_report=no
+fi
+
+if test "x$enable_large_alloc_report" = xyes; then :
+
+$as_echo "#define ENABLE_LARGE_ALLOC_REPORT 1" >>confdefs.h
+
+fi
+
+# Enable aggressive decommit by default
+# Check whether --enable-aggressive-decommit-by-default was given.
+if test "${enable_aggressive_decommit_by_default+set}" = set; then :
+  enableval=$enable_aggressive_decommit_by_default; enable_aggressive_decommit_by_default="$enableval"
+else
+  enable_aggressive_decommit_by_default=no
+fi
+
+if test "x$enable_aggressive_decommit_by_default" = xyes; then :
+
+$as_echo "#define ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT 1" >>confdefs.h
+
+fi
+
+# Write generated configuration file
+ac_config_files="$ac_config_files Makefile src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GCC_TRUE}" && test -z "${GCC_FALSE}"; then
+  as_fn_error $? "conditional \"GCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_OBJCOPY_WEAKEN_TRUE}" && test -z "${HAVE_OBJCOPY_WEAKEN_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_OBJCOPY_WEAKEN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_STATIC_TRUE}" && test -z "${ENABLE_STATIC_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_STATIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_FRAME_POINTERS_TRUE}" && test -z "${ENABLE_FRAME_POINTERS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_FRAME_POINTERS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OMIT_FP_BY_DEFAULT_TRUE}" && test -z "${OMIT_FP_BY_DEFAULT_FALSE}"; then
+  as_fn_error $? "conditional \"OMIT_FP_BY_DEFAULT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${I386_TRUE}" && test -z "${I386_FALSE}"; then
+  as_fn_error $? "conditional \"I386\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_W_NO_UNUSED_RESULT_TRUE}" && test -z "${HAVE_W_NO_UNUSED_RESULT_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_W_NO_UNUSED_RESULT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${INSTALL_PPROF_TRUE}" && test -z "${INSTALL_PPROF_FALSE}"; then
+  as_fn_error $? "conditional \"INSTALL_PPROF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_SIZED_DEALLOCATION_TRUE}" && test -z "${HAVE_SIZED_DEALLOCATION_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_SIZED_DEALLOCATION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_F_ALIGNED_NEW_TRUE}" && test -z "${HAVE_F_ALIGNED_NEW_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_F_ALIGNED_NEW\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_EMERGENCY_MALLOC_TRUE}" && test -z "${BUILD_EMERGENCY_MALLOC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_EMERGENCY_MALLOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_PTHREAD_DESPITE_ASKING_FOR_TRUE}" && test -z "${HAVE_PTHREAD_DESPITE_ASKING_FOR_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_PTHREAD_DESPITE_ASKING_FOR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MINGW_TRUE}" && test -z "${MINGW_FALSE}"; then
+  as_fn_error $? "conditional \"MINGW\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${OSX_TRUE}" && test -z "${OSX_FALSE}"; then
+  as_fn_error $? "conditional \"OSX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_CPU_PROFILER_TRUE}" && test -z "${WITH_CPU_PROFILER_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_CPU_PROFILER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_HEAP_PROFILER_TRUE}" && test -z "${WITH_HEAP_PROFILER_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_HEAP_PROFILER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_HEAP_CHECKER_TRUE}" && test -z "${WITH_HEAP_CHECKER_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_HEAP_CHECKER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_DEBUGALLOC_TRUE}" && test -z "${WITH_DEBUGALLOC_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_DEBUGALLOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_HEAP_PROFILER_OR_CHECKER_TRUE}" && test -z "${WITH_HEAP_PROFILER_OR_CHECKER_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_HEAP_PROFILER_OR_CHECKER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_STACK_TRACE_TRUE}" && test -z "${WITH_STACK_TRACE_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_STACK_TRACE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by gperftools $as_me 2.9.1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to ."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+gperftools config.status 2.9.1
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
+predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
+postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
+predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
+postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
+reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
+reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+DLLTOOL \
+sharedlib_from_linklib_cmd \
+AR \
+AR_FLAGS \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib \
+compiler_lib_search_dirs \
+predep_objects \
+postdep_objects \
+predeps \
+postdeps \
+compiler_lib_search_path \
+LD_CXX \
+reload_flag_CXX \
+compiler_CXX \
+lt_prog_compiler_no_builtin_flag_CXX \
+lt_prog_compiler_pic_CXX \
+lt_prog_compiler_wl_CXX \
+lt_prog_compiler_static_CXX \
+lt_cv_prog_compiler_c_o_CXX \
+export_dynamic_flag_spec_CXX \
+whole_archive_flag_spec_CXX \
+compiler_needs_object_CXX \
+with_gnu_ld_CXX \
+allow_undefined_flag_CXX \
+no_undefined_flag_CXX \
+hardcode_libdir_flag_spec_CXX \
+hardcode_libdir_separator_CXX \
+exclude_expsyms_CXX \
+include_expsyms_CXX \
+file_list_spec_CXX \
+compiler_lib_search_dirs_CXX \
+predep_objects_CXX \
+postdep_objects_CXX \
+predeps_CXX \
+postdeps_CXX \
+compiler_lib_search_path_CXX; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path \
+reload_cmds_CXX \
+old_archive_cmds_CXX \
+old_archive_from_new_cmds_CXX \
+old_archive_from_expsyms_cmds_CXX \
+archive_cmds_CXX \
+archive_expsym_cmds_CXX \
+module_cmds_CXX \
+module_expsym_cmds_CXX \
+export_symbols_cmds_CXX \
+prelink_cmds_CXX \
+postlink_cmds_CXX; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "src/gperftools/tcmalloc.h") CONFIG_FILES="$CONFIG_FILES src/gperftools/tcmalloc.h" ;;
+    "src/windows/gperftools/tcmalloc.h") CONFIG_FILES="$CONFIG_FILES src/windows/gperftools/tcmalloc.h" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' >$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' >$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  case $CONFIG_FILES in #(
+  *\'*) :
+    eval set x "$CONFIG_FILES" ;; #(
+  *) :
+    set x $CONFIG_FILES ;; #(
+  *) :
+     ;;
+esac
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$am_mf" : 'X\(//\)[^/]' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$am_mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$am_mf" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    { echo "$as_me:$LINENO: cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles" >&5
+   (cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE=\"gmake\" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+  { am_dirpart=; unset am_dirpart;}
+  { am_filepart=; unset am_filepart;}
+  { am_mf=; unset am_mf;}
+  { am_rc=; unset am_rc;}
+  rm -f conftest-deps.mk
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options that allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}"; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile=${ofile}T
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the  same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+
+
+# The names of the tagged configurations supported by this script.
+available_tags='CXX '
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects
+postdep_objects=$lt_postdep_objects
+predeps=$lt_predeps
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+    cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x$2 in
+    x)
+        ;;
+    *:)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+        ;;
+    x:*)
+        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+        ;;
+    *)
+        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+
+
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in $*""; do
+      case $cc_temp in
+        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+
+    cat <<_LT_EOF >> "$ofile"
+
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_CXX
+reload_cmds=$lt_reload_cmds_CXX
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_CXX
+
+# A language specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_CXX
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_CXX
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_CXX
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_CXX
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds_CXX
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_CXX
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects_CXX
+postdep_objects=$lt_postdep_objects_CXX
+predeps=$lt_predeps_CXX
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# ### END LIBTOOL TAG CONFIG: CXX
+_LT_EOF
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+if test "$omit_fp_by_default" = yes && test "x$enable_frame_pointers" != xyes && test "x$UNWIND_LIBS" = x && test "x$enable_minimal" != xyes; then :
+  if test "x$perftools_cv_have_unwind_backtrace" = xyes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No frame pointers and no libunwind. Using experimental backtrace capturing via libgcc. Expect crashy cpu profiler." >&5
+$as_echo "$as_me: WARNING: No frame pointers and no libunwind. Using experimental backtrace capturing via libgcc. Expect crashy cpu profiler." >&2;}
+else
+  if test "x$enable_backtrace" = xyes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No frame pointers and no libunwind.  Using experimental backtrace(). Expect crashy cpu profiler." >&5
+$as_echo "$as_me: WARNING: No frame pointers and no libunwind.  Using experimental backtrace(). Expect crashy cpu profiler." >&2;}
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "No frame pointers and no libunwind. The compilation will fail
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+fi
+fi
diff --git a/trunk/3rdparty/gperftools-2-fit/configure.ac b/trunk/3rdparty/gperftools-2-fit/configure.ac
new file mode 100644
index 000000000..c419d5fb2
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/configure.ac
@@ -0,0 +1,657 @@
+## Process this file with autoconf to produce configure.
+## In general, the safest way to proceed is to run ./autogen.sh
+
+# make sure we're interpreted by some minimal autoconf
+AC_PREREQ([2.59])
+
+AC_INIT([gperftools],[2.9.1],[gperftools@googlegroups.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=9:9:5
+PROFILER_SO_VERSION=5:4:5
+TCMALLOC_AND_PROFILER_SO_VERSION=10:4:6
+
+AC_SUBST(TCMALLOC_SO_VERSION)
+AC_SUBST(PROFILER_SO_VERSION)
+AC_SUBST(TCMALLOC_AND_PROFILER_SO_VERSION)
+
+# The argument here is just something that should be in the current directory
+# (for sanity checking)
+AC_CONFIG_SRCDIR(README)
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_HOST
+AM_INIT_AUTOMAKE([dist-zip])
+AC_CONFIG_HEADERS([src/config.h])
+
+AM_MAINTAINER_MODE()
+# Export the version information (for tc_version and friends)
+TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([[0-9]]*\)'`
+TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[[0-9]]*\.\([[0-9]]*\)'`
+TC_VERSION_PATCH=`expr "$PACKAGE_VERSION" : '[[0-9]]*\.[[0-9]]*\(.*\)$'`
+AC_SUBST(TC_VERSION_MAJOR)
+AC_SUBST(TC_VERSION_MINOR)
+AC_SUBST(TC_VERSION_PATCH)
+AC_SUBST(PACKAGE_STRING)
+
+AX_GENERATE_CHANGELOG
+
+# The user can choose not to compile in the heap-profiler, the
+# heap-checker, or the cpu-profiler.  There's also the possibility
+# for a 'fully minimal' compile, which leaves out the stacktrace
+# code as well.  By default, we include all of these that the
+# target system supports.
+default_enable_cpu_profiler=yes
+default_enable_heap_profiler=yes
+default_enable_heap_checker=yes
+default_enable_debugalloc=yes
+default_enable_minimal=no
+default_tcmalloc_alignment=16
+need_nanosleep=yes   # Used later, to decide if to run ACX_NANOSLEEP
+case "$host" in
+   *-mingw*) default_enable_minimal=yes; default_enable_debugalloc=no;
+             need_nanosleep=no;;
+   *-cygwin*) default_enable_heap_checker=no; default_enable_cpu_profiler=no;;
+   *-freebsd*) default_enable_heap_checker=no;;
+   *-darwin*) default_enable_heap_checker=no;;
+esac
+
+# Currently only backtrace works on s390 and OSX.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [
+#if !defined(__s390__) && !defined(__APPLE__)
+#error not s390 and not osx
+#endif
+return 1
+])],
+                  [default_enable_libunwind=no
+                   default_enable_backtrace=yes],
+                  [default_enable_libunwind=yes
+                   default_enable_backtrace=no])
+
+# Disable libunwind linking on ppc64 by default.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __PPC64__])],
+                  [default_enable_libunwind=no
+                   default_tcmalloc_pagesize=64],
+                  [default_enable_libunwind=yes
+                   default_tcmalloc_pagesize=8])
+
+AC_ARG_ENABLE([cpu-profiler],
+              [AS_HELP_STRING([--disable-cpu-profiler],
+                              [do not build the cpu profiler])],
+              [],
+              [enable_cpu_profiler="$default_enable_cpu_profiler"])
+AC_ARG_ENABLE([heap-profiler],
+              [AS_HELP_STRING([--disable-heap-profiler],
+                              [do not build the heap profiler])],
+              [],
+              [enable_heap_profiler="$default_enable_heap_profiler"])
+AC_ARG_ENABLE([heap-checker],
+              [AS_HELP_STRING([--disable-heap-checker],
+                              [do not build the heap checker])],
+              [],
+              [enable_heap_checker="$default_enable_heap_checker"])
+AC_ARG_ENABLE([debugalloc],
+              [AS_HELP_STRING([--disable-debugalloc],
+                              [do not build versions of libs with debugalloc])],
+              [],
+              [enable_debugalloc="$default_enable_debugalloc"])
+AC_ARG_ENABLE([minimal],
+              [AS_HELP_STRING([--enable-minimal],
+                              [build only tcmalloc-minimal (and maybe tcmalloc-minimal-debug)])],
+              [],
+              [enable_minimal="$default_enable_minimal"])
+if test "$enable_minimal" = yes; then
+  enable_cpu_profiler=no
+  enable_heap_profiler=no
+  enable_heap_checker=no
+fi
+AC_ARG_ENABLE([stacktrace-via-backtrace],
+              [AS_HELP_STRING([--enable-stacktrace-via-backtrace],
+                              [enable use of backtrace() for stacktrace capturing (may deadlock)])],
+              [enable_backtrace=yes],
+              [enable_backtrace="$default_enable_backtrace"])
+AC_ARG_ENABLE([libunwind],
+              [AS_HELP_STRING([--enable-libunwind],
+                              [enable libunwind linking])],
+              [],
+              [enable_libunwind="$default_enable_libunwind"])
+AC_ARG_WITH([tcmalloc-pagesize],
+            [AS_HELP_STRING([--with-tcmalloc-pagesize],
+                            [Set the tcmalloc internal page size to 4K, 8K, 16K, 32K, 64K, 128K or 256K])],
+            [],
+            [with_tcmalloc_pagesize=$default_tcmalloc_pagesize])
+AC_ARG_WITH([tcmalloc-alignment],
+            [AS_HELP_STRING([--with-tcmalloc-alignment],
+                            [Set the tcmalloc allocation alignment to 8 or 16 bytes])],
+            [],
+            [with_tcmalloc_alignment=$default_tcmalloc_alignment])
+
+case "$with_tcmalloc_pagesize" in
+  4)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 12);;
+  8)
+       #Default tcmalloc page size.
+       ;;
+  16)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 14);;
+  32)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 15);;
+  64)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 16);;
+  128)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 17);;
+  256)
+       AC_DEFINE(TCMALLOC_PAGE_SIZE_SHIFT, 18,
+                 [Define internal page size for tcmalloc as number of left bitshift]);;
+  *)
+       AC_MSG_WARN([${with_tcmalloc_pagesize}K size not supported, using default tcmalloc page size.])
+esac
+case "$with_tcmalloc_alignment" in
+  8)
+       AC_DEFINE(TCMALLOC_ALIGN_8BYTES, 1,
+                 [Define 8 bytes of allocation alignment for tcmalloc]);;
+  16)
+       #Default tcmalloc allocation alignment.
+       ;;
+  *)
+       AC_MSG_WARN([${with_tcmalloc_alignment} bytes not supported, using default tcmalloc allocation alignment.])
+esac
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_CPP
+AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
+AM_PROG_CC_C_O      # shrug: autogen.sh suddenly needs this for some reason
+
+AX_CXX_COMPILE_STDCXX(11, ext, mandatory)
+
+# Check if we have an objcopy installed that supports -W
+AC_CHECK_TOOL([OBJCOPY], [objcopy], [])
+AS_IF([test -n "$OBJCOPY"], [dnl
+  AC_CACHE_CHECK([if $OBJCOPY supports -W], gpt_cv_objcopy_weaken, [dnl
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([void foo() {} int main() {return 0;}])], [dnl
+      AS_IF(["$OBJCOPY" -W foo conftest$ac_exeext /dev/null],
+      	    [gpt_cv_objcopy_weaken=yes], [gpt_cv_objcopy_weaken=no])],
+    [gpt_cv_objcopy_weaken=no])])],
+  [gpt_cv_objcopy_weaken=no])
+AM_CONDITIONAL(HAVE_OBJCOPY_WEAKEN, test $gpt_cv_objcopy_weaken = yes)
+
+AC_PROG_LIBTOOL
+
+AX_C___ATTRIBUTE__
+
+AC_MSG_CHECKING(for __attribute__((aligned(N))) on functions)
+AC_CACHE_VAL(ac_cv___attribute__aligned_fn, [
+  AC_TRY_COMPILE(
+    [#include 
+     void foo(void) __attribute__((aligned(128)));
+     void foo(void) { exit(1); }],
+    [],
+    ac_cv___attribute__aligned_fn=yes,
+    ac_cv___attribute__aligned_fn=no
+  )])
+if test "$ac_cv___attribute__aligned_fn" = "yes"; then
+  AC_DEFINE(HAVE___ATTRIBUTE__ALIGNED_FN, 1, [define if your compiler supports alignment of functions])
+fi
+AC_MSG_RESULT($ac_cv___attribute__aligned_fn)
+
+
+# Check whether some low-level functions/files are available
+AC_HEADER_STDC
+
+# TODO(csilvers): we could remove a lot when WITH_CPU_PROFILER etc is "no".
+AC_CHECK_TYPES([struct mallinfo],,, [#include ])
+AC_CHECK_TYPES([Elf32_Versym],,, [#include ])   # for vdso_support.h
+AC_CHECK_FUNCS(sbrk)            # for tcmalloc to get memory
+AC_CHECK_FUNCS(__sbrk)          # for tcmalloc to get memory
+AC_CHECK_FUNCS(geteuid)         # for turning off services when run as root
+AC_CHECK_FUNCS(fork)            # for the pthread_atfork setup
+AC_CHECK_HEADERS(features.h)    # for vdso_support.h, __GLIBC__ macros
+AC_CHECK_HEADERS(malloc.h)      # some systems define stuff there, others not
+AC_CHECK_HEADERS(glob.h)        # for heap-profile-table (cleaning up profiles)
+AC_CHECK_HEADERS(execinfo.h)    # for stacktrace? and heapchecker_unittest
+AC_CHECK_HEADERS(unwind.h)      # for stacktrace
+AC_CHECK_HEADERS(sched.h)       # for being nice in our spinlock code
+AC_CHECK_HEADERS(conflict-signal.h)      # defined on some windows platforms?
+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(sys/socket.h)  # optional; for forking out to symbolizer
+AC_CHECK_HEADERS(sys/wait.h)    # optional; for forking out to symbolizer
+AC_CHECK_HEADERS(poll.h)        # optional; for forking out to symbolizer
+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_HEADERS(sys/resource.h)         # for memalign_unittest.cc
+AC_CHECK_HEADERS(sys/cdefs.h)   # Where glibc defines __THROW
+# We also need /, but we get those from
+# AC_PC_FROM_UCONTEXT, below.
+
+# 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,
+                posix_memalign,
+                memalign,
+                valloc,
+                pvalloc],,,
+               [#define _XOPEN_SOURCE 600
+                #include 
+                #include ])
+
+if test "$ac_cv_type_struct_mallinfo" = yes; then
+  AC_SUBST(ac_cv_have_struct_mallinfo, 1)   # gperftools/tcmalloc.h needs this
+else
+  AC_SUBST(ac_cv_have_struct_mallinfo, 0)
+fi
+
+# We hardcode HAVE_MMAP to 1. There are no interesting systems anymore
+# without functional mmap. And our windows (except mingw) builds
+# aren't using autoconf. So we keep HAVE_MMAP define, but only to
+# distingush windows and rest.
+case "$host" in
+   *-mingw*) default_emergency_malloc=no;;
+   *) default_emergency_malloc=yes
+      AC_DEFINE(HAVE_MMAP, 1, [Define to 1 if you have a working `mmap' system call.])
+esac
+
+# If AtomicWord != Atomic32, we need to define two versions of all the
+# atomicops functions.  If they're the same, we want to define only one.
+AC_MSG_CHECKING([if int32_t is the same type as intptr_t])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int32_t v1 = 0; intptr_t v2 = 0; return (&v1 - &v2)]])],[AC_DEFINE(INT32_EQUALS_INTPTR, 1,
+                          Define to 1 if int32_t is equivalent to intptr_t)
+                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).  But don't
+# bother if we're not doing cpu-profiling.
+# [*] means that we've not actually tested one of these systems
+if test "$enable_cpu_profiler" = yes; then
+  AC_PC_FROM_UCONTEXT(AC_MSG_WARN(Could not find the PC.  Will not try to compile libprofiler...);
+                      enable_cpu_profiler=no)
+fi
+
+# Some tests test the behavior of .so files, and only make sense for dynamic.
+AM_CONDITIONAL(ENABLE_STATIC, test "$enable_static" = yes)
+
+# We want to link in libunwind if it is enabled and exists.
+UNWIND_LIBS=
+if test "$enable_libunwind" = yes; then
+  AC_CHECK_HEADERS([libunwind.h],
+                   [AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind)
+                    will_use_libunwind=yes])
+fi
+AC_SUBST(UNWIND_LIBS)
+
+# On x86_64, instead of libunwind, we can choose to compile with frame-pointers.
+AC_ARG_ENABLE(frame_pointers,
+              AS_HELP_STRING([--enable-frame-pointers],
+                             [On x86_64 systems, compile with -fno-omit-frame-pointer (see INSTALL)]),
+	      , enable_frame_pointers=no)
+AM_CONDITIONAL(ENABLE_FRAME_POINTERS, test "$enable_frame_pointers" = yes)
+
+AC_MSG_CHECKING([for x86 without frame pointers])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __x86_64__ == 1 ? 0 : 1])],
+                  [is_x86_64=yes], [is_x86_64=no])
+omit_fp_by_default=no
+AS_IF([test "$is_x86_64" = yes], [omit_fp_by_default=yes])
+AM_CONDITIONAL(OMIT_FP_BY_DEFAULT,
+               test "$omit_fp_by_default" = yes)
+AC_MSG_RESULT([$omit_fp_by_default])
+
+# We need to know if we're i386 so we can turn on -mmms, which is not
+# on by default for i386 (it is for x86_64).
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __i386__ == 1 ? 0 : 1])],
+                  [is_i386=yes], [is_i386=no])
+AM_CONDITIONAL(I386, test "$is_i386" = yes)
+
+# See if the compiler supports -Wno-unused-result.
+# Newer ubuntu's turn on -D_FORTIFY_SOURCE=2, enabling
+# __attribute__((warn_unused_result)) for things like write(),
+# which we don't care about.
+AC_CACHE_CHECK([if the compiler supports -Wno-unused-result],
+               perftools_cv_w_no_unused_result,
+	       [OLD_CFLAGS="$CFLAGS"
+	        CFLAGS="$CFLAGS -Wno-error -Wunused-result"
+		# gcc doesn't warn about unknown flags unless it's
+		# also warning for some other purpose, hence the
+		# divide-by-0.  (We use -Wno-error to make sure the
+		# divide-by-0 doesn't cause this test to fail!)
+                #
+                # Also gcc is giving only warning for unknown flags of
+                # -Wno-XXX form. So in order to detect support we're
+                # using -Wunused-result which will cause gcc to give
+                # error which we can detect.
+	        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, return 1/0)],
+	                          perftools_cv_w_no_unused_result=yes,
+                                  perftools_cv_w_no_unused_result=no)
+	        CFLAGS="$OLD_CFLAGS"])
+AM_CONDITIONAL(HAVE_W_NO_UNUSED_RESULT,
+	       test "$perftools_cv_w_no_unused_result" = yes)
+
+AC_ARG_ENABLE([deprecated-pprof],
+              [AS_HELP_STRING([--disable-deprecated-pprof],
+                [do not install old deprecated and unmaintained bundled pprof
+(see github.com/google/pprof for supported version)])],
+              [enable_pprof="$enableval"],
+              [enable_pprof=yes])
+
+AM_CONDITIONAL(INSTALL_PPROF,
+               [test "x$enable_pprof" = xyes])
+
+AC_ARG_ENABLE([dynamic-sized-delete-support],
+              [AS_HELP_STRING([--enable-dynamic-sized-delete-support],
+                [try to build run-time switch for sized delete operator])],
+              [enable_dyn_sized_delete="$enableval"],
+              [enable_dyn_sized_delete=no])
+
+AS_IF([test "x$enable_dyn_sized_delete" = xyes],
+      [AC_DEFINE([ENABLE_DYNAMIC_SIZED_DELETE], 1,
+                 [Build runtime detection for sized delete])])
+
+AC_ARG_ENABLE([sized-delete],
+              [AS_HELP_STRING([--enable-sized-delete],
+                              [build sized delete operator])],
+              [enable_sized_delete="$enableval"],
+              [enable_sized_delete="no"])
+AS_IF([test "x$enable_sized_delete" = xyes],
+        [AC_DEFINE([ENABLE_SIZED_DELETE], 1, [Build sized deletion operators])
+         AC_MSG_NOTICE([Will build sized deallocation operators])],
+      [AS_IF([test "x$enable_dyn_sized_delete" = xyes],
+             [AC_MSG_NOTICE([Will build dynamically detected sized deallocation operators])],
+             [AC_MSG_NOTICE([Will build sized deallocation operators that ignore size])])])
+
+AC_CACHE_CHECK([if C++ compiler supports -fsized-deallocation],
+               [perftools_cv_sized_deallocation_result],
+               [AC_LANG_PUSH(C++)
+                OLD_CXXFLAGS="$CXXFLAGS"
+                CXXFLAGS="$CXXFLAGS -fsized-deallocation"
+                AC_LINK_IFELSE([AC_LANG_PROGRAM(
+                    [[#include 
+#include ]],
+                    [[static void (* volatile ptr)(void *, size_t) = ::operator delete; (*ptr)(0, 256);]])],
+                 perftools_cv_sized_deallocation_result=yes,
+                 perftools_cv_sized_deallocation_result=no)
+                CXXFLAGS="$OLD_CXXFLAGS"
+                AC_LANG_POP(C++)])
+
+AM_CONDITIONAL(HAVE_SIZED_DEALLOCATION,
+               test "$perftools_cv_sized_deallocation_result" = yes)
+
+AC_CACHE_CHECK([if C++ compiler supports std::align_val_t without options],
+               [perftools_cv_have_align_val_t],
+               [AC_LANG_PUSH(C++)
+                AC_LINK_IFELSE([AC_LANG_PROGRAM(
+                    [[#include ]],
+                    [[(::operator delete)((::operator new)(256, std::align_val_t(16)), std::align_val_t(16))]])],
+                 perftools_cv_have_align_val_t=yes,
+                 perftools_cv_have_align_val_t=no)
+                AC_LANG_POP(C++)])
+
+AC_CACHE_CHECK([if C++ compiler supports -faligned-new],
+               [perftools_cv_have_f_aligned_new],
+               [AC_LANG_PUSH(C++)
+                OLD_CXXFLAGS="$CXXFLAGS"
+                CXXFLAGS="$CXXFLAGS -faligned-new"
+                AC_LINK_IFELSE([AC_LANG_PROGRAM(
+                    [[#include ]],
+                    [[(::operator delete)((::operator new)(256, std::align_val_t(16)), std::align_val_t(16))]])],
+                 perftools_cv_have_f_aligned_new=yes,
+                 perftools_cv_have_f_aligned_new=no)
+                CXXFLAGS="$OLD_CXXFLAGS"
+                AC_LANG_POP(C++)])
+
+AM_CONDITIONAL(HAVE_F_ALIGNED_NEW,
+               test "$perftools_cv_have_f_aligned_new" = yes)
+
+AS_IF([test "$perftools_cv_have_align_val_t" = yes || test "$perftools_cv_have_f_aligned_new" = yes],
+        [AC_DEFINE([ENABLE_ALIGNED_NEW_DELETE], 1, [Build new/delete operators for overaligned types])
+         AC_MSG_NOTICE([Will build new/delete operators for overaligned types])],
+         AC_MSG_NOTICE([Will not build new/delete operators for overaligned types]))
+
+if test "$perftools_cv_have_align_val_t" = yes || test "$perftools_cv_have_f_aligned_new" = yes; then
+  AC_SUBST(ac_cv_have_std_align_val_t, 1)   # gperftools/tcmalloc.h and windows/gperftools/tcmalloc.h need this
+else
+  AC_SUBST(ac_cv_have_std_align_val_t, 0)
+fi
+
+
+AC_CACHE_CHECK([if target has _Unwind_Backtrace],
+               [perftools_cv_have_unwind_backtrace],
+               [AC_LANG_PUSH(C++)
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                    [[#include 
+#if defined(__APPLE__)
+#error OSX _Unwind_Backtrace recurses back to malloc
+#endif
+]],
+                    [[&_Unwind_Backtrace]])],
+                 [perftools_cv_have_unwind_backtrace=yes],
+                 [perftools_cv_have_unwind_backtrace=no])
+                AC_LANG_POP(C++)])
+AS_IF([test "x$perftools_cv_have_unwind_backtrace" = xyes],
+      [AC_DEFINE(HAVE_UNWIND_BACKTRACE, 1, [Whether  contains _Unwind_Backtrace])])
+
+AS_IF([test "x$will_use_libunwind" = xyes],
+      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __arm__])],
+                         [default_emergency_malloc=yes])])
+
+AC_ARG_ENABLE([emergency-malloc],
+              [AS_HELP_STRING([--enable-emergency-malloc],
+                              [build emergency malloc feature])],
+              [enable_emergency_malloc="$enableval"],
+              [enable_emergency_malloc="$default_emergency_malloc"])
+
+AM_CONDITIONAL(BUILD_EMERGENCY_MALLOC, [test "x$enable_emergency_malloc" = xyes])
+
+# 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 __environ is available (for GetenvBeforeMain)
+AC_MSG_CHECKING([for __environ])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
+                                [char **env = __environ])],
+               [AC_DEFINE(HAVE___ENVIRON, 1,
+                          [Define to 1 if compiler supports __environ])
+                AC_MSG_RESULT([yes])],
+               [AC_MSG_RESULT([no])])
+
+# If we support __thread, that can speed up tcmalloc a bit.
+# Note, however, that our code tickles a bug in gcc < 4.1.2
+# involving TLS and -fPIC (which our libraries will use) on x86:
+#   http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
+#
+# And mingw also does compile __thread but resultant code actually
+# fails to work correctly at least in some not so ancient version:
+# http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html
+#
+# Also it was reported that earlier gcc versions for mips compile
+# __thread but it doesn't really work
+AC_MSG_CHECKING([for __thread])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) || (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2))
+#error gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
+#elif defined(__MINGW32__)
+#error mingw doesnt really support tls
+#elif defined(__APPLE__)
+#error OSX __thread support is known to call malloc which makes it unsafe to use from malloc replacement
+#endif
+], [static __thread int p = 0])],
+               [AC_DEFINE(HAVE_TLS, 1,
+                          Define to 1 if compiler supports __thread)
+                AC_MSG_RESULT([yes])],
+               [AC_MSG_RESULT([no])])
+
+# Nanosleep requires extra libraries on some architectures (solaris).
+# This sets NANOSLEEP_LIBS.  nanosleep doesn't exist on mingw, which
+# is fine for us because we don't compile libspinlock, which uses it.
+if test "$need_nanosleep" = yes; then
+  ACX_NANOSLEEP
+  AC_SUBST(NANOSLEEP_LIBS)
+fi
+
+# Solaris 10 6/06 has a bug where /usr/sfw/lib/libstdc++.la is empty.
+# If so, we replace it with our own version.
+LIBSTDCXX_LA_LINKER_FLAG=
+if test -f /usr/sfw/lib/libstdc++.la && ! test -s /usr/sfw/lib/libstdc++.la
+then
+  LIBSTDCXX_LA_LINKER_FLAG='-L$(top_srcdir)/src/solaris'
+fi
+AC_SUBST(LIBSTDCXX_LA_LINKER_FLAG)
+
+# In fact, a lot of the code in this directory depends on pthreads
+ACX_PTHREAD
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([whether pthread symbols are available in C++ without including pthread.h])
+acx_pthread_despite_asking_for=no
+AC_LINK_IFELSE(
+  [AC_LANG_PROGRAM([
+      #include 
+      #include 
+  ],[
+      pthread_t th; pthread_join(th, 0);
+  ])],[
+    acx_pthread_despite_asking_for=yes
+    AC_DEFINE(HAVE_PTHREAD_DESPITE_ASKING_FOR, 1, [defined to 1 if pthread symbols are exposed even without include pthread.h])
+    AC_DEFINE(HAVE_PTHREAD, 1, [])
+  ])
+AC_MSG_RESULT([$acx_pthread_despite_asking_for])
+AC_LANG_RESTORE
+
+AM_CONDITIONAL(HAVE_PTHREAD_DESPITE_ASKING_FOR, test x"$acx_pthread_despite_asking_for" = xyes)
+
+# Figure out where libc has program_invocation_name
+AC_PROGRAM_INVOCATION_NAME
+
+# Make the install prefix available, to figure out where to look for pprof
+AC_INSTALL_PREFIX
+
+dnl only very recent mingw has sleep and nanosleep
+case "$host" in
+   *-mingw*)
+     AC_CHECK_DECLS([sleep], [], [], [#include ])
+     AC_CHECK_DECLS([nanosleep], [], [], [#include ])
+   ;;
+esac
+
+if test "x$enable_backtrace" = xyes; then
+  AC_CHECK_DECLS([backtrace], [], [], [#include ])
+  save_LIBS=$LIBS
+  LIBS=$UNWIND_LIBS
+  AC_SEARCH_LIBS([backtrace], [execinfo])
+  UNWIND_LIBS=$LIBS
+  LIBS=$save_LIBS
+fi
+
+# For windows, this has a non-trivial value (__declspec(export)), but any
+# system that uses configure wants this to be the empty string.
+AC_DEFINE(PERFTOOLS_DLL_DECL,,
+          [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.])
+
+# In theory, config.h files shouldn't need a header guard, but we do,
+# because we (maybe) #include windows/mingw.h from within config.h,
+# and it #includes other .h files.  These all have header guards, so
+# the end result is if config.h is #included twice, its #undefs get
+# evaluated twice, but all the ones in mingw.h/etc only get evaluated
+# once, potentially causing trouble.  c.f.
+#   http://code.google.com/p/gperftools/issues/detail?id=246
+AH_TOP([
+#ifndef GPERFTOOLS_CONFIG_H_
+#define GPERFTOOLS_CONFIG_H_
+])
+
+AH_VERBATIM([PTHREADS_CRASHES_IF_RUN_TOO_EARLY],
+	    [/* Mark the systems where we know it's bad if pthreads runs too
+   early before main (before threads are initialized, presumably).  */
+#ifdef __FreeBSD__
+#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1
+#endif])
+
+# MinGW uses autoconf, but also needs the windows shim routines
+# (since it doesn't have its own support for, say, pthreads).
+# This requires us to #include a special header file, and also to
+# link in some windows versions of .o's instead of the unix versions.
+#
+# Also, manually mark systems where we have to be careful how early
+# we run pthreads.  TODO(csilvers): turn this into an autoconf check.
+AH_BOTTOM([
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
+
+#endif  /* #ifndef GPERFTOOLS_CONFIG_H_ */
+])
+AM_CONDITIONAL(MINGW, expr $host : '.*-mingw' >/dev/null 2>&1)
+AM_CONDITIONAL(OSX, expr $host : '.*-apple-darwin.*' >/dev/null 2>&1)
+
+# Export the --enable flags we set above.  We do this at the end so
+# other configure rules can enable or disable targets based on what
+# they find.
+AM_CONDITIONAL(WITH_CPU_PROFILER, test "$enable_cpu_profiler" = yes)
+AM_CONDITIONAL(WITH_HEAP_PROFILER, test "$enable_heap_profiler" = yes)
+AM_CONDITIONAL(WITH_HEAP_CHECKER, test "$enable_heap_checker" = yes)
+AM_CONDITIONAL(WITH_DEBUGALLOC, test "$enable_debugalloc" = yes)
+# We make tcmalloc.so if either heap-profiler or heap-checker is asked for.
+AM_CONDITIONAL(WITH_HEAP_PROFILER_OR_CHECKER,
+               test "$enable_heap_profiler" = yes -o \
+                    "$enable_heap_checker" = yes)
+# If we don't use any profilers, we don't need stack traces (or pprof)
+AM_CONDITIONAL(WITH_STACK_TRACE, test "$enable_cpu_profiler" = yes -o \
+                                      "$enable_heap_profiler" = yes -o \
+                                      "$enable_heap_checker" = yes)
+
+have_linux_sigev_thread_id=no
+AC_MSG_CHECKING([for Linux SIGEV_THREAD_ID])
+AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[#include 
+                           #include ]],
+                         [[return SIGEV_THREAD_ID || CLOCK_THREAD_CPUTIME_ID || __linux;]])],
+        [AC_DEFINE(HAVE_LINUX_SIGEV_THREAD_ID, 1,
+                  [Define if this is Linux that has SIGEV_THREAD_ID])
+         have_linux_sigev_thread_id=yes
+         AC_MSG_RESULT([yes])],
+        [AC_MSG_RESULT([no])])
+
+# Disable large allocation report by default.
+AC_ARG_ENABLE([large-alloc-report],
+              [AS_HELP_STRING([--enable-large-alloc-report],
+                              [report very large allocations to stderr])],
+              [enable_large_alloc_report="$enableval"],
+              [enable_large_alloc_report=no])
+AS_IF([test "x$enable_large_alloc_report" = xyes],
+      [AC_DEFINE([ENABLE_LARGE_ALLOC_REPORT], 1, [report large allocation])])
+
+# Enable aggressive decommit by default
+AC_ARG_ENABLE([aggressive-decommit-by-default],
+              [AS_HELP_STRING([--enable-aggressive-decommit-by-default],
+                              [enable aggressive decommit by default])],
+              [enable_aggressive_decommit_by_default="$enableval"],
+              [enable_aggressive_decommit_by_default=no])
+AS_IF([test "x$enable_aggressive_decommit_by_default" = xyes],
+      [AC_DEFINE([ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT],
+                 1,
+                 [enable aggressive decommit by default])])
+
+# Write generated configuration file
+AC_CONFIG_FILES([Makefile
+                 src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h])
+AC_OUTPUT
+
+AS_IF([test "$omit_fp_by_default" = yes && test "x$enable_frame_pointers" != xyes && test "x$UNWIND_LIBS" = x && test "x$enable_minimal" != xyes],
+  [AS_IF([test "x$perftools_cv_have_unwind_backtrace" = xyes],
+    [AC_MSG_WARN([No frame pointers and no libunwind. Using experimental backtrace capturing via libgcc. Expect crashy cpu profiler.])],
+    [AS_IF([test "x$enable_backtrace" = xyes],
+      [AC_MSG_WARN([No frame pointers and no libunwind.  Using experimental backtrace(). Expect crashy cpu profiler.])],
+      [AC_MSG_FAILURE([No frame pointers and no libunwind. The compilation will fail])])])])
diff --git a/trunk/3rdparty/gperftools-2-fit/depcomp b/trunk/3rdparty/gperftools-2-fit/depcomp
new file mode 100755
index 000000000..6b391623c
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/depcomp
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva .
+
+case $1 in
+  '')
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputting dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to .
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='	'
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'.  On the theory
+## that the space means something, we add a space to the output as
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like '#:fec' to the end of the
+    # dependency line.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+      | tr "$nl" ' ' >> "$depfile"
+    echo >> "$depfile"
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+      >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  set_dir_from "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using '\' :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
+
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  set_dir_from  "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
+    sed -ne '2,${
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
+
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
+
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for ':'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+  "$@" $dashmflag |
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+        set fnord "$@"
+        shift
+        shift
+        ;;
+    *)
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile-fileformat.html b/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile-fileformat.html
new file mode 100644
index 000000000..3f90e6bc7
--- /dev/null
+++ b/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile-fileformat.html
@@ -0,0 +1,264 @@
+
+
+
+
+  
+  Google CPU Profiler Binary Data File Format
+
+
+
+
+

Google CPU Profiler Binary Data File Format

+ +

+ Last modified + +

+ +

This file documents the binary data file format produced by the +Google CPU Profiler. For information about using the CPU Profiler, +see its user guide. + +

The profiler source code, which generates files using this format, is at +src/profiler.cc. + + +

CPU Profile Data File Structure

+ +

CPU profile data files each consist of four parts, in order: + +

    +
  • Binary header +
  • Binary profile records +
  • Binary trailer +
  • Text list of mapped objects +
+ +

The binary data is expressed in terms of "slots." These are words +large enough to hold the program's pointer type, i.e., for 32-bit +programs they are 4 bytes in size, and for 64-bit programs they are 8 +bytes. They are stored in the profile data file in the native byte +order (i.e., little-endian for x86 and x86_64). + + +

Binary Header

+ +

The binary header format is show below. Values written by the +profiler, along with requirements currently enforced by the analysis +tools, are shown in parentheses. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
slotdata
0header count (0; must be 0)
1header slots after this one (3; must be >= 3)
2format version (0; must be 0)
3sampling period, in microseconds
4padding (0)
+ +

The headers currently generated for 32-bit and 64-bit little-endian +(x86 and x86_64) profiles are shown below, for comparison. + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hdr counthdr wordsversionsampling periodpad
32-bit or 64-bit (slots)030100000
32-bit (4-byte words in file)0x000000x000030x000000x027100x00000
64-bit LE (4-byte words in file)0x00000 0x000000x00003 0x000000x00000 0x000000x02710 0x000000x00000 0x00000
+ +

The contents are shown in terms of slots, and in terms of 4-byte +words in the profile data file. The slot contents for 32-bit and +64-bit headers are identical. For 32-bit profiles, the 4-byte word +view matches the slot view. For 64-bit profiles, each (8-byte) slot +is shown as two 4-byte words, ordered as they would appear in the +file. + +

The profiling tools examine the contents of the file and use the +expected locations and values of the header words field to detect +whether the file is 32-bit or 64-bit. + + +

Binary Profile Records

+ +

The binary profile record format is shown below. + +

+ + + + + + + + + + + + + + + + + + + +
slotdata
0sample count, must be >= 1
1number of call chain PCs (num_pcs), must be >= 1
2 .. (num_pcs + 1)call chain PCs, most-recently-called function first. +
+ +

The total length of a given record is 2 + num_pcs. + +

Note that multiple profile records can be emitted by the profiler +having an identical call chain. In that case, analysis tools should +sum the counts of all records having identical call chains. + +

Note: Some profile analysis tools terminate if they see +any profile record with a call chain with its first entry +having the address 0. (This is similar to the binary trailer.) + +

Example

+ +This example shows the slots contained in a sample profile record. + +

+ + + + + + + + +
530xa00000xc00000xe0000
+ +

In this example, 5 ticks were received at PC 0xa0000, whose +function had been called by the function containing 0xc0000, which had +been called from the function containing 0xe0000. + + +

Binary Trailer

+ +

The binary trailer consists of three slots of data with fixed +values, shown below. + +

+ + + + + + + + + + + + + + + + + + + + +
slotvalue
00
11
20
+ +

Note that this is the same data that would contained in a profile +record with sample count = 0, num_pcs = 1, and a one-element call +chain containing the address 0. + + +

Text List of Mapped Objects

+ +

The binary data in the file is followed immediately by a list of +mapped objects. This list consists of lines of text separated by +newline characters. + +

Each line is one of the following types: + +

    +
  • Build specifier, starting with "build=". For example: +
      build=/path/to/binary
    + Leading spaces on the line are ignored. + +
  • Mapping line from ProcMapsIterator::FormatLine. For example: +
      40000000-40015000 r-xp 00000000 03:01 12845071   /lib/ld-2.3.2.so
    + The first address must start at the beginning of the line. +
+ +

Unrecognized lines should be ignored by analysis tools. + +

When processing the paths see in mapping lines, occurrences of +$build followed by a non-word character (i.e., characters +other than underscore or alphanumeric characters), should be replaced +by the path given on the last build specifier line. + +


+
Chris Demetriou
+ + +Last modified: Mon Aug 27 12:18:26 PDT 2007 (cgd) + +
+ + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile.html b/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile.html new file mode 100644 index 000000000..c81feb6ae --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/cpuprofile.html @@ -0,0 +1,536 @@ + + + + + + Gperftools CPU Profiler + + + + +

+ Last modified + +

+ +

This is the CPU profiler we use at Google. There are three parts +to using it: linking the library into an application, running the +code, and analyzing the output.

+ +

On the off-chance that you should need to understand it, the CPU +profiler data file format is documented separately, +here. + + +

Linking in the Library

+ +

To install the CPU profiler into your executable, add +-lprofiler to the link-time step for your executable. +(It's also probably possible to add in the profiler at run-time using +LD_PRELOAD, e.g. +% env LD_PRELOAD="/usr/lib/libprofiler.so" <binary>, +but this isn't necessarily recommended.)

+ +

This does not turn on CPU profiling; it just inserts the +code. For that reason, it's practical to just always link +-lprofiler into a binary while developing; that's what we +do at Google. (However, since any user can turn on the profiler by +setting an environment variable, it's not necessarily recommended to +install profiler-linked binaries into a production, running +system.)

+ + +

Running the Code

+ +

There are several alternatives to actually turn on CPU profiling +for a given run of an executable:

+ +
    +
  1. Define the environment variable CPUPROFILE to the filename + to dump the profile to. For instance, if you had a version of + /bin/ls that had been linked against libprofiler, + you could run:

    +
    % env CPUPROFILE=ls.prof /bin/ls
    +
  2. +
  3. In addition to defining the environment variable CPUPROFILE + you can also define CPUPROFILESIGNAL. This allows profiling to be + controlled via the signal number that you specify. The signal number + must be unused by the program under normal operation. Internally it + acts as a switch, triggered by the signal, which is off by default. + For instance, if you had a copy of /bin/chrome that had been + been linked against libprofiler, you could run:

    +
    % env CPUPROFILE=chrome.prof CPUPROFILESIGNAL=12 /bin/chrome &
    +

    You can then trigger profiling to start:

    +
    % killall -12 chrome
    +

    Then after a period of time you can tell it to stop which will + generate the profile:

    +
    % killall -12 chrome
    +
  4. +
  5. In your code, bracket the code you want profiled in calls to + ProfilerStart() and ProfilerStop(). + (These functions are declared in <gperftools/profiler.h>.) + ProfilerStart() will take + the profile-filename as an argument.

    +
  6. +
+ +

In Linux 2.6 and above, profiling works correctly with threads, +automatically profiling all threads. In Linux 2.4, profiling only +profiles the main thread (due to a kernel bug involving itimers and +threads). Profiling works correctly with sub-processes: each child +process gets its own profile with its own name (generated by combining +CPUPROFILE with the child's process id).

+ +

For security reasons, CPU profiling will not write to a file -- and +is thus not usable -- for setuid programs.

+ +

See the include-file gperftools/profiler.h for +advanced-use functions, including ProfilerFlush() and +ProfilerStartWithOptions().

+ + +

Modifying Runtime Behavior

+ +

You can more finely control the behavior of the CPU profiler via +environment variables.

+ + + + + + + + + + + + + + + +
CPUPROFILE_FREQUENCY=xdefault: 100 + How many interrupts/second the cpu-profiler samples. +
CPUPROFILE_REALTIME=1default: [not set] + If set to any value (including 0 or the empty string), use + ITIMER_REAL instead of ITIMER_PROF to gather profiles. In + general, ITIMER_REAL is not as accurate as ITIMER_PROF, and also + interacts badly with use of alarm(), so prefer ITIMER_PROF unless + you have a reason prefer ITIMER_REAL. +
+ + +

Analyzing the Output

+ +

pprof is the script used to analyze a profile. It has +many output modes, both textual and graphical. Some give just raw +numbers, much like the -pg output of gcc, +and others show the data in the form of a dependency graph.

+ +

pprof requires perl5 to be installed to run. +It also requires dot to be installed for any of the +graphical output routines, and gv to be installed for +--gv mode (described below). +

+ +

Here are some ways to call pprof. These are described in more +detail below.

+ +
+% pprof /bin/ls ls.prof
+                       Enters "interactive" mode
+% pprof --text /bin/ls ls.prof
+                       Outputs one line per procedure
+% pprof --gv /bin/ls ls.prof
+                       Displays annotated call-graph via 'gv'
+% pprof --gv --focus=Mutex /bin/ls ls.prof
+                       Restricts to code paths including a .*Mutex.* entry
+% pprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof
+                       Code paths including Mutex but not string
+% pprof --list=getdir /bin/ls ls.prof
+                       (Per-line) annotated source listing for getdir()
+% pprof --disasm=getdir /bin/ls ls.prof
+                       (Per-PC) annotated disassembly for getdir()
+% pprof --text localhost:1234
+                       Outputs one line per procedure for localhost:1234
+% pprof --callgrind /bin/ls ls.prof
+                       Outputs the call information in callgrind format
+
+ + +

Analyzing Text Output

+ +

Text mode has lines of output that look like this:

+
+       14   2.1%  17.2%       58   8.7% std::_Rb_tree::find
+
+ +

Here is how to interpret the columns:

+
    +
  1. Number of profiling samples in this function +
  2. Percentage of profiling samples in this function +
  3. Percentage of profiling samples in the functions printed so far +
  4. Number of profiling samples in this function and its callees +
  5. Percentage of profiling samples in this function and its callees +
  6. Function name +
+ +

Analyzing Callgrind Output

+ +

Use kcachegrind to +analyze your callgrind output:

+
+% pprof --callgrind /bin/ls ls.prof > ls.callgrind
+% kcachegrind ls.callgrind
+
+ +

The cost is specified in 'hits', i.e. how many times a function +appears in the recorded call stack information. The 'calls' from +function a to b record how many times function b was found in the +stack traces directly below function a.

+ +

Tip: if you use a debug build the output will include file and line +number information and kcachegrind will show an annotated source +code view.

+ +

Node Information

+ +

In the various graphical modes of pprof, the output is a call graph +annotated with timing information, like so:

+ + +
+ +
+
+ +

Each node represents a procedure. The directed edges indicate +caller to callee relations. Each node is formatted as follows:

+ +
+Class Name
+Method Name
+local (percentage)
+of cumulative (percentage)
+
+ +

The last one or two lines contains the timing information. (The +profiling is done via a sampling method, where by default we take 100 +samples a second. Therefor one unit of time in the output corresponds +to about 10 milliseconds of execution time.) The "local" time is the +time spent executing the instructions directly contained in the +procedure (and in any other procedures that were inlined into the +procedure). The "cumulative" time is the sum of the "local" time and +the time spent in any callees. If the cumulative time is the same as +the local time, it is not printed.

+ +

For instance, the timing information for test_main_thread() +indicates that 155 units (about 1.55 seconds) were spent executing the +code in test_main_thread() and 200 units were spent while +executing test_main_thread() and its callees such as +snprintf().

+ +

The size of the node is proportional to the local count. The +percentage displayed in the node corresponds to the count divided by +the total run time of the program (that is, the cumulative count for +main()).

+ +

Edge Information

+ +

An edge from one node to another indicates a caller to callee +relationship. Each edge is labelled with the time spent by the callee +on behalf of the caller. E.g, the edge from +test_main_thread() to snprintf() indicates +that of the 200 samples in test_main_thread(), 37 are +because of calls to snprintf().

+ +

Note that test_main_thread() has an edge to +vsnprintf(), even though test_main_thread() +doesn't call that function directly. This is because the code was +compiled with -O2; the profile reflects the optimized +control flow.

+ +

Meta Information

+ +

The top of the display should contain some meta information +like:

+
+      /tmp/profiler2_unittest
+      Total samples: 202
+      Focusing on: 202
+      Dropped nodes with <= 1 abs(samples)
+      Dropped edges with <= 0 samples
+
+ +

This section contains the name of the program, and the total +samples collected during the profiling run. If the +--focus option is on (see the Focus +section below), the legend also contains the number of samples being +shown in the focused display. Furthermore, some unimportant nodes and +edges are dropped to reduce clutter. The characteristics of the +dropped nodes and edges are also displayed in the legend.

+ +

Focus and Ignore

+ +

You can ask pprof to generate a display focused on a particular +piece of the program. You specify a regular expression. Any portion +of the call-graph that is on a path which contains at least one node +matching the regular expression is preserved. The rest of the +call-graph is dropped on the floor. For example, you can focus on the +vsnprintf() libc call in profiler2_unittest +as follows:

+ +
+% pprof --gv --focus=vsnprintf /tmp/profiler2_unittest test.prof
+
+ +
+ +
+
+ +

Similarly, you can supply the --ignore option to +ignore samples that match a specified regular expression. E.g., if +you are interested in everything except calls to +snprintf(), you can say:

+
+% pprof --gv --ignore=snprintf /tmp/profiler2_unittest test.prof
+
+ + +

Interactive mode

+ +

By default -- if you don't specify any flags to the contrary -- +pprof runs in interactive mode. At the (pprof) prompt, +you can run many of the commands described above. You can type +help for a list of what commands are available in +interactive mode.

+ +

pprof Options

+ +For a complete list of pprof options, you can run pprof +--help. + +

Output Type

+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--text + Produces a textual listing. (Note: If you have an X display, and + dot and gv installed, you will probably + be happier with the --gv output.) +
--gv + Generates annotated call-graph, converts to postscript, and + displays via gv (requres dot and gv be + installed). +
--dot + Generates the annotated call-graph in dot format and + emits to stdout (requres dot be installed). +
--ps + Generates the annotated call-graph in Postscript format and + emits to stdout (requres dot be installed). +
--pdf + Generates the annotated call-graph in PDF format and emits to + stdout (requires dot and ps2pdf be + installed). +
--gif + Generates the annotated call-graph in GIF format and + emits to stdout (requres dot be installed). +
--list=<regexp> +

Outputs source-code listing of routines whose + name matches <regexp>. Each line + in the listing is annotated with flat and cumulative + sample counts.

+ +

In the presence of inlined calls, the samples + associated with inlined code tend to get assigned + to a line that follows the location of the + inlined call. A more precise accounting can be + obtained by disassembling the routine using the + --disasm flag.

+
--disasm=<regexp> + Generates disassembly of routines that match + <regexp>, annotated with flat and + cumulative sample counts and emits to stdout. +
+
+ +

Reporting Granularity

+ +

By default, pprof produces one entry per procedure. However you can +use one of the following options to change the granularity of the +output. The --files option seems to be particularly +useless, and may be removed eventually.

+ +
+ + + + + + + + + + + + + + +
--addresses + Produce one node per program address. +
--lines + Produce one node per source line. +
--functions + Produce one node per function (this is the default). +
--files + Produce one node per source file. +
+
+ +

Controlling the Call Graph Display

+ +

Some nodes and edges are dropped to reduce clutter in the output +display. The following options control this effect:

+ +
+ + + + + + + + + + + + + + + + + + + + + +
--nodecount=<n> + This option controls the number of displayed nodes. The nodes + are first sorted by decreasing cumulative count, and then only + the top N nodes are kept. The default value is 80. +
--nodefraction=<f> + This option provides another mechanism for discarding nodes + from the display. If the cumulative count for a node is + less than this option's value multiplied by the total count + for the profile, the node is dropped. The default value + is 0.005; i.e. nodes that account for less than + half a percent of the total time are dropped. A node + is dropped if either this condition is satisfied, or the + --nodecount condition is satisfied. +
--edgefraction=<f> + This option controls the number of displayed edges. First of all, + an edge is dropped if either its source or destination node is + dropped. Otherwise, the edge is dropped if the sample + count along the edge is less than this option's value multiplied + by the total count for the profile. The default value is + 0.001; i.e., edges that account for less than + 0.1% of the total time are dropped. +
--focus=<re> + This option controls what region of the graph is displayed + based on the regular expression supplied with the option. + For any path in the callgraph, we check all nodes in the path + against the supplied regular expression. If none of the nodes + match, the path is dropped from the output. +
--ignore=<re> + This option controls what region of the graph is displayed + based on the regular expression supplied with the option. + For any path in the callgraph, we check all nodes in the path + against the supplied regular expression. If any of the nodes + match, the path is dropped from the output. +
+
+ +

The dropped edges and nodes account for some count mismatches in +the display. For example, the cumulative count for +snprintf() in the first diagram above was 41. However +the local count (1) and the count along the outgoing edges (12+1+20+6) +add up to only 40.

+ + +

Caveats

+ +
    +
  • If the program exits because of a signal, the generated profile + will be incomplete, and may perhaps be + completely empty. +
  • The displayed graph may have disconnected regions because + of the edge-dropping heuristics described above. +
  • If the program linked in a library that was not compiled + with enough symbolic information, all samples associated + with the library may be charged to the last symbol found + in the program before the library. This will artificially + inflate the count for that symbol. +
  • If you run the program on one machine, and profile it on + another, and the shared libraries are different on the two + machines, the profiling output may be confusing: samples that + fall within shared libaries may be assigned to arbitrary + procedures. +
  • If your program forks, the children will also be profiled + (since they inherit the same CPUPROFILE setting). Each process + is profiled separately; to distinguish the child profiles from + the parent profile and from each other, all children will have + their process-id appended to the CPUPROFILE name. +
  • Due to a hack we make to work around a possible gcc bug, your + profiles may end up named strangely if the first character of + your CPUPROFILE variable has ascii value greater than 127. + This should be exceedingly rare, but if you need to use such a + name, just set prepend ./ to your filename: + CPUPROFILE=./Ägypten. +
+ + +
+
Sanjay Ghemawat
+ + +Last modified: Fri May 9 14:41:29 PDT 2008 + +
+ + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/designstyle.css b/trunk/3rdparty/gperftools-2-fit/docs/designstyle.css new file mode 100644 index 000000000..29299af1f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/designstyle.css @@ -0,0 +1,109 @@ +body { + background-color: #ffffff; + color: black; + margin-right: 1in; + margin-left: 1in; +} + + +h1, h2, h3, h4, h5, h6 { + color: #3366ff; + font-family: sans-serif; +} +@media print { + /* Darker version for printing */ + h1, h2, h3, h4, h5, h6 { + color: #000080; + font-family: helvetica, sans-serif; + } +} + +h1 { + text-align: center; + font-size: 18pt; +} +h2 { + margin-left: -0.5in; +} +h3 { + margin-left: -0.25in; +} +h4 { + margin-left: -0.125in; +} +hr { + margin-left: -1in; +} + +/* Definition lists: definition term bold */ +dt { + font-weight: bold; +} + +address { + text-align: right; +} +/* Use the tag for bits of code and for variables and objects. */ +code,pre,samp,var { + color: #006000; +} +/* Use the tag for file and directory paths and names. */ +file { + color: #905050; + font-family: monospace; +} +/* Use the tag for stuff the user should type. */ +kbd { + color: #600000; +} +div.note p { + float: right; + width: 3in; + margin-right: 0%; + padding: 1px; + border: 2px solid #6060a0; + background-color: #fffff0; +} + +UL.nobullets { + list-style-type: none; + list-style-image: none; + margin-left: -1em; +} + +/* pretty printing styles. See prettify.js */ +.str { color: #080; } +.kwd { color: #008; } +.com { color: #800; } +.typ { color: #606; } +.lit { color: #066; } +.pun { color: #660; } +.pln { color: #000; } +.tag { color: #008; } +.atn { color: #606; } +.atv { color: #080; } +pre.prettyprint { padding: 2px; border: 1px solid #888; } + +.embsrc { background: #eee; } + +@media print { + .str { color: #060; } + .kwd { color: #006; font-weight: bold; } + .com { color: #600; font-style: italic; } + .typ { color: #404; font-weight: bold; } + .lit { color: #044; } + .pun { color: #440; } + .pln { color: #000; } + .tag { color: #006; font-weight: bold; } + .atn { color: #404; } + .atv { color: #060; } +} + +/* Table Column Headers */ +.hdr { + color: #006; + font-weight: bold; + background-color: #dddddd; } +.hdr2 { + color: #006; + background-color: #eeeeee; } \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/docs/heap-example1.png b/trunk/3rdparty/gperftools-2-fit/docs/heap-example1.png new file mode 100644 index 0000000000000000000000000000000000000000..9a14b6fb89e66316368656ae26f2250a25760951 GIT binary patch literal 37619 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/heap_checker.html b/trunk/3rdparty/gperftools-2-fit/docs/heap_checker.html new file mode 100644 index 000000000..ca05b5003 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/heap_checker.html @@ -0,0 +1,534 @@ + + + + + + Gperftools Heap Leak Checker + + + + +

+ Last modified + +

+ +

This is the heap checker we use at Google to detect memory leaks in +C++ programs. There are three parts to using it: linking the library +into an application, running the code, and analyzing the output.

+ + +

Linking in the Library

+ +

The heap-checker is part of tcmalloc, so to install the heap +checker into your executable, add -ltcmalloc to the +link-time step for your executable. Also, while we don't necessarily +recommend this form of usage, it's possible to add in the profiler at +run-time using LD_PRELOAD:

+
% env LD_PRELOAD="/usr/lib/libtcmalloc.so" 
+ +

This does not turn on heap checking; it just inserts the +code. For that reason, it's practical to just always link +-ltcmalloc into a binary while developing; that's what we +do at Google. (However, since any user can turn on the profiler by +setting an environment variable, it's not necessarily recommended to +install heapchecker-linked binaries into a production, running +system.) Note that if you wish to use the heap checker, you must +also use the tcmalloc memory-allocation library. There is no way +currently to use the heap checker separate from tcmalloc.

+ + +

Running the Code

+ +

Note: For security reasons, heap profiling will not write to a file +-- and is thus not usable -- for setuid programs.

+ +

Whole-program Heap Leak Checking

+ +

The recommended way to use the heap checker is in "whole program" +mode. In this case, the heap-checker starts tracking memory +allocations before the start of main(), and checks again +at program-exit. If it finds any memory leaks -- that is, any memory +not pointed to by objects that are still "live" at program-exit -- it +aborts the program (via exit(1)) and prints a message +describing how to track down the memory leak (using pprof).

+ +

The heap-checker records the stack trace for each allocation while +it is active. This causes a significant increase in memory usage, in +addition to slowing your program down.

+ +

Here's how to run a program with whole-program heap checking:

+ +
    +
  1. Define the environment variable HEAPCHECK to the type of heap-checking to do. For instance, + to heap-check + /usr/local/bin/my_binary_compiled_with_tcmalloc:

    +
    % env HEAPCHECK=normal /usr/local/bin/my_binary_compiled_with_tcmalloc
    +
+ +

No other action is required.

+ +

Note that since the heap-checker uses the heap-profiling framework +internally, it is not possible to run both the heap-checker and heap profiler at the same time.

+ + +

Flavors of Heap Checking

+ +

These are the legal values when running a whole-program heap +check:

+
    +
  1. minimal +
  2. normal +
  3. strict +
  4. draconian +
+ +

"Minimal" heap-checking starts as late as possible in a +initialization, meaning you can leak some memory in your +initialization routines (that run before main(), say), +and not trigger a leak message. If you frequently (and purposefully) +leak data in one-time global initializers, "minimal" mode is useful +for you. Otherwise, you should avoid it for stricter modes.

+ +

"Normal" heap-checking tracks live objects and +reports a leak for any data that is not reachable via a live object +when the program exits.

+ +

"Strict" heap-checking is much like "normal" but has a few extra +checks that memory isn't lost in global destructors. In particular, +if you have a global variable that allocates memory during program +execution, and then "forgets" about the memory in the global +destructor (say, by setting the pointer to it to NULL) without freeing +it, that will prompt a leak message in "strict" mode, though not in +"normal" mode.

+ +

"Draconian" heap-checking is appropriate for those who like to be +very precise about their memory management, and want the heap-checker +to help them enforce it. In "draconian" mode, the heap-checker does +not do "live object" checking at all, so it reports a leak unless +all allocated memory is freed before program exit. (However, +you can use IgnoreObject() to re-enable +liveness-checking on an object-by-object basis.)

+ +

"Normal" mode, as the name implies, is the one used most often at +Google. It's appropriate for everyday heap-checking use.

+ +

In addition, there are two other possible modes:

+
    +
  • as-is +
  • local +
+

as-is is the most flexible mode; it allows you to +specify the various knobs of the heap checker +explicitly. local activates the explicit heap-check instrumentation, but does not +turn on any whole-program leak checking.

+ + +

Tweaking whole-program checking

+ +

In some cases you want to check the whole program for memory leaks, +but waiting for after main() exits to do the first +whole-program leak check is waiting too long: e.g. in a long-running +server one might wish to simply periodically check for leaks while the +server is running. In this case, you can call the static method +HeapLeakChecker::NoGlobalLeaks(), to verify no global leaks have happened +as of that point in the program.

+ +

Alternately, doing the check after main() exits might +be too late. Perhaps you have some objects that are known not to +clean up properly at exit. You'd like to do the "at exit" check +before those objects are destroyed (since while they're live, any +memory they point to will not be considered a leak). In that case, +you can call HeapLeakChecker::NoGlobalLeaks() manually, near the end of +main(), and then call HeapLeakChecker::CancelGlobalCheck() to +turn off the automatic post-main() check.

+ +

Finally, there's a helper macro for "strict" and "draconian" modes, +which require all global memory to be freed before program exit. This +freeing can be time-consuming and is often unnecessary, since libc +cleans up all memory at program-exit for you. If you want the +benefits of "strict"/"draconian" modes without the cost of all that +freeing, look at REGISTER_HEAPCHECK_CLEANUP (in +heap-checker.h). This macro allows you to mark specific +cleanup code as active only when the heap-checker is turned on.

+ + +

Explicit (Partial-program) Heap Leak Checking

+ +

Instead of whole-program checking, you can check certain parts of your +code to verify they do not have memory leaks. This check verifies that +between two parts of a program, no memory is allocated without being freed.

+

To use this kind of checking code, bracket the code you want +checked by creating a HeapLeakChecker object at the +beginning of the code segment, and call +NoLeaks() at the end. These functions, and all others +referred to in this file, are declared in +<gperftools/heap-checker.h>. +

+ +

Here's an example:

+
+  HeapLeakChecker heap_checker("test_foo");
+  {
+    code that exercises some foo functionality;
+    this code should not leak memory;
+  }
+  if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak");
+
+ +

Note that adding in the HeapLeakChecker object merely +instruments the code for leak-checking. To actually turn on this +leak-checking on a particular run of the executable, you must still +run with the heap-checker turned on:

+
% env HEAPCHECK=local /usr/local/bin/my_binary_compiled_with_tcmalloc
+

If you want to do whole-program leak checking in addition to this +manual leak checking, you can run in normal or some other +mode instead: they'll run the "local" checks in addition to the +whole-program check.

+ + +

Disabling Heap-checking of Known Leaks

+ +

Sometimes your code has leaks that you know about and are willing +to accept. You would like the heap checker to ignore them when +checking your program. You can do this by bracketing the code in +question with an appropriate heap-checking construct:

+
+   ...
+   {
+     HeapLeakChecker::Disabler disabler;
+     <leaky code>
+   }
+   ...
+
+Any objects allocated by leaky code (including inside any +routines called by leaky code) and any objects reachable +from such objects are not reported as leaks. + +

Alternately, you can use IgnoreObject(), which takes a +pointer to an object to ignore. That memory, and everything reachable +from it (by following pointers), is ignored for the purposes of leak +checking. You can call UnIgnoreObject() to undo the +effects of IgnoreObject().

+ + +

Tuning the Heap Checker

+ +

The heap leak checker has many options, some that trade off running +time and accuracy, and others that increase the sensitivity at the +risk of returning false positives. For most uses, the range covered +by the heap-check flavors is enough, but in +specialized cases more control can be helpful.

+ +

+These options are specified via environment varaiables. +

+ +

This first set of options controls sensitivity and accuracy. These +options are ignored unless you run the heap checker in as-is mode. + + + + + + + + + + + + + + + + + + + + + +
HEAP_CHECK_AFTER_DESTRUCTORSDefault: false + When true, do the final leak check after all other global + destructors have run. When false, do it after all + REGISTER_HEAPCHECK_CLEANUP, typically much earlier in + the global-destructor process. +
HEAP_CHECK_IGNORE_THREAD_LIVEDefault: true + If true, ignore objects reachable from thread stacks and registers + (that is, do not report them as leaks). +
HEAP_CHECK_IGNORE_GLOBAL_LIVEDefault: true + If true, ignore objects reachable from global variables and data + (that is, do not report them as leaks). +
+ +

These options modify the behavior of whole-program leak +checking.

+ + + + + + + + + + +
HEAP_CHECK_MAX_LEAKSDefault: 20 + The maximum number of leaks to be printed to stderr (all leaks are still + emitted to file output for pprof to visualize). If negative or zero, + print all the leaks found. +
+ +

These options apply to all types of leak checking.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HEAP_CHECK_IDENTIFY_LEAKSDefault: false + If true, generate the addresses of the leaked objects in the + generated memory leak profile files. +
HEAP_CHECK_TEST_POINTER_ALIGNMENTDefault: false + If true, check all leaks to see if they might be due to the use + of unaligned pointers. +
HEAP_CHECK_POINTER_SOURCE_ALIGNMENTDefault: sizeof(void*) + Alignment at which all pointers in memory are supposed to be located. + Use 1 if any alignment is ok. +
PPROF_PATHDefault: pprof + The location of the pprof executable. +
HEAP_CHECK_DUMP_DIRECTORYDefault: /tmp + Where the heap-profile files are kept while the program is running. +
+ + +

Tips for Handling Detected Leaks

+ +

What do you do when the heap leak checker detects a memory leak? +First, you should run the reported pprof command; +hopefully, that is enough to track down the location where the leak +occurs.

+ +

If the leak is a real leak, you should fix it!

+ +

If you are sure that the reported leaks are not dangerous and there +is no good way to fix them, then you can use +HeapLeakChecker::Disabler and/or +HeapLeakChecker::IgnoreObject() to disable heap-checking +for certain parts of the codebase.

+ +

In "strict" or "draconian" mode, leaks may be due to incomplete +cleanup in the destructors of global variables. If you don't wish to +augment the cleanup routines, but still want to run in "strict" or +"draconian" mode, consider using REGISTER_HEAPCHECK_CLEANUP.

+ +

Hints for Debugging Detected Leaks

+ +

Sometimes it can be useful to not only know the exact code that +allocates the leaked objects, but also the addresses of the leaked objects. +Combining this e.g. with additional logging in the program +one can then track which subset of the allocations +made at a certain spot in the code are leaked. +
+To get the addresses of all leaked objects + define the environment variable HEAP_CHECK_IDENTIFY_LEAKS + to be 1. +The object addresses will be reported in the form of addresses +of fake immediate callers of the memory allocation routines. +Note that the performance of doing leak-checking in this mode +can be noticeably worse than the default mode. +

+ +

One relatively common class of leaks that don't look real +is the case of multiple initialization. +In such cases the reported leaks are typically things that are +linked from some global objects, +which are initialized and say never modified again. +The non-obvious cause of the leak is frequently the fact that +the initialization code for these objects executes more than once. +
+E.g. if the code of some .cc file is made to be included twice +into the binary, then the constructors for global objects defined in that file +will execute twice thus leaking the things allocated on the first run. +
+Similar problems can occur if object initialization is done more explicitly +e.g. on demand by a slightly buggy code +that does not always ensure only-once initialization. +

+ +

+A more rare but even more puzzling problem can be use of not properly +aligned pointers (maybe inside of not properly aligned objects). +Normally such pointers are not followed by the leak checker, +hence the objects reachable only via such pointers are reported as leaks. +If you suspect this case + define the environment variable HEAP_CHECK_TEST_POINTER_ALIGNMENT + to be 1 +and then look closely at the generated leak report messages. +

+ +

How It Works

+ +

When a HeapLeakChecker object is constructed, it dumps +a memory-usage profile named +<prefix>.<name>-beg.heap to a temporary +directory. When NoLeaks() +is called (for whole-program checking, this happens automatically at +program-exit), it dumps another profile, named +<prefix>.<name>-end.heap. +(<prefix> is typically determined automatically, +and <name> is typically argv[0].) It +then compares the two profiles. If the second profile shows +more memory use than the first, the +NoLeaks() function will +return false. For "whole program" profiling, this will cause the +executable to abort (via exit(1)). In all cases, it will +print a message on how to process the dumped profiles to locate +leaks.

+ +

Detecting Live Objects

+ +

At any point during a program's execution, all memory that is +accessible at that time is considered "live." This includes global +variables, and also any memory that is reachable by following pointers +from a global variable. It also includes all memory reachable from +the current stack frame and from current CPU registers (this captures +local variables). Finally, it includes the thread equivalents of +these: thread-local storage and thread heaps, memory reachable from +thread-local storage and thread heaps, and memory reachable from +thread CPU registers.

+ +

In all modes except "draconian," live memory is not +considered to be a leak. We detect this by doing a liveness flood, +traversing pointers to heap objects starting from some initial memory +regions we know to potentially contain live pointer data. Note that +this flood might potentially not find some (global) live data region +to start the flood from. If you find such, please file a bug.

+ +

The liveness flood attempts to treat any properly aligned byte +sequences as pointers to heap objects and thinks that it found a good +pointer whenever the current heap memory map contains an object with +the address whose byte representation we found. Some pointers into +not-at-start of object will also work here.

+ +

As a result of this simple approach, it's possible (though +unlikely) for the flood to be inexact and occasionally result in +leaked objects being erroneously determined to be live. For instance, +random bit patterns can happen to look like pointers to leaked heap +objects. More likely, stale pointer data not corresponding to any +live program variables can be still present in memory regions, +especially in thread stacks. For instance, depending on how the local +malloc is implemented, it may reuse a heap object +address:

+
+    char* p = new char[1];   // new might return 0x80000000, say.
+    delete p;
+    new char[1];             // new might return 0x80000000 again
+    // This last new is a leak, but doesn't seem it: p looks like it points to it
+
+ +

In other words, imprecisions in the liveness flood mean that for +any heap leak check we might miss some memory leaks. This means that +for local leak checks, we might report a memory leak in the local +area, even though the leak actually happened before the +HeapLeakChecker object was constructed. Note that for +whole-program checks, a leak report does always correspond to a +real leak (since there's no "before" to have created a false-live +object).

+ +

While this liveness flood approach is not very portable and not +100% accurate, it works in most cases and saves us from writing a lot +of explicit clean up code and other hassles when dealing with thread +data.

+ + +

Visualizing Leak with pprof

+ +

+The heap checker automatically prints basic leak info with stack traces of +leaked objects' allocation sites, as well as a pprof command line that can be +used to visualize the call-graph involved in these allocations. +The latter can be much more useful for a human +to see where/why the leaks happened, especially if the leaks are numerous. +

+ +

Leak-checking and Threads

+ +

At the time of HeapLeakChecker's construction and during +NoLeaks() calls, we grab a lock +and then pause all other threads so other threads do not interfere +with recording or analyzing the state of the heap.

+ +

In general, leak checking works correctly in the presence of +threads. However, thread stack data liveness determination (via +base/thread_lister.h) does not work when the program is +running under GDB, because the ptrace functionality needed for finding +threads is already hooked to by GDB. Conversely, leak checker's +ptrace attempts might also interfere with GDB. As a result, GDB can +result in potentially false leak reports. For this reason, the +heap-checker turns itself off when running under GDB.

+ +

Also, thread_lister only works for Linux pthreads; +leak checking is unlikely to handle other thread implementations +correctly.

+ +

As mentioned in the discussion of liveness flooding, thread-stack +liveness determination might mis-classify as reachable objects that +very recently became unreachable (leaked). This can happen when the +pointers to now-logically-unreachable objects are present in the +active thread stack frame. In other words, trivial code like the +following might not produce the expected leak checking outcome +depending on how the compiled code works with the stack:

+
+  int* foo = new int [20];
+  HeapLeakChecker check("a_check");
+  foo = NULL;
+  // May fail to trigger.
+  if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak");
+
+ + +
+
Maxim Lifantsev
+ + +Last modified: Fri Jul 13 13:14:33 PDT 2007 + +
+ + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/heapprofile.html b/trunk/3rdparty/gperftools-2-fit/docs/heapprofile.html new file mode 100644 index 000000000..6f508699e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/heapprofile.html @@ -0,0 +1,391 @@ + + + + + + Gperftools Heap Profiler + + + + +

+ Last modified + +

+ +

This is the heap profiler we use at Google, to explore how C++ +programs manage memory. This facility can be useful for

+
    +
  • Figuring out what is in the program heap at any given time +
  • Locating memory leaks +
  • Finding places that do a lot of allocation +
+ +

The profiling system instruments all allocations and frees. It +keeps track of various pieces of information per allocation site. An +allocation site is defined as the active stack trace at the call to +malloc, calloc, realloc, or, +new.

+ +

There are three parts to using it: linking the library into an +application, running the code, and analyzing the output.

+ + +

Linking in the Library

+ +

To install the heap profiler into your executable, add +-ltcmalloc to the link-time step for your executable. +Also, while we don't necessarily recommend this form of usage, it's +possible to add in the profiler at run-time using +LD_PRELOAD: +

% env LD_PRELOAD="/usr/lib/libtcmalloc.so" <binary>
+ +

This does not turn on heap profiling; it just inserts the +code. For that reason, it's practical to just always link +-ltcmalloc into a binary while developing; that's what we +do at Google. (However, since any user can turn on the profiler by +setting an environment variable, it's not necessarily recommended to +install profiler-linked binaries into a production, running +system.) Note that if you wish to use the heap profiler, you must +also use the tcmalloc memory-allocation library. There is no way +currently to use the heap profiler separate from tcmalloc.

+ + +

Running the Code

+ +

There are several alternatives to actually turn on heap profiling +for a given run of an executable:

+ +
    +
  1. Define the environment variable HEAPPROFILE to the filename + to dump the profile to. For instance, to profile + /usr/local/bin/my_binary_compiled_with_tcmalloc:

    +
    % env HEAPPROFILE=/tmp/mybin.hprof /usr/local/bin/my_binary_compiled_with_tcmalloc
    +
  2. In your code, bracket the code you want profiled in calls to + HeapProfilerStart() and HeapProfilerStop(). + (These functions are declared in <gperftools/heap-profiler.h>.) + HeapProfilerStart() will take the + profile-filename-prefix as an argument. Then, as often as + you'd like before calling HeapProfilerStop(), you + can use HeapProfilerDump() or + GetHeapProfile() to examine the profile. In case + it's useful, IsHeapProfilerRunning() will tell you + whether you've already called HeapProfilerStart() or not.

    +
+ + +

For security reasons, heap profiling will not write to a file -- +and is thus not usable -- for setuid programs.

+ +

Modifying Runtime Behavior

+ +

You can more finely control the behavior of the heap profiler via +environment variables.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HEAP_PROFILE_ALLOCATION_INTERVALdefault: 1073741824 (1 Gb) + Dump heap profiling information each time the specified number of + bytes has been allocated by the program. +
HEAP_PROFILE_INUSE_INTERVALdefault: 104857600 (100 Mb) + Dump heap profiling information whenever the high-water memory + usage mark increases by the specified number of bytes. +
HEAP_PROFILE_TIME_INTERVALdefault: 0 + Dump heap profiling information each time the specified + number of seconds has elapsed. +
HEAPPROFILESIGNALdefault: disabled + Dump heap profiling information whenever the specified signal is sent to the + process. +
HEAP_PROFILE_MMAPdefault: false + Profile mmap, mremap and sbrk + calls in addition + to malloc, calloc, realloc, + and new. NOTE: this causes the profiler to + profile calls internal to tcmalloc, since tcmalloc and friends use + mmap and sbrk internally for allocations. One partial solution is + to filter these allocations out when running pprof, + with something like + pprof --ignore='DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc. +
HEAP_PROFILE_ONLY_MMAPdefault: false + Only profile mmap, mremap, and sbrk + calls; do not profile + malloc, calloc, realloc, + or new. +
HEAP_PROFILE_MMAP_LOGdefault: false + Log mmap/munmap calls. +
+ +

Checking for Leaks

+ +

You can use the heap profiler to manually check for leaks, for +instance by reading the profiler output and looking for large +allocations. However, for that task, it's easier to use the automatic heap-checking facility built +into tcmalloc.

+ + +

Analyzing the Output

+ +

If heap-profiling is turned on in a program, the program will +periodically write profiles to the filesystem. The sequence of +profiles will be named:

+
+           <prefix>.0000.heap
+           <prefix>.0001.heap
+           <prefix>.0002.heap
+           ...
+
+

where <prefix> is the filename-prefix supplied +when running the code (e.g. via the HEAPPROFILE +environment variable). Note that if the supplied prefix +does not start with a /, the profile files will be +written to the program's working directory.

+ +

The profile output can be viewed by passing it to the +pprof tool -- the same tool that's used to analyze CPU profiles. + +

Here are some examples. These examples assume the binary is named +gfs_master, and a sequence of heap profile files can be +found in files named:

+
+  /tmp/profile.0001.heap
+  /tmp/profile.0002.heap
+  ...
+  /tmp/profile.0100.heap
+
+ +

Why is a process so big

+ +
+    % pprof --gv gfs_master /tmp/profile.0100.heap
+
+ +

This command will pop-up a gv window that displays +the profile information as a directed graph. Here is a portion +of the resulting output:

+ +

+ +

+ +A few explanations: +
    +
  • GFS_MasterChunk::AddServer accounts for 255.6 MB + of the live memory, which is 25% of the total live memory. +
  • GFS_MasterChunkTable::UpdateState is directly + accountable for 176.2 MB of the live memory (i.e., it directly + allocated 176.2 MB that has not been freed yet). Furthermore, + it and its callees are responsible for 729.9 MB. The + labels on the outgoing edges give a good indication of the + amount allocated by each callee. +
+ +

Comparing Profiles

+ +

You often want to skip allocations during the initialization phase +of a program so you can find gradual memory leaks. One simple way to +do this is to compare two profiles -- both collected after the program +has been running for a while. Specify the name of the first profile +using the --base option. For example:

+
+   % pprof --base=/tmp/profile.0004.heap gfs_master /tmp/profile.0100.heap
+
+ +

The memory-usage in /tmp/profile.0004.heap will be +subtracted from the memory-usage in +/tmp/profile.0100.heap and the result will be +displayed.

+ +

Text display

+ +
+% pprof --text gfs_master /tmp/profile.0100.heap
+   255.6  24.7%  24.7%    255.6  24.7% GFS_MasterChunk::AddServer
+   184.6  17.8%  42.5%    298.8  28.8% GFS_MasterChunkTable::Create
+   176.2  17.0%  59.5%    729.9  70.5% GFS_MasterChunkTable::UpdateState
+   169.8  16.4%  75.9%    169.8  16.4% PendingClone::PendingClone
+    76.3   7.4%  83.3%     76.3   7.4% __default_alloc_template::_S_chunk_alloc
+    49.5   4.8%  88.0%     49.5   4.8% hashtable::resize
+   ...
+
+ +

+

    +
  • The first column contains the direct memory use in MB. +
  • The fourth column contains memory use by the procedure + and all of its callees. +
  • The second and fifth columns are just percentage + representations of the numbers in the first and fourth columns. +
  • The third column is a cumulative sum of the second column + (i.e., the kth entry in the third column is the + sum of the first k entries in the second column.) +
+ +

Ignoring or focusing on specific regions

+ +

The following command will give a graphical display of a subset of +the call-graph. Only paths in the call-graph that match the regular +expression DataBuffer are included:

+
+% pprof --gv --focus=DataBuffer gfs_master /tmp/profile.0100.heap
+
+ +

Similarly, the following command will omit all paths subset of the +call-graph. All paths in the call-graph that match the regular +expression DataBuffer are discarded:

+
+% pprof --gv --ignore=DataBuffer gfs_master /tmp/profile.0100.heap
+
+ +

Total allocations + object-level information

+ +

All of the previous examples have displayed the amount of in-use +space. I.e., the number of bytes that have been allocated but not +freed. You can also get other types of information by supplying a +flag to pprof:

+ +
+ + + + + + + + + + + + + + + + + + + + + +
--inuse_space + Display the number of in-use megabytes (i.e. space that has + been allocated but not freed). This is the default. +
--inuse_objects + Display the number of in-use objects (i.e. number of + objects that have been allocated but not freed). +
--alloc_space + Display the number of allocated megabytes. This includes + the space that has since been de-allocated. Use this + if you want to find the main allocation sites in the + program. +
--alloc_objects + Display the number of allocated objects. This includes + the objects that have since been de-allocated. Use this + if you want to find the main allocation sites in the + program. +
+
+ + +

Interactive mode

+ +

By default -- if you don't specify any flags to the contrary -- +pprof runs in interactive mode. At the (pprof) prompt, +you can run many of the commands described above. You can type +help for a list of what commands are available in +interactive mode.

+ + +

Caveats

+ +
    +
  • Heap profiling requires the use of libtcmalloc. This + requirement may be removed in a future version of the heap + profiler, and the heap profiler separated out into its own + library. + +
  • If the program linked in a library that was not compiled + with enough symbolic information, all samples associated + with the library may be charged to the last symbol found + in the program before the library. This will artificially + inflate the count for that symbol. + +
  • If you run the program on one machine, and profile it on + another, and the shared libraries are different on the two + machines, the profiling output may be confusing: samples that + fall within the shared libaries may be assigned to arbitrary + procedures. + +
  • Several libraries, such as some STL implementations, do their + own memory management. This may cause strange profiling + results. We have code in libtcmalloc to cause STL to use + tcmalloc for memory management (which in our tests is better + than STL's internal management), though it only works for some + STL implementations. + +
  • If your program forks, the children will also be profiled + (since they inherit the same HEAPPROFILE setting). Each + process is profiled separately; to distinguish the child + profiles from the parent profile and from each other, all + children will have their process-id attached to the HEAPPROFILE + name. + +
  • Due to a hack we make to work around a possible gcc bug, your + profiles may end up named strangely if the first character of + your HEAPPROFILE variable has ascii value greater than 127. + This should be exceedingly rare, but if you need to use such a + name, just set prepend ./ to your filename: + HEAPPROFILE=./Ägypten. +
+ +
+
Sanjay Ghemawat + +
+ + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/index.html b/trunk/3rdparty/gperftools-2-fit/docs/index.html new file mode 100644 index 000000000..7b93ed396 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/index.html @@ -0,0 +1,20 @@ + + + +Gperftools + + + + + +
+Last modified: Thu Feb 2 14:40:47 PST 2012 + + + + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/overview.dot b/trunk/3rdparty/gperftools-2-fit/docs/overview.dot new file mode 100644 index 000000000..9966f56cf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/overview.dot @@ -0,0 +1,15 @@ +digraph Overview { +node [shape = box] + +{rank=same +T1 [label="Thread Cache"] +Tsep [label="...", shape=plaintext] +Tn [label="Thread Cache"] +T1 -> Tsep -> Tn [style=invis] +} + +C [label="Central\nHeap"] +T1 -> C [dir=both] +Tn -> C [dir=both] + +} diff --git a/trunk/3rdparty/gperftools-2-fit/docs/overview.gif b/trunk/3rdparty/gperftools-2-fit/docs/overview.gif new file mode 100644 index 0000000000000000000000000000000000000000..43828dadec8b7ceb5e85e863fb35d78f172d5f46 GIT binary patch literal 6472 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 O0 -> O1 -> sep1 +heap:f1 -> O2 -> O3 -> sep2 +heap:f2 -> O4 -> O5 -> sep3 +heap:f128 -> O6 -> O7 -> sep4 + +} diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pageheap.gif b/trunk/3rdparty/gperftools-2-fit/docs/pageheap.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cf00bd9cdb738586bc057da89ef3a3651b99ed5 GIT binary patch literal 5942 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 JECK*@{|}y!zAyj) literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof-test-big.gif b/trunk/3rdparty/gperftools-2-fit/docs/pprof-test-big.gif new file mode 100644 index 0000000000000000000000000000000000000000..67a1240fc10321edacdf8313197120cdddbd07ec GIT binary patch literal 111566 zcmd444}4SQy+8isPt%i-)-s`C%q zU6P(woX8EOxY8BYY76+M&N-^i4NdFBTCsLTaZ{%-fy(9UaC6h$>)p-o{XFNK{A&_$ z_xIiR-q)_L(kACT&*%C4eSiKuiz*kEJ66xuhO|E?BpePC`rrTl@WT(k_O-A5;0Hf= z>7|#x@r`eM>s#OY$xnWQKPCL1 z{abK*>yEaa5C5orSI3V#cklU0SN9{2_Vn)ExBs!npLnwGsh>XmvuA#Op#RzDp8v%Q zzx>s~7hehu48Hv9R}Q^8^xE+2hu;`^bM!Z3N8Wn-=sUmt-MjC-|N9RppMUYU|M<@@|LgDn9VQw>f#>P2fhI0z<_$wnTX?R? zDHQd6{)Z(M z`o0@S%j>u1xb+r7RQ4i~(7!A`V(}NWOV1mzXt@(TZ{O7U*Hgd$fjxK8GiA%lR(9Z>u4;+0rqnFo_5U=%j zZW4K0Z(Hq5m#s~;P;U`c(iWbYenYuB%pN*brFJy*UsQka-Y>ppd}aIWH*%J~z4P|p zU$pJyuBSfvWmAos5Sd1MZ4G_>ljd0{B?Zyj*FPn{L*vdh%he@HN?@dSgLJ6dD~P@aisGRTkC)U2CdIzE)kFX?P~+9Bnt{+lWtH37UB=7QPJPt8)|+Zx>c?5gmS) zmA}WRtNSae3ZVF!A+yt4T>%3p&4YSvD^4T-jbn(Yj z$AY}ttud=B1Q6!Xe5>di^@V~wN5Z1W^Gh@tTBjkCp4>Wox$RSYTDz%*-@D+};asoB zhksV#BmU06hzp8)bG2r*wzh>oVX=s{$B0eTka8=ezYSZg;2NiG5rQSn!4vwNPU6?5 zR{>c#VtfZ&>FyX6c@y!1ygvNLM95ZNy#!~+X=~|U@jI^?|Do#2G}dVq=csb6+D+RS zW%XTp4W3gDK_BjHY!z~{DUZ9j?iTRubTMc(TeQX9lOaOb9ZsS+%g8=oBF+h~XeW%9 zQ%V2zO*r`x>1!GzxVwVO5&2UK?ASKxbqe&1atC+e4E>#5qJ95ti@;eq%VE8nYaA3{ zZYqm=jYQ2e`Mn^o|LDxrU9WSiwu<#vr3Hz$WoQmHsvqS z(IYxVzwPCC4;~?i_I-W}Pl!Nw$2E5FL-YkFv_;x^OF3~6tca!WH(F}c8W1SYy?^J! zVK0^HSryz|oS+t@!D;BE^QDij^gQ1A;}Y zxy{E^FpSw1XaBpYyS%mc-bWsL;hDZK2Y)vINdNci`6}t9ExgT#m#*Vh2XKZ&rzcLx zxr_7TNGWl`C$MQ(J?D>7XOvU~u;~h}f7r!rPJ_fqATJ&>Oe!L5q@g%xB8v^rR4Z-GH)028iFt0*pRGGUW>?(l>I6V*<)wAgL@Fgq}(MVPsW z(^HOYq*TP25~s-}6wNCY?c-X_CD059>MnNghp>b7DL0o;Zk9AymA1mk4?VEWxF*{q zF#vTzlAhX{QRvbMWNJ4(3`_p1Q`l#;7!6gNMxEyl)&?fK&AexqdKcbOM2{GPsLpYh z>(urdk4fZv+DyJfE--=dk+!i)w@*WYZcamZwUNn+Lb))$R;7HcB)6E_+Vo~CBMU^{ zA=Wq@UafhM5Fb7cZFtCN>Cqn(EGlTMO(VSfktT7$>L3KsrB^NA5a`|@@;a)@2HT;< zj^S&Xrp{KlECpENA=k=n3kB3@*b`vQ8Euk5YKx6rqdAaC%UBpbZJ z6(-^opnVpV6Jm0!PRd?gQj#vKDTec~oU;T~RX$5DxF7!^U|BW6?@ENQ-HKn*&s5-j z(DfOFRB;xUuy3}dOQkd5)DP(`UB!zzJHBVb_xx>{I>&2-wCxgtjlB6p&uaSqw?e`? z)o13KTT}$60Ap=}4fgoloZkqi0B@(JzEVe=ty*1REg>~@MUo%(!LPo&pydyqhfh7Q z_uq$~{o|xp|Gea#&#!W=#bd9wcB#CkXT9`0QPSLcQ$6-|@j! z#!X}Sl8=Z;B0Nx2@Y>k?->kgxcSpZ}{MtRI-+l2eH zuu7AWsh^Z}!Q`AN7v)_%^=p>tGm465U3&SP(&d6qa=8)4Wd_bclN`gQv6&X?$^NMf zF-utH!FLPHjHZ{5lub1W4(bb9{JB-@<^{EzOp?c()Qi31GPk8oMZn*7gKQw*tcY0d zz6<=+;(uE%Ow>K$s|CCpo#|s;JlSoxP6EL zAq3OP)*0+pQjPcK2*GDWytZ*fQ=w+ocN5fG?_Wgfg`_;`pVZ)>^*a3nRVFZg3)};Q z1n|Ve^zn@&d4uhCSU!#hSU&t`A&1j58cS59#YlV>4WdXXDha`*4^afcQh@IiGj8qJ za2u6HIF(}!gK1Uga(2EmMAtgK$|Y2AwN<&nHp-(kb{aPxH*z7a_7TK@pot5l zl@J<5EwFUL0n2e}n>x#g@FwvxB;bRJg<1G8oa&l+7vw1tkqpc#H&9D-Omyzk`Ee^?kPeT8$r3m}3#Qc0})-VNS;a z^P4FPAU0?e`9jJ9y$+tsE(cd1y4w|g4g z9z1j}bFBL`&3v#-)q)o%fB6Qyyp`y&{EarVP4ux?EwlKW9W+E4&JFC!G1jKDxEn8| zK84DlTJCUr;MfM*j)}qyIUpKwyxgt{xALSM3?v0e3NKPmKilj^^a_WI3{Y_Ek?AkD zH$jh;Ej^-jek9=JeA<=Eg;j$aW#lWldHldlwW=907GfzHL9BqQjHpo3CH1zP&}20M zB!`GsX7uRs!(V=wKZN)U@x7%$1NcKlDpbTbnL${ux-K-At;R!(D?N?dnoem)>7r7i zjh*5`ZZ%HIW)Te4_S{z9V9N~hBVn_BH$P|t+5ojsZBXYmiqrMR<6F0HGd>ErFN41+ zK^t=_xCV8(2ceH0rq)S9epfZ{D8G@Ag5%H{dW2@D3o=*PO~t%tgS(@+)A6dGQ#%$- zV=-GQoAI@7zng={iFHZtHZT}?#!$w4T(_vZ4kOmc6`dyY79;2MyM{}Lmf&|pJ3|D+ z;y*&r0?!vde6eaj1xIQDWLY&ts8nlQCDPhES7xiBGO$jwXy$6m;U;8a?fHngfdht9 z;Hj6n;Z6HHLx3fVo2s{XoElQ&5%kWWdJYLOr!RluJb#yKlGSe|wSo@6BX_FjsoFKu zm}9P|j(PDB_~LV1AhB~4-i8U_j0pk5amcLA8Z0Xk>_e3=r&XAZ-~Ui?7t;8YOuwXd zN8nsW>UZvb@or|~C9FK^v@NzNNrdL)ZqY}RX41%Mf_U$dcMmcUHM_R}=B*i;d|F3bG@` z(aeD%$r_{Z{GKzL4gbHaH|262C-OFpl-N=ck%B@oo4ZGxoyj&AK3IO9Un%P*oN={z z7tx>M9Zc!o9wAinkZxJGbS}k}rAx|diC`uY_MV-bsGmyel)7}bovZy9j{@-;;-1tuJ+MvB_GU13%+Cb8y-8AZ? zZb?D0w3^QTOS>bKB-4PW{~G@+x2P(Hx^k3%#)rxmOWZRjYeuDdvd6mJG^p}19sa?^ z$+q@v6AO9P>0`+k&FQoi^)w9b%E`D^XNFCev|EgFdtBZeay+r37LLIVGpU0#CU1x3 zth7P}j8L{o-63R@%vj)t&n*99Li{sVV!b-^35pCLc+N~_js8lt*@|tk@=8P_?0c@d z+bS5mdbk2XXvCnK0`+l;$^E)>3D6}{bR?(9zB7vF06sb*25r7tPDeJxrhgP`9quSf zL77CtM15;*Ghmdf^AWXJx*X$LO9-xD^sf}ixlPs~j%MBj&`VRxS(XO9L48kXsEtc5+$ztaE`i+_c+|;h@#xS38wh%Fijz0@r@oKgX@{E z6ScMNLP%RnR2k$@9w|g}Z-*>S@mWlEk|oWKb%s}cs^uJ>Jh{@_VFA zmS#*a9N$sMd)S#Xn`o&@@DYKiw7H~QL&#zrd~zVBDS+_UiZnpa2Ak88YglX#!<`yb z!8ZVchIkK28~bq!oY4@HJL=b2a)%UZ+p#4P@zu(`8)hP_b&rSZZd27D8kWP;`H0OB zJVD?Qhg2%~GwGKpd1%!1$!J}WSDz-B99V@yK&=QhININ3apNsZW z$N=e=1N>}&)?jf4R$8v{O=f_<I8E>6(o+46Chio2Rt#f|`g}Rf&ZDZ62avI&u@* zs&NbCAU-*LQeoP5zm8jr<>gs9le39%HbTWJHNTFD2)`TEnhJpggZShyA9iP14r`ib zQ=ppjBalW^2IgaVuEy$n-R(KPC7hN}_;OeR5pUNYYQ zsnb%SE?$DvT`{p|6QPR?P`#Gap4>+x^gJY;4(k`g5Cw zo||c~jg0v!n$#{qU?ah?&vpd=s8?lE_0;Lur=O74{i{MfgT=~)t)8p*^6u8mP_ElU z01bOog*7zmlj@xDr#!cL6*!1k3W{f#7X;*lP#dgHb^(z|HHe5_Z#1e@q_qq?MlioJ z4>SbuAg4sfT*DbNLS7*_Cf1y4qakH{?D7|d4gb^HH>-_SN~98L*qeEk+}>e6TMJO8 zr|qPNmlJ}GUA#KrMCgmfP_RQ?yn@r4sT&^fa5{S8^I}sR~(+o53=U@wN>G&^x(7-%LYKReAOVvs)4M_;OS8{f-f2i{?U+ zmRZC#J&x5LvK=WUp_$i(3C(Mmp-q7MurL^)i&oQ0!K5+vC5VF@0s{JKRI@dBN0<0( zoa!Y26S6yU%oC8OTVx>sf}Y%me$O?X;%7TXOzOvr%m$#r!_Wtd_RR6p?2nS&fjWaG zD+ip6^sf0cZRvRD5vvO&1pc<7c9?c#Y6qc8SY?bO`*E)oV8Ai4Y(;tFHqB%t#}`a2 znPFZ~MzJ_8OaG}68L=?z*ivwN-!&DVKaL%uD>*nE>67DXUhonr>lO_8tBbW=A}q462)gu3J> zSyYIBxVHF(=28^bM3PK#dBZ&BJ@T!VXN=@^6~KCDURME3_$@7YCXXr!%9pFP8Dy5cJP{W!ylOHNeIq}m5fX>aIp#D+Wb&y(sQfn|^Tp7+UUr3pU*q?C< z19>?jWuAb-Ja*Y?=}-cagn8umSOgSoJdg~1x{xaI5m*)!I#`gDhrsE(NCi$NXdr^t zOgt7ioJhBlZ2V+>Gf4IZSu!@Mg+#5JyD5asETkkZG@vz$vWK;G*|4LYRIN>Md?;=F zluM3vA2ORAfPHUvac^&G?Ccvs+au{lK=6_-007-MUj{0p6KxxtVCcb z!A7?u_ahPXhBx%8Sa={@v=iZnd>Ys1YbC}*KFBxc7S}2H5T2tIYt+%3v~9q=X6tHm z%Z)YACKH+P%nJYo#4;V3zMCk8n`hqm%x{&v+6No2vTBv1f0hDbE0Ok*>2hW{M{@)4 zbdmcBnIG-)Z-Jhrk@VRLrS`}gupctNY&X6<+ZG$9$CQ@dN;k72KboN2lPN#7{>n&N zcIhH06j}~eT^Gjl&opIApZO*n$wT)9bSPM2d%J28^$Cz#7~VJ(GOsbWtTr!n$%IU- zU{O=|wQ?B;$X9aKvn8+Urp`M!*ZQSL%Caa3hq@j5=&w)R`lsgU5>Zg?WL~4s+9aRB zFI%K2OUdtS%ncY1 znWcKrccqtZw+ms(B1Yai)qj3(wMPMpiEq_M-zrS4)g3Yyx?C&`J_7ohoi@eUeby3U zY<2x&r^HsPO(_`qaze40m3!c!$SfVn|9;3bp)rf}c&U$FU3dG`W})%y!OQd#=zDhy zZ$C83{4I*yz9&=oj;R*&)-WUSYLfoFd->4=j4;6R&)udS) zfIG~fh*5{v;ul!8$IMJa$!>~K1dwRcW>p=xS$Qp8WCO21(O&!p62FKT8}rR43POkV z#9kUwg`6r{;8SWPh2#OPnr5A5W=&gnEzooZ>Y?&${q9Gd5EC8ETcR{}xZPAz6kH4E zv2z0$pBA(F1FA`Se*xeG2@EOps4D@1)C952L!B%SYMkaTsPOyo#V{1ea84wJljlvY zr7{=_KRj8jI)x~@+#(XNB?HAofS#W!CD7QJK{43pr5-5DLPJ^6M!I zGc_oxQO2b5R{JbIbyJ(Jt2l?~mU7v~FiLhA?t(JgT(eruz6|=V)2~)6(2o>_84m#6 z^(|I7dfI3qZk%ebU#%9J@hqD-?E<|;*n+H#Rt*>>ig&T4LZMw1~m-T25g(q^TGgG($DF0R;ege-27%VOsiJ zd&p^_2u4V#UD(%u^zp}SEQhgb55E^|iX8Is9+gS2GLeuTFbh1)HY!1ZoR9T?5$)Z2 zKM8MOSk9~Z<6R{>!*Rl8W9?-=i^YjTFVKE+M@fd+M2b+U2Hcg#kFtLIg)v3KLQ;hF zoNF5m;YVEVjvb=iS^!4}po|z4=zkEJi&~X^wWqkE+{Bxax9UJ$AuX*N!j4>|`3T<)RFlr0wg!W(rdo z2Y^~+S!&ED5KveuRL(&f;S(Qf2T_x1F3kw%Lt`L9#)8VS&YkZ+TErHWc9#~$I2|h+n{zmzA<_-tm*}&5kT!aO(k2}q-wg2oMp`xurb4z zLI9h8E^b)M)eosOQpHA&xS^%M{|K3kP#li55T^E+7DJ*ymI4`A+Ag40ss(nyG~~}l zvJk&>M3wzIrPd~~Rl-Me{3sKxZ{Z&oX$yjW3AeU|-!B$wX{jMxalPMTI@Os&`wl4f z)@#ukx&#$j1j}Hz@b|jA=#~XA`(yJhV##fNpNd{Wj&<@T9|1lXQzeb%j(2)<)yu#l z25)f3QEEh5_}luX7_aqkD!^@2$-0F{ z;8q8c1|T46AKGZ?Z$L|iuvmQ7s`po$t;Cs)mwIUlM1QTV*@w1(87IMGEYi&Kd{UMFG6;Z1(Nx$S&*7S4A&Pg69g(6)@`dCMgt2l#DP|ES}b$|nNE z!*0hR$i>}Y=mq(d8U>YZ`%2mXU}y8^6D8X zQ|z0~XaJKj#+XA6$JgGnQ_d*TR?t(nQB5~pEJJ}5D+ZygJ6)W%oV&GpOExK@e~r;y zv?6?*gTYdFFx`cJ7R@W!>hN%l)j8xLo9&0e6^$eTwrs&a!1cw|HW zkKn5Pi(G?)`t~Csbb_pgRBR{e+yJH6ArvFtE7x#CPpzZdrMe5eqiLxD7@@=e+v(Ci z9!l(Q2BtP8;AOR;+khud>vk7#f6$r2va$j^6pl zgFm8G|2wXMAJYi2rV1LGGNYtomscbzkHuO%gS#3E1`=(DDW!rJC)<#PVOUJ6z02s! z%{D9X(w9>W6m;8^C?QUThhy8_P=bZZrWP@X9+42_woCNc$_Hx9Yhh1ZZZ&c8z{m-b zDnyNDr%hGxI_n=+dFKJLgd>aKDT6lGA^%Z4pkG*ZkDFWPyVK2`K(!(JFt--^oR&}) z&qY1ZB91x`v@)oY%Lr@=Q5%7il)bJ7R^6ImMLqmH`_OU{#3}gvsJ5Zls9ilD`5u6q z0l13CJtlAYnw}iDIb$p8#Hb(06hJ#Hx~jlxrRc7x638(iCsyL446-i z(U`*ReWzJxu=LC!=F?j9D7E5lPvfvjy+C8kMOw23sB9=$L(Qji7%m>dS*bGK=h|yU zx&JnJKhRC7wPRH)emEEVe5mtP)u(vcTTGZ$8%PfozFvYBs!l0yhp9sZdrX^ zMJQFe8P!qyER8G^ZJlZZDsdFG}Ln zN%4R>-BiiApwago<#fYJA%N0OJDU~k?WUR_At41^M9M^tU+f;OJ7WJh(!lY4Do1$r zWEz1ZM3SXC3O4469x0deyB7Yy(XvS;?C6;baz&~WxW7i~Q0Rh)C@?^z7gzzSZde>C zj{djT9OI}rKOCS6Fj;w+%Qh4StcyOqBq;S1qy^xN%9+=fno>O^+Q4y|3dDE4d{aC1yYPAAyOHZj$p{OgQ0`;~KR8$E%4zn|F8l<{YBdnZ^gZEB8WW7&b~ei*1AnV{;LfsU>Obw> zTD-&$Xd;?MXJ$K6$i+D)$~No6lwg1X+H)Y)X1^+9$eStNNipQrxn(#%K!WW31QBsQM00onPkyijVXKem;7cd;S$C7WioGba_g9igu$ho7zP_Yho ze*^DwOTc#q+PS zm<&;O{vMTs*C9y(M4`0^-tST!+ORW>GQfhll3mn(t9p7Aj|ocHR8+ zXzMnfvlnU2AwBAloQ7AO2%R#B7x7a-)718B;vLo2S9#E%GHq=LRnx`Y`d|C})l>pc z({>fNla}6~^@VDO;oL1My{;H>l0~y{JFg;3oL(jy9XTlVZX=p-9zH!nOR!i;KFqsd z?x7VM&~wV5Jt>5_Ien^pIO+h~ywE*rTH0kpRae|B01vufbMP|1ML;JK zXGFD?VwGK4sSE@IPv%u{K6KhIXz21OaNrPH$+$;UMgVod>Ff-cgWKkw(4pI*wdzxWnG!@n9D6FXybx(72R!fs(mtAxB)4fZk2I+vL>DL z-}NSD&!x70%W=+PWiGo`1;5>T6943U`iiQ&!R@|K4K0@exG=_!q_fh!YYdnMuy0gz zghG6FY-`S8$5P$^?X!-esv}yB9BrbEKif>5Dg!Wxqjll+eS|gTpwg-t$N+27C;~v)86YPOIi$APD&1{d#X9eWl!g^rr-XI~?UI50VLMkWQQI(^9 z4Dgy?Yg2Y>{0 zpa6k9FrjfoztHlj6Z~w2}@L;CgcqWUd1Vr#91W9ag#qRJ4$lH32haT~o>{ zVruD5P(=_{wiw&4Dp|>rX5TGbcNOCfRO_I7e~^|JQa#!z@;G=6Ln+ckd#RRjn!V>N;lB=`MWuT`!y{a zlrOH-zafKo2{0|{nOLAt1D>LcCNZvM7fw&2^Den{EMWn3wH>n-OomPPDi^jK=GD6? zw^J7cxWo`|>dnz%=@imxv-CKM(CZ6!rQP-F4t?+|{fYR=ALpg@>jsdA%fW&}= zM$LaKU_cmlesC$ef0#1D-0x$mpWDP#`DJ4dr3URb!CNWH-$x zWE#5(SqmR(vU|HtTUN9n)0ad4O4Y|BQq$Hl?$!~8h;GcLNyo`XRXi*gK2KbZ_IhD^ z>&%To{)8W_B7tt_Y#58tjkl!NjXCZ|aQH=K3~O5!H7Mp!m#3t2fc5YFrJluo8d3i4;uF3|LeYP1y>;+%cA;b{`PgY>yb+ zH7sSv`%b^V`3?Y#aC93+92L9BHXi(G#6&415}9aVzY>$$Y5%F6sY?2Gcuaa?R$iiX z1{qUX`u`EcwgcT=ZCKC9Y)yy)Yh(kKTs;$YcYxx)3c5A`cYfC(zB@0h`Nulm&O21F2J$qfH=aRc;5?FMgf z2fP{c+A8%TN@@-ptrdcQ4hco*ORO}RxmF66wARdY9$%^7$-5zOxo$3KtZ`G1(e3M& zmpLG4^MixbAl7qMzkkR_a?L&Sn+|J-!?TH#eVYCUgGGdOXgc0*@}VdZxmNVa!Q8f5 z?YuR{a2#eHq;k~JF$cGIW7dS&1w<<+#1I7}`u%OL8OBX)SOuaF^A>I3aHk2Q*LqM~ zrEL~{I@bKxOYx}vrVCB#e4z`Q*ic|T(TVo|xc<57I+y=L+1c<8wy< zxG-3m?PtJ;Leq6vV+_7^ImM7AwvYl@*o@eJMrY?4-C+uccEaE*d9cP^$1Iqz289{J z;FF|rACcx-S1J$V{}qfCHKH-KVCS=#aAYz`nhL$I3ab6XtNG_ICj3vv8~?YFCY-L@ z_n!;J{y!m2IAPf3|4x+p{~l?=u@jii6Ei>eYKYw$MEz8Au*8qr@;Eb@I0O|K`*U4< z$m#9$!O=98a%!(&uXZZ>J=r7=I+pfZE)=p6RA%KEv_gjFhuZXmLFeN&Kc#LQZqU!-}H;mJR=u0HJCD=v(foHR>9SfH9@0Hs>+j7ruor`0m7D#f<4oouyMJoe&=$FtrXk}x>1Be=EX}GO4o(uSOG?kESRB!Zt$^Xb|{`rduOYF;1Y(KYuk}Z85V^<*($Ok_|3q zx_l|knx$s0@OxKK?!tH^nplsdbrR=kGB!74IEqp~NqW$uHNh3xDOq|&sYpG=r@s02%HL=j~tr+8SNpN#<>F#|Xx_gZ-&*{Yg(fN2}+l((xf$22HTJoqVYCo@$pVh-@3qH+@yviqyLf$d^oX>C!&JCGT#oO zJ{GH-<#Sb2KLh_{%9183BG5w;v;BXU=P#=7bko|`ljTA)Kc>~|c46iM@n)BApr@x& zhZRkdv|!~brRBTa8uY>$T;ucz&3g3`Ap?!7-cFTw8imDDRM#jPO%jNAA1uu-t!Xz9 z72yd1?`SyNP^r~MYumoU1Mbm9AKD#o02Bx+D`;x#^@Vd=jkQ&++DLz0 z(whq2ks1GB`A2q5Gy6VJIt(4~c!NgUkkD(bjB2^$dOb=7y%lRfm#PNo2%SoQ7y6ffsUT13?D3C|Glvfa>8vx=Pjyezy4GC z=4GQ4M|GVi$MifkJAQr^si^5^wzP>x*DC&0dTpA zfGptAW-YO2b^;(SlSDnKq=)HLC|T5vukqLEv?qP&{_Qf>9K*o>HMg|W-e9A?2T5Q2 zBw)gZeS|y!T^v&zmQHl)pD*#*VKRp8u9;{qE;I_X(VJ+Az@dLRgpy75B(w;hmmc4V z;$o*%HJd5seO#Wq2TaJA(N1GWRK5})ZSQuX+(Bn$?cHgE3Tp9D|Fx<`TN@mx+HZth z;(=(H2qZLH6K^r7=|rL_RTH!VTuDb+a#(1}&}Czz*zG^myq)ko+NynF#~cHPgYe~T zK$4!$xl#KFx~J*6fS&XxZvn`PdG8b8v$h?N8ZmFU>ms!RE6EpL#Im`jzD`lKks@ zY56~5j1fs!Ot^XIoiB2jBim;QzmMm?b62W<_UJ`WRz}bD70-h_KRxq;^<2lRcnlW# z1-a*<=$Dy{q94cu zDUtDmJalcZq4lo5RBWUi!@e#iB#SH1F29xauBYHTpY0!xyk)kn)!Y0d9B z>V;;?MnjZ&@5#MU-5192I+a%U zt~%GYe<^MI6+y({YdS^!Tnga1gfEm#N?MW-R&Kev_|3bfNE~-0JG-uN=D)kxzlevJzH zM;Hp`Sc5_47>5+qo9A*KnR8M;UA%XwtF1Oy(&u3olHV;AL8nHNFTsLy+O+OqahFCz z>r0-1iGO=u1O6L~SES+4bc z^a~w(V;C~o)*O=Iys2|NT5>QJg#Paw`bClb-?eo0A7x)S5+gB51J-(lNYQnzk`+Sy ztsdd%6(q9wmw$+c9JZ5&j&u1uMUvv%cnG~pbEVA~)0?fEWaMzXAaJx!+WqTM#gX*Z zknbrVghM%%j=id+n~Ch@GYO}H@r>@JFzLaBBUeU!^b5%V(_0@_pS}IPXX*cTNakr` zJ2bnb=Am)f25&qnhzFmOzjH3-FPq`=^?8FINN;)Xn&@!a*y)!Mtb2}R!~XDOJ-7J| z={r9@hl}%^vhux_|8r1Y8MFBD20t8oiQ;!4(#5jsexc>*FBl2ldv;xVVz0M(P{%20 zm3R2hKajrlb!D5$uN3^7F{4<)5Z;S?>DiPO^6VzYi~p@V(y0~mrE|znb_E+{PNDl4 zTD&JgJ}LA6?>7e`z(JJi?=4J!Qg@&POr8OLB)Y42zi^WAq(aG=-=h zgzuE@z;C}O@??2fc^+C+Wg7xZQfLdOC>3Y+?YaojpObApW-ZBD8@l_6vq&09qksiIK^?|}rHELbjq~$y!$xYy@pdUhJy_O0 zc}YO!+pZ=mpVuViK_)&bbrB-P50*+V`VkT{#NLe3W&ma^0y!HtB2c?DP6&QzN_RAu zNJq1{$yh?nqwGO+%wt3U-8uwh7sk87%mqw^QamWr%A!RJlf~NVLA9+kcx4@;$8X0w zYdz_B?Yq&`Wl~=2NNp>_xQW=6p3RS37WsQZeJ3UD-y`z(3mLO(iuxQ-4rvwg?H5dx zPrGS8=(&RPF9Et8S9_vOhd_N@_FjJM<{lf|=)`Pe43$!~0LzZ1d%77ig)Y?laq|ux zvNNC$TS7FZP!f~5>5l#b=?vCmr1Q#qj1(LNDDDcXB~V;XYq4dh-RKU|p;-$WtCWUT zT5Xcn${dv+{<5)b3g?t&S_@7#&^%@yGX$CTnvaPq_Ld!wEv))=TKlzkZMBk!CLsyuh#Y)P=#g&9G9AE|}kj=JeJxUudy>R-b7@aXuWk|D{f0|V~YF|yk zeF&Hj*QxgUkX>r5CJ_xrAKy8ByRXpvfObnvoXac2o)f$A8Fop>x*{aLz1`oU*APJJ zPMRU@ag}rlO>MPRGIz=}@4SEXUYbf$iiu)I5l>7^y%(VK-_T~9rSEYb&to7uR-WTg z`8FaMkiqGYF_!bVI?E7kj~$u(aY3xslJ7l8exv7&l5o6(%*-S9DM$@lR2!TDS0Nce zjwVQEN0WbfqQK@GT+kbP#o86=ByXuKc^~cA^rC(H1m^2}bkq@B1-&Wh2`cf=X4#+| z`sl>>jUeu|v-p$FK!2{VfGLLoJ=ts^U9PHi;psYSJ@VuX+w)|1vE6(I{Oow0%; z-M*K?{nAA^`+Ye%7H0|JKBU#MEJ{b_$er13-wo#eh*S*bg?KYgfHuv9g@GWwlc6+L z3L=3i4bTpxd;E>k<1Kma^GwfYzD4ARi%xI_M<+jyob(T3(y6b?8$;Tuu=U45TUJGOOsPu`=R zy!g5PN>Nvwe+mYm=5-%n z+zaE~s5J_nkPJI|iuLqelTUBOWH)XqaDTk_u(u&UweM2@!ow1DGKpn9kd;t8m3UVh zG0K!wcAfS=@ z#1&gZJxdY3EALlMQ_{6*oXT5b!k-@~VD1Nw1SUvr9vTf17W~zh3grCPkpw0%=Z0ha znP?{?&D$=Il6Ox8>facDhHF!+_Hk28C^%J-m4_0}Fpc;4U~H&N6cT=8%Kac{yoPFFTJ;T&&@U0g)!&*sG|q{@^FSeF|kOkewT zRNx)r>xWNMh%jX?94R)iJhC|^q-A#WnoaYO9lqB2twzk+A9 zk+mhdlh1H58tH=jBF7-je~PAFt0I4qm-N|!6;iQOUhMWbx}KAIxbSkcn?Q?a+UQCe zdva1KxQE$FrTj0z394aeN?IB*htiSycn)9dpuB(5l5pnH`zTpN5wY*oyl(2`3*|?mhj8SM*pM$vdpdhRTqshM8qAMLX$j3KJg?DP)Z94 zj8e8t9yRyfSlMVXQ^dyy!sHZ4yZtP2W0zw;iD%QWhhBkl=EV)~$8xE0u1(MoIv8p| zKFc=~C~j&3{!yEtilUlhcC0{ekgf?Dkb14}P5hD>pG_2o$R4kWvF71{r<>FmBLkXv zWdtj6JG)#e%$!Y-OhpVnir#ku$MbLOqok`%Wt=UUp(6=iNyuCgO=!u<&XgKrW-PgDnEX^wSPzoC^JMoC4ae*!_2-2~jzn`s0)y zY&{g5FnHC^nxfEhBX%{mQs44#}($u3tKVH{MW=TnQ8+X7rA@J^m)*HBDfR_mm@_ z5c`iPYnMbZf)N-eutwy_BiDz?O0H93Yc_-bY91r|WSM_4L1~|iKfM@feNkRUSW*c$ za~V9lk^;$^6?E`eynMyeE`~jR7QfG{m4>|1X526ydt_kC2(=QOlNE7Pog)T186I)b zxS@$&%oZ!?--tWJn1#%VUkE0&DW{8g7A&#d`6 z9ixMt-LRRc$+sqJ7HXMB;HJ{SFpts)S(1;cO>j%M=B-sJ-Ux#4AN5Wdvi2kNw*J(J$V^_#n+2?@aN=Yrpar z!-^Zq)|#lY=Cj)Y*e2Ujywd!Se(`TiAEtRDyYVSW4f}8Z(JwyFzG#RGI>Qm|C!th{ zq99S=`>PqqF)JY?lHKm7m{d?SeIiSK(JbZglJ{5tlF8)G1Z(p~jCloB2WYevGV zsETCeC96^#N;%u(2C3->oJ`-3dK#u_&NM*{r>)IQZY4`|em9^I;bT@6pd^^&g#?uolHll;GAt{2p6*j5Cfbbw#-W)hBLaonrH5meIbl8EGy7ej8`Z=kRDp6ea^R!D<%5F@; zv{|{d5c0B~4=|!&wX>45<%?2Cer5b(sRMU&Fpi*EC3ZF&0;}tdKi=80dbyjeE__?V z^FQj?aQ3bn(FAl+#;*87`)&}Io>iWdJG!M&QCazsC#PWYZ%X^dgZD%pjMRIq7W?k# z|LDPYcPK3VWk>wX^69VPf-)R9Cb~rjPhTNZY1F$J0HkD$v!7p`EfuKjTDr zI&Qn4&cMuZ>bCP-3En(w=}AmI_h-%k*Y3>D4fK1RG>^UwoG>J@l+oyCss@*fp?I17 z0mFs0&PRcvwXsVr8}qNt#+8?ADeHC&<9Y`51yz)cJ8^Z_kRM}~*dAdDjwbp9VOeRP zl_O=|j$19E-La2-7CS~vpQswP2=w-P#Df^H&(xxYi+L!O;R2m1h2Vsd^_mfeJLB6K2^ zI>+t2#iz=mN*4Fvu#d3*A8#(ME+@W?r#k&c&WefWl^VM3OuZ#oMhZ@cFbEa%(iegr z7@V<5`mpO%r;34uH&4Rlq}90i5`V?0){#7*z$3WJcaz$CstuNDz-j3$3weSlP{BiS zU1#h=>jngicCD^J*UV!s2bF!)D5lc=@}!J)p$i#HkGb5QRnsuX6*ODQ4U9T)xhGXn zl6rpk!JoPi`m4-h?GMow52EkJc+_IERdhbSfYD<`J_fFb0Wg3dBYIzVTZ>eaRVt}_ zXi$~CaU>6eXz2%Y%vA_mvrX=f9NZ9qcUEF2{JhD=+G%*_TOuELEaU_kDNI0hN{X2j z8Is^!sd<(y^UiEj;IZ5RMw&{ut!)^$J>k(xfc~LmWp(;jjb2#t7FFx~2H$dU7z6`% zWARINP6*ow!{U3|b9U)>2DvNW~Qo1s2i!?*-soSdybP=xI*wnSCf1v6gzl30VBNzWXf$ zXRIycPAsvAbH=sO;dQP^1A@JbY`&4 z)mEZ5_9!Kgd`56@llH&;RdP}n%ZIe`VcygC4AuoH$aS|jR=Q^8r;YMFakR7f!aDR1EZ+OqzErxl=I^a zvfN|*t-XI3>%f5I3QqNgW1RX@ipbPE*aM59#T-~~KBJzalC$tt(70f!3@i%_oy|C> zGMr_sMSUNw>tRngjr+k+O8S<3Y)ze1X;!5XCHLf-uqoO?HEkK>v1kl%I?9m2Y%vu{U zI@{KUK1{rGCR-(if3Rq;#FMmyjqRyg`7YZMJCXyf{NVn(28D6Vt$=K=8__fJ?1NQW zP@J(L6jq{+{%hojSb<5EY@}R+d(?L+ThdfJmbn`je(0Hm_e`&mmV^Lg9DBkhBr@-0 zug{$vuxTIYC^dV0WN@jASH{^}sr|Bo@Q>@i7>(ySv=AR+xzI_bz3>)GPwu|tr* z#&*|sAzXvEYjGz1dznM!kWRK&It1!@-<4c@eoIcq&y}_3a@3<%75AFfdV?z-0Vf`i z4i#s7uSCIEBKO@T$9pns$51*>C_#AXYZCWdZNWX_ef^IY-YVe!Kb#rvSgy^+;&T}Z zn66JTlIF)!?%^HXw^g_t-WOsV1(hI$AhB%Qup9U6$Z^_NBkvwu ziU|#|YRXz%^pnR9;W}?{6J#fb!aGw?SgxD-x=dl{0wXB=mUb%6EPQM98Sg&$Su7_= zE3b1+vuMk#jAdk=W;>J#3W5lc=&X!q4-!WwM8L2B_ z(O@#Ak03Z--~bZcYuY^ek$^IzEfS2@#mh0GwUsr`n27+K&A?tm8)@hFq9 zhry_~bj9fdX^S%R#A{|*d9#D*Ri?yd;Q^DnC=cN~1<;?eHD=8^$)SsPBq;2xVo;#i zMO+nr^>VTjem8t^I?z2OomX&{f-1==+-VO}mp=FWIa>V~!jAwNIdJt{C*wRE6+F;d z$$&9uWES-)VzYKK;__U=vL!dOq5mByPZ}vOM?==j32M2qgLex}an>UvhVRoUyBWBl z3wHaO#Y;I0y|I#!M)tHSi^GyFV8kXV^oKHPLuL<%F!g;_<*&Vz2G*}Ru!%_*PRS?5Ig(9?A#)u46Rfwa z8yVkGi%Wrkj4f}$g~a?T#?t!`c2O6ymg$DNiasdx844s6kF&q1)HKL0A9b-I8E3ft zEz6$}>4k1gS|kU2qFvlKpZVT#Y^^Xn<#(hLO4+&ZmiS-xP1w4s;HXlE@Gk92NmomJ zRx%*afLfAtiRwF3P+h4oRFoiQQqp@GbDLLIJbsrO1cAMk4lk+8)Qa;>aFouI)uEtA zHc$fR)`ICHa!p-jxbg68DTgujy=qW_Bg63pL9-nh^s~rnB$Db!Oc~SZHiK` zja()?hx>)}>3MLXOyKjMi#7X=12t8y=^~Go4O!7bUKhjviFnnLz+!W|FhCA07x{zi zZcD-m;JSsy2r}15vM(LzR0PWpz|+3YZNp#daTQYo6ZU#QE;OK%gN_CovYio=Ysrh` z1h&rdO-Vr(I}yq(%hwoJY!TPe+PC@1CGhmFp%rhx-tKLflp$L^jeB zkqoO8{6wtNuCVlkSd9g9M~k+7>M+WGvO

}mxb3J0NbmSCsIBR>?@186|Vy8tJbMTiUZbd6ACAsaf30$jb!G~^~X4boJz z&u`A#bTzmpWJ55A?^o9qK|$xax#rpj)W&YC4^Nl=O11PZNe#~hv;lgtXnY7)S8vkc zI!kNNHA4i9rFMYOh?hI{l68f5O%-bYMQcC+{nlw%s#)5J6j!(DbPkFy(r9#S9)7CA zH&l6cgMMv|-s0uJlh}`Gm&(}MT)o9G4cs-7gTG6*}+KL^F`J`K&K(-%xgP)P+Gd5vuiT^Z?1l&wK_V)P z)jOww^~z|p)Har4ic;i&p1BI=53FLug%z;{0{<$}7{iT)cqzR?i`qk|w3Bw&^cf|X zC~AbzK5&>2-)exn!)tWfS};#fH)cid#2N-3D^51KBBPOilCws`BonU_W>d9CtHR)BzoNvX@-D z*yXIMfI;H1?v^TTCJ7TPrB8M3V%5_RyV=_B!rfCwR0$XNvOj%JgW4&%*tr$bu$#jD zf)2NI?c}IbqLCClN}S6;M9HGhO0Jrpk=d+tZD+QXT?~JqaDiLM%)>)Ut@c{i{UIK` z-Qe+^r-M$kN6NJXm(NDJ0Q*umvfJe)ukua%RFizYW%-%gb8w&hCR_qvUAN9*<=bZa z4(qk_v2P0qS{@rjz)An~H1L_?iE9hfy5Y#;7`YPNC@G=cf6+UN&5S#XKgx41=1)vX zK0fQc7nI(gVMM6K= z!}6QIo|e`hCEfCOlowZwu*>XcKib7y{pg3!x>zY#tTS=7j47ET&4+P?SxT|r#hXSP z;d)H^%gbOF3dDT+0s}>L=%H|3JW0vOSWPKTVJd@!-BPRd_Oxqo0(LUR7USl&(Y zGf_moGkIG23RZ-6+vSIn?@Af7))YO$3tA#|P2Z7ocw5sl+D2XSXUmn=Db8J?*zA~R z$JW0p%~^5B9+_A#RRn$V%5}+)L#fP7ejKcXj#hC^)WB2$|Enw^$$3i=&HB8gNBwsx z$?;%gENeyT&m%`&8f8Uv1}I`5J|jmw<4KPra@5K5;Lj-xoV@r!S@?MJh0EEQ2TNnB zmSXPGQ3!r-a)K*0*+!)@A-=3yF+6*da>|WL(_%O|8%Fk>JdOFI^V@fQ^3t=D@`0UW z-@B6U+ab&SIrjZj@_j3|t>T>hQZ^{s0{l(@bxMU#orIXk-vA5x}}RgT)Mk(GT=@ewciv_IclXt~FuRK@Jh znr3G{)!1#H2x0%$D_2jWAb4NtwQx9(D(FQ*Ja9#1=eNqEG4alPdc!OI>QM?y|CRof zgG75Df&@5fZyf$A3c8FbFbHS1Y&ho+<)h`y?BroUUfj5~c)wah~; zsFCiwU%`M95>jtOsE7~A!`Je4z3_JFSNjm)vg(b7ospmVFKXK89wsx{Vpy<(G=%Iw zh7W|W;O`;=Y-sh!Q2zPD-TDZ}xiZ*ST@+7p5*ysQJz=WcZHOJ-o^l`5g)sd^Urs#ZHNH zrCT_9RINe8UCFS6^?g$kx(t*F_ez7#{1~?Qx=V*sVO~)$BMQAIRw9o+%#P~Eym8Mc zCB(zjslO{9NA+^u>(9&_Qhui`5_y{$VLIc}O72kI^dd*NKUhg5KMC%rSooBMWtDthtZVVc)MCONj}I7X$)`H5HV)!|cYl4|%!*`-Z# z>B)C#d^eZ&u>TAp3~vpyqvzuJvTL-(7Q$)||$I;D=WI(PKo7qwi5T$D1^%9rE)RXJ|q zm92F}w;~S>9WfK>!h-dE>#j4cb#p!K2+Qx>#=G|;EC(($B7v_B8BL=7$^P6D27k+; z#`k0&Ae_+Sq>Sg-6T{4}cS%YACw5L3H=aG1Q^u~|hI4l$$Bnpe-g2(@=*&q*mNdcG z7WL1-$#Y#cksj-?$?d!lmn{R%0~GcQ<$lr}e6s(-M;I$fTKKc%9=p;g9X&02SW;%Z z@0y2we?0gj_Y5EtG1XmLIu zOr`o|%8pJs=XkdK-q(G9?$76wkW{zx&-Zs;J6q|)o%`W>zTVe$9e_VVZ?f683Cl=X zE)JM$Sz>W{@eIv7X4UQoo)Q|avW%y2ArGr=?2)!I$;-m2JU;&E7*{i7e1_je?c$&a9sDa;Vop$_wt!04}#oE zb_goW3IB@;POj^dEnl4nixO zWA74GznnK_n&})n(>x$-p7#S0hS4;XTKn&{X)?xSGUZ8TrarpLLFs!ROCRa2Z0Qi+Bi^F1y{VV@=S3 z&%s9_U`%vw(aoYDpuQD}P@~epSmS$Y4E{S}-zUnolKeo-7{JZu65K1doqhH7JHRP1 z);;}*&42g`KR-UXoWs^jr7#wjRTGK_G5+Hq)B3R2NRic9QZqD#&nYudrpCGUs57dm zbf1VQ0RwHP5c#c?_PYW>HvZLH^N`VCg@~7$Y@x$fSXPdbx&j*_-n02!^eoBpn@(a$ z0tc3*0`>;t-D|V5P_H?Ql0wb0c$59K`1+UqvLdffQ>`mB@S-eX-=t0X8*nY#iBD3G z>miPPGm!s);F$o_#M3Z4dT0pWas28+c29Ssl_*t~Ou*KUBH|9E zTK|a6&SLvrKlG*h^Pcwug@{Z> zWd+L!kk!17*X5)l=zVYsSaONwT*V~vW-9T5y;Vq9j}ludNz8AeEK}K1l(p>V8f)IV zYKE+B??a9P$*yTnc7TJpx)=^(!TrNZC8WZqNKfoy&oLf9kdT<_#XelNW_)jm{a9

c0)to@d<|m zOhOig=Tm0PmZkXJb$(AKa1-7I7-|I!?X)L>9^EK-t)KJSW&OXl3rqfT0WfFXMa(v4 z9AAsX-*HyWbf3`Sy?C>?;nR@PsKj?qab{a9YN;Nw*^G6td(itL!yjZMRt+hxqxOen z!6gpg+{Q5@<9e>UTy=c*3XlK{f4Ty)m$|yID42MB2qv8aM}|%zq1=ot+Zeim&fD>W zAQMZMHrq@)B2j>}km4EY4>Hw<9p(J5c61geWTewcU(v%Y7nRagc&;Dj@kexgG=*9bedhDHqV3)eX#Uxsb|-Ss`@L9h$Ig`9I_^>I%k4zt=h*6iyL!yLdjmecld zwO!{1r&2z(H;R`c!vfremm+tn;(0h<^Kbzx6QZZL%MfB|W^Og2gXn23gN z-zt~T!F<6O9=BXXKKUldLeg&>tOP!ncjAE*H345>XG`FWb3#^6WY}j(2MqIFJERI)BL9$`9ya3=tUM+_NMV>+(HTa_hFOE zut{e+%xtYHqDRK6Q}8?stlL^M^prXU4j8tr*eFl}-$E&RnNt2MA*G;GFyjZ<3KgIf zNH?z9gt>eCk+3eY%3wLm1=AS z*TAtBu&pB4ijF%B*b1YDb>r#Xu$6Ka7hzxuM1fIb+#k^Ald;LQwwhI>6kjH_exB@#o>&9C*c%KW{ShMVz#a#!kf+;FF$-iNx&} z;mFFKyidZg1Q5g{bxZVc1}^@kIgc^eQm?R2hdpG|cRP+a)0udSp^-}BXJO4GPW{{^ z;x`{8ux5re4%Ppm_$eZ5xRu!T&m*$xe3jv3eO*gqV z!J2-;QXpH&(`T8?3vOq|&Oy8;DJVevoked}-AeyALAWTazl)L&yG!&6N_Z&`+iXYw zGc?1*{QleEsSs5>*^w7Um;_GcaS9D>wdu)ayHyJN`R}bc5XGNK1q>otc-Xm!whO`N zL>clE^nbgBH4q!uds+mgS7_pTMO>^OzgM5%r!NlB=l2&kG*|Tp-GqO8>kNP|OgZle z+fH;23j#z+m(`0{ETVBwY(;<=P9}8pN?7Da?Ep=;!K-2gJo~mo9X-<4$M*DuxQDnj zt588&9%A7lQYBX)NLPHM@)(QD^+MI1+f>!&YOqFWXY&A5W;OxJxQ-!^gQzw+$3YZW zwc8KdsI6JmOj85mU4kfbFHZ4E5Na5B36FmtxEo=x>q1-f&5eR@II^#+A%qBSf|ZG)6ZJ&%^)3 zKk=;Xp`!tU-%MM8LvANv()ILy>Q@N)r*jU#s9^8somUo>gW6I6u}aKO~i)!579G&{mkx{lsuiy)%bU7X-E54G!k zHDnK_uMa-eAsI8tvs$*oat>QvXfroB=@jLl!YgG(k~rd{(iE+w36jnAkCKfIVYW>K ziDM6PyM)5TE|SXI>}pz+wpue0eqvh`xwA)&scV7r8!#TF*&XViwA-ukkCeGcY_BkH zy$!KSIUxIwZtrINb9F{Ktp;np=H(%2KHyn2a!!>OO+J*0ygKf2lkm z@4qAb^2?&T{f3|OoRfIp4-Nb2Jt{MKY9%KzE4(js#AOGV=4&!ALz>TYi#Gkqx=scHDLMvo>*){Mn+ykQzls6gp-2I8s2O^3ZD|4ck;d@?4d~OlU z`<8Pjfn5j%`v1(i#j&Fo#Cz{bd~Ok;|CVznhS|LT9nYN@W%C=sg9E>J5|mAQ44o$< z^XM!8yL0bNNauHnZ0WbWcVbl4>F;*#B&e#6?{sbfV~eV$1lL5=UYLa2x4id`gy&YW z#NTr6#K6H}0%KDwobM}((98tJ4B23^0xXY|X!Yx|lgu{UPjk}uCo=FC-EsM{84D47 z?`2S&=-?auVT1k;)0m2wINaWyUq=_vcc9c?oXUf6E&av6$M^P_hr@m2-|G#d-%6Lf zv7?_xY;ppMn!2#gD-HiERJ^NtIu9}A-pvo|D1M&nH^)5uR3=kv)Qtg&O&`#n&|}XJNDXo z+f(+k_yrr9GC3+2r^G>=e(9^p752>a)l5mvxi zC^K5t-Z5vp0nO%6HHI``xObP{O2$3{){*lqm?C!#^9wun0$0H?>~|+N_uo!y*0Lz1aiVam$XbstRpdqH|EUwn7n}aMoofEe8U_QNh7q{65nHSzZeLnXQ66>%h zg}In5qa_OR(aNNQ2GpD;~<4t+5{22e=0%619gQgR zPrlymJ=!S&e@K;Ai0V@*C*BGYE82_RXb)6cs*&|3dGpTX=_bQ%8_;QkY<%R`sOS!) zy0LQ7d?eZE(%zYb=-Hiv!LPV~^AL6kz=Uih$&x_k_Z{Ku@4G>5PHSH@{&OBuwbm%F?WUTl1OB^l1h>IYLCN7tR!)78Cl*j$ z3wclp0wy-&yVND#bt4f?QLZAgXH`1om+oP?y95H-sB?lK$n!o3l{JNGc$8OiTXQVtGOPJRlYc54a9re+B ziyfS7M$jNI6g}VwiYd%wfqqDy91`)AQDyP(Id*^XC0;RIb(kd;k+}i^Y@6eedl1aQ z>(It)LzHG}2CIUyDaD5GK>@r40cKyt0E77^7U=On04N~>rP|^fS={$uMdJRDg<_vI zUT_SRURRA~%<{A+unP)m6l;Yw?Ma@%$6GUuPj#e#Dr##8>Ec?K6%9i4@z(_dEHj+pzrt??yiF;uf60CFSb_wek zm?pzwiN(`xoeDC4Dc7EiUcj5HLGS@WR26?{SKwX!5Z%s`Ml;n^xhHF7=# zO*Mp=lDH8+0AAwzv!Xx#?Ub^Lw{K!x4LDMeEPva)(lX(}d ztuiHnXei|UR+*fiMNV!l4hS{33->`nBt697RRBG*WsK~?CnXlR*NUkHT;NKuM=2m* zf);4>d@@`Bop18O5-HvLm`=|H^q-`u&yqfr;TJ#q z5?0l};(GL)Dr=BJMxp*TIn}L`)9h$9XZmCwRV^^s4+sHGx6lWY8S1!HvK`t{<6lCQ zBr#Z$j=C`cy-JgPX79F{_`Z>mCOcBzxfmBLQ@K+AcvbAyH$cF_B%(HaB)F7*GCM}` zJEsPJOrmv>hy_NK=`)!O$^jescplP<$Cy!oV`A&D<>>V~F5h|!%!nJY$NT(2$_ll( zSxYI9xf53aGhhiPbGvp3mrCXj%3kju2~TjydJQ)ZVw+w7Ui7hanw}x7cXJ-CJcL57oy20f6~1 zqbY~kV#wy^f<(%oT5VP0xYRiGCOK|ptr`>;EI4`w)O31^7WvViJ5`b!Y`c0uHYFnX3^&2rxDg*Tbv&2}`Bj)?hIxg)?L-ss~j zC<;sit79d}!I+Kbrm_G-hab@e=m;utS5bCoN5Oj!bpu?gBLa)ch zQ^m%gMSc>W%UhvAL=)bRclS_qi;Td#m3l-V!fjZiQYCG@0?I^?7B zRe*49v005UXZ2Y~GHxIa-VaFxk}F_c3@RPO%a=9K$Pr?anRdf~hDQIOnj1I-5j`&m zM*Z0!v7h1MvklLdA2E@?xLS zx7l_K-^(;g(xyx*T9QxF%;fhfrLRJ4{~J+l-NIP%B@`Ud>(@+Roh!B}SACkfPQ4cH z`;e;s7+5(-Xjn2evhJHRniEY&E9g1xSa25gi6Wxz4O$%&+(g;&e^EQlbpE)Z(TcJQ zIEDKVq^RR}kx5z~jSuOdmj!Zn$H>3Iur27qU~w>EAj%2u8DwT29h$E)hY7wV#KKfh zlrK$oAKUmbYR!a8rgL)nj2O>!f1spPhT%dy{hC8U$QuwAq9Ss1uoWrN_0DwJ zq}qYrsYSGXI0y8Ds%8G-HSoOxGXXIO^9W`47NW=f6C!z;Bo05 z#yy=E-dZT-u(jFefvK5;va%PuW=88AVU%Ad8`rf^iKKqsqDHF(y@YvA*5VvMl@`8d zh9MY(HUyjV`_v^S1kvDtE5gBi?9dh1Ah^jQv-Pl3cK;vdhQQTi977jJK@H>`5V&Kk zY)lAV`}$8H3sw|!2}UhRtK}eWvRwOQ?(Fz79J%&-_Gk5s3CgP&)h}WiJ4suzbs{3b zoPcXL$S4>vIH^||G_vkL#<*Hr@?nPf>4V`FMkbl91r$AjSC1}qb1Vu>u^lp$)Ylwb zXysONva8@Iws9|zO@~}!(Y+5j4_^&pi$z1bnUKlMixOug22JM6F6`43@cAr+kU8n2 z?O;i6_%k^Aka#T=ACIWEg0kDP&K$6pm!cl`4rJ55)D;V zGShyI*54)_f9c7<+_B2YIqMKKA$9^KlImKv$P5x7@x`mj@+UCbMYnX{g_{fyMm7QN}KlWP$lLm5egOWun;kend|R05=z~ zGK}Sr((L3HRK=8nk^F+{V_g4uV&NpRtS>OsuNAJrTAZr~2L3*3h0NIEEw)=HBu+n~ zk!AVl(FHkw3xdy&twu2v@l<;bLi?Y0UTX$qk%`K6V0mUH&O>pC?l#B^R-ufT#QUS? zLoQ$eUhr56_QC7^&M05qs=stYA zzlkPlo`N^uwkpf9kV*~qW6!fk2SE)iU5Cn}aQ(&Ax|2@CFxeAA19J#BL3AnX&;=h0 z(`lqKW^ke}Hz_M9CejxBksPX!Czr@btGLA3T-gO>r7Ts(G#=aqkgElVOV*$cAotlO z(+`VhOk%w7cII!;^Vs68r^L90eD#vC`7YZT>^=47S5ET2@1n z6#&7V=)%a%xJE!Q!3|{5DE$3aAGm)BlQTmQxFVaYJQWF)g_Q)l=NwMwG)jIXc9OnGdi*&Omfg)V_VrW?UeX0c%?1x*^#&IsoNX zo$cTNuL-C-AG;p!W0NHO9&>ka*O6t66gm=;!d-lXQD-qHg_#w|?Jkr&i}vF7R&9oD zxosa4M;oh|GAAMKH@VY1NKP<_(H!ioMk+2dF+kK?XYRulerPGk3sd1*@3LonF2h!$ zl*!!mPDQ4zSE@q|2g?luw}0=&?Zl4-M(8v$Aw%g=zw2PW7o(rxG*ENZXPtOD~tsCYv4>7FT2FPQ|^^V$&WLrGob>!`I$yby7jtcVA1Me~SJ~i%rPtl8#XpJAp7Or5KkWAfH$Z z|3sjoX2d_u2$)+WnUpC+Lvfej@cgu-bHi4M5vK8Ip!#qHhwBRj-+v&MOT8xkskMye z!x|ec+ExtwA`<~LbxTIE$Kjk`R;ugc*m|Zt%gsa|BQ!QzTCRl%RktUZhHxnvY0L%o zRv}titJs&%xb%3^wG?PeyxCdfk3o4VAWuRmrfLrnRmv;gR}d8Oi>>uHvR)SAkdK&l zF|bEjV~0RN$LZz|l+GS;6nj43mq*bhs_#EfP1$^T>lq{?>#4*d^ZnZdDCn|Xl~;`5 zT2O9S__i;P0mnmi7ZclHFN+km2DBCZzLjoZTgW(qJWxTdH>4GO#AL$pe`GPf)~V15 zEgQ{hWayo-m;e@k865QZuAE>=(%y?(x=cokOH=0lCYPqjRyvecS5EX7*!)SdU9 zZTYZxv-+Rs1yV9z^tj^^$pTq;;pZv+*{|NK`A@O|%X%6*4T&D0NLn^O-YWeC+Lw(F9K2#Qu?RF|Wd66-1R(@|v+$Myu ziEH2W6VZiGm;~yD#a%?XV6wQ!7$TBIkQrE zoy~D3s^3MrD|%V1?wf9T&YoZ+0e^gI;v2EN;8vfSnSMLYbA>+m|0o}NhQ^b>sgTZ; z*sdIv;bf-}Eox;Uu~=E~>DW`4`6&_{Vw6GxYodoMvIXAssfnj!4iVk**JNZlKTcYz z#CI{4n|`e9jvd!6tJF*DZ;gEm(S2_2ikD+g@q&-NMS@fCakq-f75%oJn%Ez6iY-Zb zYd*Q$CA~BuO-UVb%ZCZMl&Hbp;_@F*3MDZw9k9lL!*tSxMKoR8iLd5cljgI z&_WY)d{v(;8Q(Jzcs%B(e^zMawarP=zLCtQ`KF{5% z^c>zLb!EDwU`Quz4$7KBj{l6#i#d~OU=}}38!CwTspvoo;?WOLH%c~jxHI=% zl0E5of|eU%etJx0`-eOZgV!X5(UZg(^Px9MNi@;0&5S`scTa8{sKV@<@HwmGmz)Mk ziv7?$#yZi1P}f!z^0Q#g{UFEDKL4`amP+bTu98iN-6B&js~6`!mw+(6L*8GPu7u{BDPa`O(+ zF^4ObW4@?zfp5fY;<4nLn4xZ*)V#`SFEuHP;RiQZlQQhb8e)i6=Pgt9$Ap;2m{Sqa z5{QEAd%14R67_GOV#h0n!j~`0czaIfvqA}}9z?%j7yFy2B2`5j+rEb{rD@euQ}RvR zAG3*}>Lz+(Hu1fr6!EcYc)x^;5Dh=E_Y&+wfVznf zJQ&rYYQN`wK0nO11g65T#*}JL{E7&gUU+@-1DJ0tqQT#MZ?X14aqC*LdPDWb$ZS%* zyWg&1gCd0y(K^6w+^KG!*g)OKx(9santfDi_Yt=Z)z+eI7*wNR9g-R?mt^#0`X>f=AE6#e-R98D^1N>!~P5Qzj%Qj3olL#w52%L+%+CjjOp}fXmEPwPW<~Uo>YLov|>glIJt6 z$VDZH@BHN4?R#ULcGaYM|2ECeqvqs{{>K=9Sz|GGuGdJY2Q*)660?w2Yd6O@8}dkC za#8Nr{9s6O9-R@x9f}DTop|wT%}=tDpJ3Nsl?q|uDd7!_-sRfv15TH>HPSgGQwc*l||%>(|xp?F3YetGH4bIaeoPIOMX zz^aK9>8>Tp!uM6yh=N5G-)QyQ>sDYJSBdb^iddr(apLruZ*5=x{;dbmW1%9O?eY%>dfO(gSu4gj&Rsz(UEAm{ATVObb?>cPk>*KeYVTO`V$34t zVmlXUkW*`nGHd@zPe?z&n0DeDoY$nlvJc%6CDBs!8V>MA^IY1HcL zSe3HsCn~vt+EfcHt>v}~OO8}})NFR>)9_zgkBv7t0{CadW;40Em>YN1(^l7e<^lNn zbhcK!DYo%lDg9SupvEIyR4KW;4EQgH6p#!}_@`5n+bV9?9f<<@P}wv9uiO=D zw>1HU6Q8VI`^e)j{<{5}?q5wgH9>3RoK!^62VHAZ*Ej1O^MgZ;re6j#x=iS$c{IrW z*%Tbg-FECB1wL9|EQW_`W8y4|ZaLcUrNxr(w)rKO!3G3CgUuuXtU1biILMQ+$h#*? z+C#XUj?sEz+zDk3T7;PBKng!vr7^BF9TTCu3-5YV%K#IVrytT%e??KZtT-FB!3JfF z50h`FuM>il48scL(k^tB+@_duarqb}b_C&8dzFx)6lr`+;iA<%cakSI6gTyio~vW5 z^4o|-{$8O3Ia8n{A0Cdf=$I%XBvt?EJ3EwLN2phEgf9*!`SD?KvP4bYm^W4}pRTD!)yUemzpk1<(Hd2 zy0=xAPXMd*X4{Z}%WZizQ`(1&YJH4D7^6U6d`|RmffkPbz3~d-#J-JBQQg{DSquH= z*2o({DQu{WRO;_`2mNJm**D|=mjVi>Ur^me>Nj{DJgcB?;~!x_S`>10ZZ((!AL3xDneAU0b^)akpQF;KijL))ef~m`dSA*(ke(0S?GvN|Ko|N4uo;%$p^+s0%CrBE zVC&+lT4@piY?421?Ym;v5T8+DYkzfK?L?4iG(|P>%Qz{a2HP+Gy;j-HUWHHh#soRy z=>HqdXWy@WwmRSppPl@pwQj-!<)c~dW72GD_IQqU_w2lV@0KJ`0rsTYP5eOJ#3Ty# z7rIOT?99lD0vB1IopRK?1T%N2|MRQRv>E>0Qq~eFLR~;C0~mjU zC~kIE(J8Pb_^94yTevfCme~d39Keq0__>BSe;3k6WvN@AU2P)E4G>0mDYXe1q@RD> zb8zZOe9u{M!uxoBN+?n(wE|&dFwRN>vS3C-%%!NYpl5VVWOm_Z0?zfBpG>s{ojIn; zvT04t_Jwwd$(QtfUMp0X^g85riD~~pqF|5a6!)v7mRSt|ms!8R;Dje-dqpNJ{e9N@ zbb~%tY|?~X5MzNY4eg}k;gJV&e@Fl6(O zv~1mEKDtw~NI~qhsG@msWd4u<NW}$isX-COx$Gtr#mPxAYof}R#7$njN>4kxz{aEPA)^7|xShMVB@pY1 zR9~mL>B)-A(ZrZ&83xQnt7>zL%6a0Yw`EI`8Z!i(Vce|{8(DGYdgbV^*{Yccwq7~| z)ap^5a`|G@6h%xTau(-TzN^Ge9$xc?;(fdRtkG|=!FZ*PgzLfAHN>AKQ)cb(?lWp` z|B`i}kJmVizle&@?{WQE!&Kk-^E1Wg%Tb?p-GWWyk9w>}JOkRvYt*a!n}{B~*!0Uw z*QrMva0~CNzjsN1sxM@ApSgoiaz)Nbjz;l(PfUn+)pE_JM?1yGSH+}F<2;$Kf8JlD zP|up1#ibctf9_l^C*Q`KP_QWQuspsM_ilgFY+Cqy{kB7WyXVM1cn!m2Ur3(AA|pjZ z&ceYv>RQ@9p9OhgnH;hveEc<6WSnUO39}E)4570|fv|=#;dcr1Z!U-JabGX`vU(f!4xSV@(uK|xH|;{Nti{O_ zFz_`s_TC3PWpa16A0PZjVF>#On7(bmN6}dJwR{`nhv58$;)JhJvH6VyzKN=&L?Z58 z8_xflhhN5@*hs{xIP5?)prBSr>piC`qv7(S)Dm4U64@~}U+gnMY_Yjy*^s_UQI;Yz zdW!9%K!j#l^}~*Vu5?10OqO4r|C?N@yohaMm)IXGP(CHeM@z(Rnl(Db8bsHNgfq#8 zK|}|Bmnt=uST38p&M-*(*Y^mcgSVSg0}7YN6DD1@Mkgi|Ku9WUl(2q>1JS8wjcfTn zI=P@#q%6_Lfw@Vu*U(>oQ-fmUIf=72~8|04N|TkF4O?4Q0Q~E{(?CNV>wiY;gGUG&)S@(~AF_^+4w(mYayd@5Ji4)hbx{I`Xuh zYof5nywf)b>9vPZ$nu9($$Po^t-_u;f-$oj5s7toomN`E%ZofZ(4E|;-U%xpntWvc z$UU&pn+%m)(m&^mqPDp`6oSuZ+BYW5>IVp3!F-P&A1Da#zKA4EY~^>lh$= z9;4MZa*}0+-z$=NCH-Swlk$#b0@apU>5K{{8H|vOHA7E>C={S*jN4G8fUllwxI@U)iGxH4 zUlep$1~OPx_aN=JDsop@qh2lwQBuJi55BNw@6sopzUKmy3)c%N+F5f}I1v|K7f~=O z>7XRV=L1@3!VtS~eMVXIM=~=0JK+i7ogv+fbsBa<1e@!iY{_1TQ3sNu;%RyB_^T-zrKgS9-Sk}Km!)_T@)2dtbRLPSwg9p5=+b+ zz^+p00w@OA&P2jfS&OGb8LsIz<*F|a2`OZIZ=!uXB&cldr4I&rS%tG!ylq!@pq%Cx z>MGwC4--HCIz|*OKeB@xirD^d#2^2cCOR|_g}g2V>dZu|aHYvrpC%kaP<5>w`t%9} zzhwE><5Q~K-n;y87yn*Az$2})q}t>$!^I!ADgmRP0{<-|mzaUTWuXSq4Nyg_ag!%^ z6~zektZS^cfRe3I25qQ&qwI&cHC7Q3li?fHhCU}u;jV46Nx0O^Zslf`p)%JZ$*Y|8 z{iw$6jt8zCGNqRARy;lFMszAH2;00OH?Uc7_Ls3qZroTjsk~c-1zA^waagbY;d)!Owj5It2kUcBrDzOP-XB}hSB z9>Z1c2@MkEjg#0ZRs`ndZ}9ils8bf5nP|gf2v!PwUW>9ChE^-r_xTS31G%kN3*x|H zOQb}L4dbI8Wt}^C0P^^}mG`6=*F*YCs#k8G+0=x8{GHOVjSBk|AXMx?J0|5O=N;p> zREXHDX&-N&$85!kQL@l!wO4tM8M(&yM+5Lu(I6R(Qg3qI!n@CsDpnIiNF`{<{?7wg z=rw6F-mKpiO7kdCsXLW2nUXGz@dKEMW?fddtHz{y#K#OdEJt_A&KoX_;0scz;06-D ziUy1(P_ZH~bp(b8Y)dj1#4WMZj)+<3CihPlhlKWwKaLq*M6z36KEAA^40m_kQ>Rc zJtd0&`Q_)o6Mr(nbd?-gW4I^{_#HjpRA4U3GPRrXCE8TuFUKn?10WIc32amS$u^Z4 zvndh(O}?ub4HUO4MdbhHU#K5LN6MDErj9o{f()?bct{+Y0HI@gW^wdL?avjPf<@tiFt==D{NZd>IqW<6zogDHlc zSCr+37m#GS<4EUi8hU3>uKEbttI1Qc4`1pa$>gH3MO}^sn|R{+I+_@D<>vaM#e96; zJ2pg2%9pkj9yPa-^xDz1?imfSFytHnmeB;TG+q$!9HwP%F&oX&h;ut7>j<0M4ox() zA`o06RoirV&T5-ma!mD(IA?{QcK8G{gldmal!hmL`G)pZOA@b_d&hnp8~VhMA~{*` zD9MJB?`LzmX{IhKXpuG=y#BnCLA%ZA%19}L&usT+_DgoXAsDW(=IQI25od-86PuH~xH- zL?g5}d%H{k3036Tg0@Y~BMoK@1PKl`NjU2wE>Gi#;vEcul#Q>A-RpBXC^gFyKfi3i zJon4*QLOg*^LL0a6w_z4Z>w$fw5<-VBLFph6o)?&`&)7 zdy=%Xq`%n~YzU2U+luxXPI`4xMnErF4Jn4oAsGuNHSAl9MtANqX5OxN{<4lDqeR9j zMyp-PPx6elEqjX7f?Y`TMy2?lbXydBQ&PIqHNzINLVjsUl}F<-Cg`@^DW!S98htOT zFzjjYc>;C&tiPA4H(PC(-yoeZW3h%3mm!Gmgm`)g;eY-DZ`)zBr=7&kbWRj(23?YK z5W+Mmk`>bbTXwl-vqWtt>+(#llcjpAu1#k(H%MNm+0|N9;XNCn183X)d5feC{$j*7 zDL!cPN3~B)5p#s@5vlG6PwejpXq^wGp|(6#_w}$4bcDDeU$AZh!7vY{lttdH#=O*> zHlt*0st!&`*;gTXJdi!ojak(n1*M%ftMl-_6uZ^MLR+C2u9)|r-kO3rJ-Z6Ro{vqQ zFfL+bID%qR8o-pk$)+DpovX5evM2?BM&ic!^pv9$t7rIp<$%$B9H?Y1_{Q~ol|Azu zX;JuHAJiXu`lS4It(OkZkWFg+n~Z&zDS6E!vm1S$h~8^*(N*cf)d44lR^wj5=O!KI zHA%3?f-W8U?lHB?G6nmY=C87S-ub4%VKG!bGJcV1eh*`+jP6~oFeZc8!G@;UO~j-S zc?Rlph$fHBx5P!D?s?pG&n#-LknpVM8z2l+Cv+Hw+Tyi+M*l+pY?XA}0di`#a=$<9G zJ6)qeBIm6z?Dd%%^bWVg{^<;}-k4kyp+`|F_CLr4I2DhKnhq1?N=unXRaN4D{>KK9 z+a75^Zaeg??>}tG*wVL=$7>hjZsOAGnd{M>(=cOI3gbspeaO~rrDtq$87zKNMwe43 zd124Qzv?&$-?{#+mB;Pq|5y27pm>yIuQnZaOqFQT=i@~i0*$6XBwQ$YHb@{%)*Lc@ zOWh0!(~3j7)`%Ap0qs{kT~2*N^QVT;(UyAsQkxF{w40ZBy_jnxNfxsq3ucOxy3nTc zY^gI!^k>M&*v==$l*$HG^xnSeu*7;f!(Tjw$R}^3({8;q?+$eJ+X+l6E_;!wq1@4} z`>s!Mv!k-CrW?{|(yT2T4G{QS!xcwMFhn6|s$b$(icbod?CgCW8If*=ns(>88tgsR z`T7kcpmQ7%_V?3F_*1JP$4U8&-EO4xFfU^)I=C;80bI~*FN`r%705!V|=(KlB_fWr1B1fyf$p%SUA%XrR@K}1- z#+q<5rB4IxP|dy&;s=8ZAYYa^PT`d6*~6_4drBQEyS$RaB`0By>>PE>mS@#LT1a*Y z`6QiG?bl1$$e3WV)nZfW5C`le7!Q^ducsT5AF5KJm?z&G^1-DO!69i-Z3E;HU zGzdkO5bi6iJ8EU1#A1X%{48~p18tVmCC{J{4bG+DT?!ahb|V6~O7G2)q!IR$DBR(J zQeW498sV@RB(E9G5Eof6R&0>P1Lmf;p}Ry7xB*Ent1ra<$t+2!!7$2+AIvXv0B=f( ztnK{yBtOEu?)?Ux5mz}sWZP#BbmIZN@U0Ufi*HcEBp(8|W?uy>AzGOgGf29CfcnFN zY8@&^L~cKKW-#b}vv*(f7u54&HLOunQ5QuOkAs7YNEmQw*4q%WHrO3TVrUXsw)5tt z$hjF>u`w{e8w_DCFRq7COwWQY8W9iKdEb8d{kw;d#`TT3ad&!vMC8v8^lr`F`Foq4Kg<|z(>fPq1($Xw~I-%)+OWp)VjZ-4|wGY`qc zxH^u>8{4Kfc~h(^lNYX!eB`Vz-)2}(JC~fgh%FHD=T*0kWIj23t|kwDpS+K6;f*(Z z`p{zRcf!H|Z!(|nX$xj-D)Kmkp$6}9-+>~UE-AY}@3u~mdrb6a`A=5SfevxB7vAMz ze-Hwv(rc9JO|03!vnE*SZaBPe0q^KxJ}jkoGn3Qfa!k_~eTq-r-mp(sw#8uFHY8fy zw#nX|XNy$#>M#ae3g&_d=yqqCj4)pfUEylUJZd=Hj$UcxAgSw^PKRac{Fyn1Vhg?k zEhGv(DwI~#K)<*1V1yo%x~yH1 zpfPmL%5z7WG=Ku>RYZfwl!=ea9kJb5SsQZcq{@I3zdf~Zkku3hHABOm#rNiRx85ShmzJM|xF>Wu zS%#GrW*#M)NArKt7l{0ucuRU8Gv+lrVePFRkwd_L3~w7f2JXwjF%R@k>u%NA>$;_p z*^&{rP%=BOSriDRO(Jzuz)a&lGoQ)8G7r}iv(EX)f?qebIrT??nJKy1am$blSa;=F z`cxOZSVNv$qAr`uy4&K;t0B%expNYG%;+C_2R`R6Ot+mubl&W?T5fc@yqL65-vnd4 zV2d;jgUF;_^Q)3cax~yPa>vVeTPe_>t&xxeiUoIy{M(gX@^7QHwA|hT{lDdxM}9_R zBd^i~P?dnNV$``#+VRTenfm=*;kvxkR`6FrxMY7xufd?R7@7PPD?R6XfQU|W-@G0( zy6hhdaP-?gF@awXS{o|o`dc%+0P!%y%3){eUQd_lFS3mzv&wa!5X%c%pfnW^cmHFt zoj=X+L$_nhU?XOjwq^t?JQTSwtPCw!Y$^<-O>=$U42&_jup#T-$rQ3=A2m#zY8C1 z*n*k~0B&C21%Y`ZDxNYPY_1fSnYPy8fd1B6U_PFDiHl-}j)Fwc1}d|qP3RL11~Cd? z$)Hr^i)Ha-Ez6U#LLl+Y!MqZba11t7?k#LEo10;HeYq)rrWetehB5O4N|DIBLEda! zW1aJCPAqSa%NuUTorR`uD$0$J;lDe5bK7}C0LKl57mwIjDJVXsv!Ru>_(h0#3c`! z?F#EFJ-uB)$znwP)2?1P`a(Cw0*o^<_EF43rn#)|v8Lc8Ej?^=C0g1d(a47(`@`;PKnKYE@QN-K2Qt;=JBZquAW`HohicDd&@s&Krmq2 zabNFL<0d`H70a<*4;)K38b)TD_DxybGxcaodY3FXV!HqOeMF!gMu>Y+FHjw+-u)*qTL>S?u_xIpr%d0`%EX=$r$)9=7;i+)eAwXze zXtf`2N%!u@Afgel>~c-@&AJ=St}c%=@Sa|(=jD(&QnnAUX zHRi{ARxV4mnNwiE>T<2pO~sOxRMUZqyhOJDSB)WVOmeh#(|ia1Gs-8=f5p7Uz1VX9 z)TW*ceVf5(XlTxfzyWkyafz-?81%ik#|!`nNMX9^#;p{*gBM_UwPMmu&gM#4-E?phoqcVNSehoHC!P)!>@{m%A!x|aJ5ZU)% zk9kz)D$Mr18C+F=b=gg(`Maf33^vUO?W!*i>c`lQt@ZCr-)TDuM{Ez24!(?7T_-8) z-&1+MCA~R#zD0HdG&<0e5zW~UF7R3oGel&CM{j0hbqW#Aifn{*lJ-lH@?xWxD>;F( z(?Tp>X_dPManvHg1qwvk=!4d;!gQGZu9mszq>mnZ-uj*zB!&>oM(}K?epkJo{v1Kw z4Q^~UrNLWP55HtH5p1PxS^Mgkz2?Agl=9AT?OW|HZbq~L>4ff<-s~EEh{EI)is+Y} z291z^;^_>TR9`7Zc~B3#)YlkhmiiwGo?5-xc6^G<3oaTNMvOBTb59HysJX<{PzlQo z_KnFE$mouwG}VEX*+7cD!DS?z6`VS|7T;r1B8Bc#C5Zy z+VHQizF`%%XjG;Eb6g=j&$SFG%zU@l$KTesOW)=WBmCitlpM?^GuGe^Pi31N;exz{gfM!Id!pe$_)b*et}FWEg?# z%E+(>9!a2>MF8iTnZ*;r)jDeVRT=a})?)zmDP)T>t26BItI91_bDPy;aWjXhKD$bv+1M3f zi5Qe9BWt=$M94YDHT@R9juOf(Bb{ZNbxmD}SohCBxRVglQx=q^+q{r9(-9vw^E5$B z7v-x3o1)@lVh|Kse$7p$D_T6GvKv64+3wfVk7nyIZoN5w=f-X+w~MU8z}gcn8$rXO zoHqLq2W_?*7ECi;x!Hy}XO&(|kjk)EJM*^FD3;0+3kIUxQcdDK`stJfyKP%%cxciD z!i@cf`8_2wPq|}KzBgFP++?(6IQ@goAJIXUl$CamulF~TpiK`vVwjb1cDzxvE$W-U zg4F`9YO3&=8YwSbKf+(?C^D3_rAtzm!2pR70?SEP;A~h-wycVmj-5{$c4pw#z1Vo= zW*f9+6QujLzG>aR>MPe%!f(>7NAkk1K~|_&O4(dPGf+i|m)zxAw=@DOgHv5UbKz3< z-U{d){@;{;zeN$^eRmj#v`*FMBa6ny9G13jH5APZB1`eHY5msV0kaJrueD*b*J}b6 z9U(t39NZGx5`gqaeYKQds+<&f{Mj%pir#PqvJX7HU@0>lsTw`sJfGOje5)PdN<5?i z!`^9ZSR4^OYS={v36|X3=um7*jd{0B?LRo7Zo>v$j+2~zOy#k*g);Q|IvdXWY(Xv@7PtB4&|4XM0l0_5ku8Lpir2i>kNnnbkQ zR@UB;ZyAMo@rTq^LIkG8i+~^*w1RK>pF;5r-MVu+V zXDM<3E%2)#dvo`=ZrSB89yAK9n`^aHn)TZec0MT ziuLjAL2p?CUQ{Nf$az`495>oan(Jce}M-Or{ znnD(5=9gv|CFgo{F5x#_p01|?o@tI-cC%r&%lv_^X0LmOJ7VzWOZ(E#jt7P4A(~{d z*W;^YL37WLCwg1)z?gmR-(8Oxa440SlxC)VyNQbTUY_@B1KzZy~`%;wePAQO^E zil7y4A~1_8%qKpBK=w!boZ+l)Ya4<^xaFJj?CT@v5h;e~ZVR92IxeOw~_?@cXpr zV6@ME%o7QNM9zjwKc&IXvBnH4R}vvUeyX;cTprZHnAsN$`%=VB*LCkS5!G!C`)+om zrv`A-<>}>nUL_C+qJk`761QbD!asEoi_pFx39}O+TW=3E{em9MJWoX^2Vw`GvZ`g) zXwL&(b!0&d#q2!{*uLRAZFr@+;T1uhL;@?6-kYt9zRp@9WcpKGCx=p^Yi+0vUs3$J z#FTmKl~d=#XERHVbE;w4-#S6)nxFaqoubh%wb~(MXo6L&!3qFlA{tfH!kO$rkj4ck zO7@!<9+1*_YN{}7Dfh4l%j_MIPt1!qOEh}YV;X?13$CF(loy`Vwr#1n5HG8kG!E9>9{#(f`6&7P-ALti;O#fsPyQC*uOUVnO zOVR*=sl1@Z#{x9kNR&nG!^x|_nkyp!VCWG)1btJ)B_G+QRxp}vC|F|ya^ePHR#Hl) zmF4TofC^by4!DM7f@Bea72gFOB`Ca_Pd0)?d+vd*C~-%Om!U2} ze5ju;a=cmtHl&(qUrlsD$%TIB-3?asKgJs{16bp)oR&SkXTR&!o$!-tNN{Ib?ZuJk*Gxx>k@J55~4rJ*Bzb^~%GE z1@2-CC~%_$1%r3JrZUPm>H?yMXgOQp=L7BFh`PXJmHz)rPTSOGvugi1-yx-Bxp|ZeQu>f!V8yicFt%v*Xu$r1zo8|NF1t`L?QTeB6 zioZGcs7()^{UV2{E~_^DdM@;z>OT}Vq1oRS+Q4A)%6 z8O_&w)l~)wMw}@7>#;P)NbZn!CY##q0uA*QP7)}duY`Eig01E2jafy#>UHXh3QNoO zc&sHF<+R%)qWBOu_iJePel>`p6uAjA_cHr%$|>F{2FN5sn&6?yWH;ZEWhclIAI38l z03o2M*|=-8dH64Oy43uz_w&xvqL*##Cixx@a7Sg5#gQjln_r!$z3fS8xL2=qTgb=i z9-AYV)wED66Sjdved+!@KtJY6N*xi$ODpr=&>E~p*6tLmE44>_!t)ebz;`(%gdnfg&x$xrCPlnic#yZ*v$wuF~u$z=oJ^AA?N4$V(`xh9q@5$MO<>@4=?;?w#euqaKP?6zl%2_Tf94!Eu^*sB#96}gB)*VSnhm%iZCqCd- zHUc}m^$1vzFi%d;u^NR^s7<3j1IZFHqW)9SD{OU|0R{egD))Gx#j;>!`0R@+vM_3`&5S|X?xk3_L@r3r`P_G(InqJQi| zBgoISucX8cNWrT;Rnd7~evnN`ZN@AOMQb{4zkk0?9ESYbJejmUOv+)}%Y7r}$ut}< zcfub?aA>^#_oK=T2$)ey;WVp%|E0`hFJnrEP?B*>KTiAh8n(K>PJ6PYbTZ0kmF1_# z^pl90d^0v?Ee+p)??)P8GH5)m8>J15?aSpVvjjtMuFw*brndbDngM&4zK;kOGEEey ze`}u9*rJT+qxnBt4L3{6bhe=Ct^aKh{5?ce73C9k!uH(9jDZf%v1w`_lo;K%Q{%7y zZIC+q1*Daku~5<`x6wUBtfuLz60_RvLjAH>aZGGIOKFQj#&+wVRJm)3b*0idBu=du z$^3|l@(nf-iV|DQ$bonFUTaK2{lq-EgaLD1l1SovMPm>OJbXaGQmr$BCL{u-NldU4 zwTf&!3~DFTJB=CWV)bG>OSCth;g%%+hOEr#WMil$L*4O-Rsq44r~{5TS+jWW&i8{hlbKV?mV2}E?80b-wFPmfJ->bRY^P)=_=AUtM z;=eTdo{I#OhX^445FNS}X(-Lm8q@USh-UCxyt#AvKASZ+k(L@W8ECX<)Wbt}!xTYT zFAtAUqG6X`XTIhDSMkw!XoMuV+4_o&x>snPcqe6@+N1HIi*MU6@j`6cg=+)t_xK#k z%Rt`$FD@O`D7^n4Z9BoPsdl|H?-&tRGojKt`YfVpbKk=kQ;ehabn`WbrbWU6^0Y&5pStVoYQWAB8{m);yUZ?Xi zJg)1+P_$qH2hy9IRn6iAmEQ!<*<)PDV(0>buz*?wn}7 zhD-BzZC}K*;$EHzur#)y+HA9%1&p?Z>!y+R`naScRR0mB3qQ4X^i7JfNWafwJfk(= z`&aq)SP}a%--hN&JFvpr`m#dN4yU1Z>~ugjtHp#^s+ntKWxY>!zTFgwQDqdCQV=Xnxne3vkkMqADjd+w)LFkyd{t#O74CSpXzwadXP&G8}SjT?$K1fzy&#VHZg zmP^v@0jE)FGK8A)rVo)TJ$);h8z^PNp?nUGNF&MnOe$n(BO}OY?>m zky>Zy1DxWCC$_fEs(|T9)k;0HDs}>>o-0o^+cAG@q%d_0@hde!D5@x%^(MO*-~)1` zuI#k{FZM25vD5wDx^dj&J5#1Vp!<+}e5tMz=|@u|X3%*4%r*(=$G^0U2ZRU6)u7ZI z@tOxo>3TyimAbOR%;q8XrtCJWsY2)6f{S>?TcOu=g)#rmgNvaGNK};DnuByP_7K31 zDL%6)2qON1Rt<)w*NPut-F0-PvOsH?LydE_@_?DqvpEBl?#$14xH=Cn-tTp_jE8A5 zWaj;$XS2&H14JIcl_2|K>YWDy{eCw^L-h5}F^Xn{t($RoM)2W<)J9MXl|H0D-=*=4*eU3r4vURU# zgl2fG(v8LZo^bvy6VNbvz;iwHivU{rMmk~4NnxF27!@4aElI5vs3{CkX>q_@>X0^3 zkg{he%5jhBQc$c8+M6$#up%lYC1;lhrC?Z4N@>EY!+Lo<30Gg$J>~G*Iv~EwuNhQw z#8BWyeZ23OBS5vgZfbCpa=Y2~$ ze6wnFT1Owp6ILB5diClB?Td5~2x#v8&V2sTJnH?%z&gMwM{|5G>d-{+{Qa$lLR?fZ zr4hvM)B)ncs(L{|l~h(trdVoD>%B*}Anw2{1qsu=uZRkDZuiNkNyj$k7g|G$xkyQ#+q&p&=SV26mt0=fuXH=tpqt>{glPpz0FexCGd z7n}Iimf6q$f5lyEa2r<@zPpy?m7+MZ?0^)Uu(IWc(w54O3$~LVE89&J)pdnK8QSu& z9j7*Jp$ZB!4Joje73ERaD6Ueh;B@5HPMYuUN&3y3;PtdSJ>xSGQh9t%EzN1L!tQ?U{fdBY3dW3 z2Mr_#5akP(ckb3f^Tr$P6DkLsl1&+!h6O$N-!Kbes<(L|Ff?bzI%I4f|1^t$#F;DW z=7(X-+_tlm4=xLKt1oQKW6C)e zCa`O7V*9-9b2>?(=y9@c)0*-E2Mt-gPjBm0naZJsN-MF$X*KtGeU#8JHt3_wYi*mE}meAKeHls&mC?^h~j3 zx1IT?;G#snewiVUf+<-eIzz0aw%gs#c&JM#t>!Bp#Hhs}!}t(KxyXYDnh$Km&se_# zxd#i6=R=DM_i3nn1}}3|%dNtS!FEtV4!+}2-@J6A-pcCj0yp!u%@O+yH*-wmjwE6L zkG_0SV(i#U6O{R|S~LRLZflRawR@N|40oXW))OD4D}L#F7!r4+GblGV1=?U{Ok}PL zlnR3DO-{s!`vanKqw`$u^bL*%RhFRY7wBZ!?-F4w+|40e)BQa9dS}`^|Y~ z8#`n+LI1$lMC{|6rBfl7+Gn?xFPA6D6(J0BPm0qpNPRF@AuE7PPd$t4nDq~Eef6QS zoinXm)?i(0V1Dz7k5m$gW&$yN!njUU;YUOO`A1r^K=5%@n%%_$$ zy)YA%VG%3Lgf+JIq^T~Utf)iS&@434oyfLOq*oyfnG@-9-5w&ztQ=8KB^A3OPV~9G zdCHK1`NeA=3%QKSDBIE@=~(%4<`~uy{I(-8TpkfRNLqqP=S^%2npknLS|5! zU`lb2a+#}_ji4FVpnEx6FQL`@VeC;{fbQzLVZ31^0RjODWMm7HFwxKjO~!I(q-B{wD#WkFL+hF(Od8rQbTvs#M9<32Vj%-;nxr+5%g~M&hXjqF>I^~V zI=$DiS?qVd$0Ca?>epMVi1P7~FggSsOR*X@XEaEPSrnj7g|X2`#F{acFYL>ClKt6r z)vQ|E3VsN2S)qgO|AB}Ko#j`!kAN~jRSKkT{MwsKPhN}kFIT1_y~R(B9}VBS>@$Om zvUCQlk_G4cF+Zdw`7FHP6P6Y|>!8e#k2F7*e>PP>$a=bV7ixBu!F3fqtTOSk^$CDW zchgKmQ-W99?;xGP0b>8MmNV>SN0MG2EIO5j1+2ZA4%hUCT*%Z?SBES@WZu4(bRGvd zDcScfSDREoN8%;gt>}%NkpMP5+!aXoQ|Sk7CmrNl(~7=}+VD?++1DG1b^qm;E79;)F!Fx$~isY;BuG*AURN)#hTCF8RCj(6JKQ3hb zUml&g|2)&|SL%1&`yP^pB4w!0UuD57%U=1WF8ffBk5eiw`Q$yoMoofq@Ipklv9a%* zVVqWU+zk52Adnp>mI;>^ufAMB_bmgt^OeaPI_}RDxf?!&I7(Kt)xX^ODQ(xEJ{|mf ze7k0z`ksp%jFWw;k#5PyHwk%@{v@C~g+udpyRUH+5Ghnn+N+t!PT@qy2c}%x+FTk* z;i!2Ig`C)6Y@cs!!3KCGy&Yl^)3$RXbr(il+*zcqySf#}#dUc4k*#-@Mb8Mg)I)T9 zFQlEehwG}&rlg&6>L)iAdH2vROfD)v%k?4-FNC%}-T-fpL}@hUd2}gHBZX=BLFKBZ z@Lp1H4YciBa0o%@4s*(!?rcL3RZ+6#8J-&*ny5z@9B+6dq8v*)TtYLecdmw*#8z*2 zN-PmVS*a_#D*Cn~e0l>H?S1W=JH#;ax8pXUou{ISnTBmN>$z3_pr)$vZbdcHRo9)N z{sL1zDdq*l;{&O}65OOG&hT_^)xDufi`S$5}tm~ULz_h-!CO^|ii%=z?iS+>v`mp!Up}~afZB@I z`b~%X+QHJb==`mXwWAGH-IRCnB#L4TK@lrK8mbSYtH_89VtwW67~~pisY=hY0en5P zP}l6Bbh2?%^}%raH7%3KrxaPoWMuRmcKH3LUKwW~xCKpJ!vsBVe)UEogV_8`BRN=`bjJ1(n& zp=P3#h4DQ}kGAH_79k+J3Sxe|<(#Gc@NZt=A_z<;wprPrpINE=(K_l|qBfXzP9tvP zd7^1hMKW4GV~B6pGsgfeYeH!7l4;twG5)nkFtlK2uW^QolMg?c+p*5(lYf9LR)Dr*y8bU8e#RU`LlE| zfkiyKb3yk9WX}?|{7mhGrSq&k6D@wU=M=o@W<4winjq&&os%^d9gc=NBBU#Wlaob) z@ueF0(jj+Gyab71-6pSp0DC0KVb!R}v!BjIads6P@aa8QA={Niqn0XWq*FG1d3@O| zR<5xTIP>9!P&E>J1Eefi>G>=4g*FXaFPfskb~!Tc**6r0o3RHj8{qG+S+xdBNQTRb zjr;bZ(56GYVany-CsOYS&;%quTbD{rlUpgKa811RH!~$UbI_6M@L75h@#Ch1@JroeDc|^=f zBG#k0z^o`Hqf2Kj;y5eo#OlT_+Mu_Q&Xrog_u^?5a^}Q4lUPChiHPDOY4G#)h}tTYup6YB;*n&-Q7+MP zf(u{1`Q!(TjV{k^SmO~l^p@8crwu)f&49!0-Wz*qrXi(3hc+mh;ph5&CpaGDn-b9M(M>m`zcfrTF308x#Tqa}*d0Wl|p(Pf8Zl<`Vk`0W&k zMC1QupWR$PdwU@an6mquyXUp^iN9W>9$tv=;OA1;f3T{PLpN{$i)Im6+2}=R!k~8r zEJyeV#wr~~%@?v*++UiyaB zJ+Gb((gO45=84#AUL7prOYbOZ*1pKcNdvgjjuxx+*F5vhO~N#sMfPVer3y$ePAz$& zom#@(?~sx_G~Zp;oT2(Gu}`4xwJV)-vekcs2+)itwQ$!bbZ{nk>+7XI>CFPJrU;Jz zovvKWmI_-W#iTD#NvD^Dn$s?0&KPu(&_jRJwkw$r@!1u2-6hj278SloE-U3`fQ zBGF!w1-7y7=U^%?cELOo!c6w7SJ2#iCs_pYEJ?!SlM%WnIi} z%YzsGI{W57SD1`@e)8xa_qMM6>aLk1uNxlp9)02XpZ1@<>-)d@)|<-;ADEv1?pp(G zU;o+fp7`7HuRMF; zV?R9o^H<(7tXkXXz5T8)>_2q;$uqzB?O%=WyJr1Ocig?}fv2J$Quieo4 Q@q6wc82N^=NMPxCx_;{X5v literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof-test.gif b/trunk/3rdparty/gperftools-2-fit/docs/pprof-test.gif new file mode 100644 index 0000000000000000000000000000000000000000..9eeab8ad2305f48acdd8a1c94e52f47240a3237c GIT binary patch literal 56995 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 AzW@LL literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf-big.gif b/trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf-big.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ab292abac5594335f9931dacbe020adedf8de30 GIT binary patch literal 100721 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%0A+pPT|Fj zKvA`FOBI(-S91)1X!Wlh3?^WC=e|C84botYy2>T*@Z!g;L2ObIVL{@|zR>@Z#l7EU zil-ixp_IxS%GipxnCURmI@%BUj;R=xdj`c|)dL2I9c^aRSv_U$D@4^v3+S`eZOo-W zq3iRzND37z4>@FSz@km-$NMEy0C05DL0an=9!_0qH#rCVauuaeLRfBZ)RCkkpBx$> zS)-6ST}$AGMJfFSp%d)C0NTddA3loDRiYu8^fTLTJ59A?t1bVTpY;L$12CB>-E9m-@x?JQ;e8wJC^JTWjuG@l239qGkEw*|5gsDf4i zO0m1m)6h!rq{0-iqksWhtVe}_ISoYWXa|Us|7s5g?CAyg#QG`l7#TV1@GS8EZCaJA zjS>pOnH4>~K~6<8bQUR_N!Uf77p6qs^I>$l%O))##)N)?#*`_{?L$m{*KKm@?u2ec z;&){YDitvZP5G3*MuD@SHJ;`X5l<_lDsUY#cDn zxTi2|^sd1GozF0MKBsEAJ%W7By|h}BN}*Y-{st9XnQq`J;&}9~96Ay{^PJIU#Udqe z3E%gzPC2PfSpGlFkds56Ed}9dbls2K=CQDCZ-z#4SK zkqRshalu-;TO`y!p}bR%;lB0jMZVI@Y1#adt~q%fy0>hma>O4A26?s3=an253ZE{Z z&)+i_D45>qf0&vosH&MyT`pU`)#+P7j4=ubkrvQWydLfS#Apq6GXd{R1AfomfJcnc z2NwG6T0HfO<-Sj<>-&-LAYTDW6KrYcQTUCq_5|<#e6u=wRsP{OiZW7&j^iWolUm1X1RB}Mut*ry z_N#~nh#6bo`;`{$St50eV!d{!VdGwOjN=;=4?6~r*QC4T*&i@VNF|y}VaLQv{6hVs zh(3R3YBAmGtYf{g#%+;S|6@z!Ed=t}?D^yhLZ{80xYBy+EyaN#J$z5Ps!Ma%0Udc@ z3C1!?upzQa3}vPs!&-U6aClvOzvfJ|8XxO6Je$pXIegmY$68jHg$%;jeS+g4^=Es& z7+B8hEF#h@U)L-cF@ftOo!=9i2~fOi&E&CKvL8$R5w99Z@9aNd zWZ80@8oEwWEEE>_aGM;FuNIht(FrbNZ?4~?BGi{LL0@7f`$QbCOZ39!7ytO9(Ya%R zDZkc6&BUgcKA~3@XR{(n+OIwT$T#qQKYRY6c~6gd)X#rBLEQ3R(ocUCKb1Cntj+o6 z_3$r*hV@arm0=wJjokGsG#Z8R_)Dm7>j`L>1bZGq-ry9RMx;dPh(o(weSKpaG zqkZv%=l?CRu)BKQh3~%lVDJ6kzW7D*t(ck>J_4Jj-@BZ@-PLKX! z^AFw&r)n~DOtXsS%`ad2x2wOo@q2-7p^mO&Cw~6Q**D+0{JY=(yCQAUl-${K?_RKE z+1Km7^~m>Ie$>9NyQlZ$t8ZNR=PMum;m^tGlc&!3o3DIzVMWaY4}Sa6A53lCzH9%X lpFIDIQ$r)~Uj6uw|B-Urm%f~L$DQ{qy7z0N%};Q5{U3`G#lHXm literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf.gif b/trunk/3rdparty/gperftools-2-fit/docs/pprof-vsnprintf.gif new file mode 100644 index 0000000000000000000000000000000000000000..42a85472caee7aee2846e9dd09800588f4e7d041 GIT binary patch literal 31054 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof.1 b/trunk/3rdparty/gperftools-2-fit/docs/pprof.1 new file mode 100644 index 000000000..f0f6cafc1 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/pprof.1 @@ -0,0 +1,131 @@ +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23. +.TH PPROF "1" "February 2005" "pprof (part of gperftools)" Google +.SH NAME +pprof \- manual page for pprof (part of gperftools) +.SH SYNOPSIS +.B pprof +[\fIoptions\fR] \fI \fR +.SH DESCRIPTION +.IP +Prints specified cpu- or heap-profile +.SH OPTIONS +.TP +\fB\-\-cum\fR +Sort by cumulative data +.TP +\fB\-\-base=\fR +Subtract from before display +.SS "Reporting Granularity:" +.TP +\fB\-\-addresses\fR +Report at address level +.TP +\fB\-\-lines\fR +Report at source line level +.TP +\fB\-\-functions\fR +Report at function level [default] +.TP +\fB\-\-files\fR +Report at source file level +.SS "Output type:" +.TP +\fB\-\-text\fR +Generate text report [default] +.TP +\fB\-\-gv\fR +Generate Postscript and display +.TP +\fB\-\-list=\fR +Generate source listing of matching routines +.TP +\fB\-\-disasm=\fR +Generate disassembly of matching routines +.TP +\fB\-\-dot\fR +Generate DOT file to stdout +.TP +\fB\-\-ps\fR +Generate Postscript to stdout +.TP +\fB\-\-pdf\fR +Generate PDF to stdout +.TP +\fB\-\-gif\fR +Generate GIF to stdout +.SS "Heap-Profile Options:" +.TP +\fB\-\-inuse_space\fR +Display in-use (mega)bytes [default] +.TP +\fB\-\-inuse_objects\fR +Display in-use objects +.TP +\fB\-\-alloc_space\fR +Display allocated (mega)bytes +.TP +\fB\-\-alloc_objects\fR +Display allocated objects +.TP +\fB\-\-show_bytes\fR +Display space in bytes +.TP +\fB\-\-drop_negative\fR +Ignore negaive differences +.SS "Call-graph Options:" +.TP +\fB\-\-nodecount=\fR +Show at most so many nodes [default=80] +.TP +\fB\-\-nodefraction=\fR +Hide nodes below *total [default=.005] +.TP +\fB\-\-edgefraction=\fR +Hide edges below *total [default=.001] +.TP +\fB\-\-focus=\fR +Focus on nodes matching +.TP +\fB\-\-ignore=\fR +Ignore nodes matching +.TP +\fB\-\-scale=\fR +Set GV scaling [default=0] +.SH EXAMPLES + +pprof /bin/ls ls.prof +.IP +Outputs one line per procedure +.PP +pprof \fB\-\-gv\fR /bin/ls ls.prof +.IP +Displays annotated call-graph via 'gv' +.PP +pprof \fB\-\-gv\fR \fB\-\-focus\fR=\fIMutex\fR /bin/ls ls.prof +.IP +Restricts to code paths including a .*Mutex.* entry +.PP +pprof \fB\-\-gv\fR \fB\-\-focus\fR=\fIMutex\fR \fB\-\-ignore\fR=\fIstring\fR /bin/ls ls.prof +.IP +Code paths including Mutex but not string +.PP +pprof \fB\-\-list\fR=\fIgetdir\fR /bin/ls ls.prof +.IP +Dissassembly (with per-line annotations) for getdir() +.PP +pprof \fB\-\-disasm\fR=\fIgetdir\fR /bin/ls ls.prof +.IP +Dissassembly (with per-PC annotations) for getdir() +.SH COPYRIGHT +Copyright \(co 2005 Google Inc. +.SH "SEE ALSO" +Further documentation for +.B pprof +is maintained as a web page called +.B cpu_profiler.html +and is likely installed at one of the following locations: +.IP +.B /usr/share/gperftools/cpu_profiler.html +.br +.B /usr/local/share/gperftools/cpu_profiler.html +.PP diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof.see_also b/trunk/3rdparty/gperftools-2-fit/docs/pprof.see_also new file mode 100644 index 000000000..f2caf5212 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/pprof.see_also @@ -0,0 +1,11 @@ +[see also] +Further documentation for +.B pprof +is maintained as a web page called +.B cpu_profiler.html +and is likely installed at one of the following locations: +.IP +.B /usr/share/gperftools/cpu_profiler.html +.br +.B /usr/local/share/gperftools/cpu_profiler.html +.PP diff --git a/trunk/3rdparty/gperftools-2-fit/docs/pprof_remote_servers.html b/trunk/3rdparty/gperftools-2-fit/docs/pprof_remote_servers.html new file mode 100644 index 000000000..e30e6129c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/pprof_remote_servers.html @@ -0,0 +1,260 @@ + + + +pprof and Remote Servers + + + + +

pprof and Remote Servers

+ +

In mid-2006, we added an experimental facility to pprof, the tool that analyzes CPU and +heap profiles. This facility allows you to collect profile +information from running applications. It makes it easy to collect +profile information without having to stop the program first, and +without having to log into the machine where the application is +running. This is meant to be used on webservers, but will work on any +application that can be modified to accept TCP connections on a port +of its choosing, and to respond to HTTP requests on that port.

+ +

We do not currently have infrastructure, such as apache modules, +that you can pop into a webserver or other application to get the +necessary functionality "for free." However, it's easy to generate +the necessary data, which should allow the interested developer to add +the necessary support into his or her applications.

+ +

To use pprof in this experimental "server" mode, you +give the script a host and port it should query, replacing the normal +commandline arguments of application + profile file:

+
+   % pprof internalweb.mycompany.com:80
+
+ +

The host must be listening on that port, and be able to accept HTTP/1.0 +requests -- sent via wget and curl -- for +several urls. The following sections list the urls that +pprof can send, and the responses it expects in +return.

+ +

Here are examples that pprof will recognize, when you give them +on the commandline, are urls. In general, you +specify the host and a port (the port-number is required), and put +the service-name at the end of the url.:

+
+http://myhost:80/pprof/heap            # retrieves a heap profile
+http://myhost:8008/pprof/profile       # retrieves a CPU profile
+http://myhost:80                       # retrieves a CPU profile (the default)
+http://myhost:8080/                    # retrieves a CPU profile (the default)
+myhost:8088/pprof/growth               # "http://" is optional, but port is not
+http://myhost:80/myservice/pprof/heap  # /pprof/heap just has to come at the end
+http://myhost:80/pprof/pmuprofile      # CPU profile using performance counters
+
+ +

/pprof/heap

+ +

pprof asks for the url /pprof/heap to +get heap information. The actual url is controlled via the variable +HEAP_PAGE in the pprof script, so you +can change it if you'd like.

+ +

There are two ways to get this data. The first is to call

+
+    MallocExtension::instance()->GetHeapSample(&output);
+
+

and have the server send output back as an HTTP +response to pprof. MallocExtension is +defined in the header file gperftools/malloc_extension.h.

+ +

Note this will only only work if the binary is being run with +sampling turned on (which is not the default). To do this, set the +environment variable TCMALLOC_SAMPLE_PARAMETER to a +positive value, such as 524288, before running.

+ +

The other way is to call HeapProfileStart(filename) +(from heap-profiler.h), continue to do work, and then, +some number of seconds later, call GetHeapProfile() +(followed by HeapProfilerStop()). The server can send +the output of GetHeapProfile back as the HTTP response to +pprof. (Note you must free() this data after using it.) +This is similar to how profile requests are +handled, below. This technique does not require the application to +run with sampling turned on.

+ +

Here's an example of what the output should look like:

+
+heap profile:   1923: 127923432 [  1923: 127923432] @ heap_v2/524288
+     1:      312 [     1:      312] @ 0x2aaaabaf5ccc 0x2aaaaba4cd2c 0x2aaaac08c09a
+   928: 122586016 [   928: 122586016] @ 0x2aaaabaf682c 0x400680 0x400bdd 0x2aaaab1c368a 0x2aaaab1c8f77 0x2aaaab1c0396 0x2aaaab1c86ed 0x4007ff 0x2aaaaca62afa
+     1:       16 [     1:       16] @ 0x2aaaabaf5ccc 0x2aaaabb04bac 0x2aaaabc1b262 0x2aaaabc21496 0x2aaaabc214bb
+[...]
+
+ + +

Older code may produce "version 1" heap profiles which look like this:

+

+heap profile:  14933: 791700132 [ 14933: 791700132] @ heap
+     1:   848688 [     1:   848688] @ 0xa4b142 0x7f5bfc 0x87065e 0x4056e9 0x4125f8 0x42b4f1 0x45b1ba 0x463248 0x460871 0x45cb7c 0x5f1744 0x607cee 0x5f4a5e 0x40080f 0x2aaaabad7afa
+     1:  1048576 [     1:  1048576] @ 0xa4a9b2 0x7fd025 0x4ca6d8 0x4ca814 0x4caa88 0x2aaaab104cf0 0x404e20 0x4125f8 0x42b4f1 0x45b1ba 0x463248 0x460871 0x45cb7c 0x5f1744 0x607cee 0x5f4a5e 0x40080f 0x2aaaabad7afa
+  2942: 388629374 [  2942: 388629374] @ 0xa4b142 0x4006a0 0x400bed 0x5f0cfa 0x5f1744 0x607cee 0x5f4a5e 0x40080f 0x2aaaabad7afa
+[...]
+
+

pprof accepts both old and new heap profiles and automatically +detects which one you are using.

+ +

/pprof/growth

+ +

pprof asks for the url /pprof/growth to +get heap-profiling delta (growth) information. The actual url is +controlled via the variable GROWTH_PAGE in the +pprof script, so you can change it if you'd like.

+ +

The server should respond by calling

+
+    MallocExtension::instance()->GetHeapGrowthStacks(&output);
+
+

and sending output back as an HTTP response to +pprof. MallocExtension is defined in the +header file gperftools/malloc_extension.h.

+ +

Here's an example, from an actual Google webserver, of what the +output should look like:

+
+heap profile:    741: 812122112 [   741: 812122112] @ growth
+     1:  1572864 [     1:  1572864] @ 0x87da564 0x87db8a3 0x84787a4 0x846e851 0x836d12f 0x834cd1c 0x8349ba5 0x10a3177 0x8349961
+     1:  1048576 [     1:  1048576] @ 0x87d92e8 0x87d9213 0x87d9178 0x87d94d3 0x87da9da 0x8a364ff 0x8a437e7 0x8ab7d23 0x8ab7da9 0x8ac7454 0x8348465 0x10a3161 0x8349961
+[...]
+
+ + +

/pprof/profile

+ +

pprof asks for the url +/pprof/profile?seconds=XX to get cpu-profiling +information. The actual url is controlled via the variable +PROFILE_PAGE in the pprof script, so you can +change it if you'd like.

+ +

The server should respond by calling +ProfilerStart(filename), continuing to do its work, and +then, XX seconds later, calling ProfilerStop(). (These +functions are declared in gperftools/profiler.h.) The +application is responsible for picking a unique filename for +ProfilerStart(). After calling +ProfilerStop(), the server should read the contents of +filename and send them back as an HTTP response to +pprof.

+ +

Obviously, to get useful profile information the application must +continue to run in the XX seconds that the profiler is running. Thus, +the profile start-stop calls should be done in a separate thread, or +be otherwise non-blocking.

+ +

The profiler output file is binary, but near the end of it, it +should have lines of text somewhat like this:

+
+01016000-01017000 rw-p 00015000 03:01 59314      /lib/ld-2.2.2.so
+
+ +

/pprof/pmuprofile

+ +pprof asks for a url of the form +/pprof/pmuprofile?event=hw_event:unit_mask&period=nnn&seconds=xxx +to get cpu-profiling information. The actual url is controlled via the variable +PMUPROFILE_PAGE in the pprof script, so you can +change it if you'd like.

+ +

+This is similar to pprof, but is meant to be used with your CPU's hardware +performance counters. The server could be implemented on top of a library +such as +libpfm. It should collect a sample every nnn occurrences +of the event and stop the sampling after xxx seconds. Much of the code +for /pprof/profile can be reused for this purpose. +

+ +

The server side routines (the equivalent of +ProfilerStart/ProfilerStart) are not available as part of perftools, +so this URL is unlikely to be that useful.

+ +

/pprof/contention

+ +

This is intended to be able to profile (thread) lock contention in +addition to CPU and memory use. It's not yet usable.

+ + +

/pprof/cmdline

+ +

pprof asks for the url /pprof/cmdline to +figure out what application it's profiling. The actual url is +controlled via the variable PROGRAM_NAME_PAGE in the +pprof script, so you can change it if you'd like.

+ +

The server should respond by reading the contents of +/proc/self/cmdline, converting all internal NUL (\0) +characters to newlines, and sending the result back as an HTTP +response to pprof.

+ +

Here's an example return value:

+

+/root/server/custom_webserver
+80
+--configfile=/root/server/ws.config
+
+ + +

/pprof/symbol

+ +

pprof asks for the url /pprof/symbol to +map from hex addresses to variable names. The actual url is +controlled via the variable SYMBOL_PAGE in the +pprof script, so you can change it if you'd like.

+ +

When the server receives a GET request for +/pprof/symbol, it should return a line formatted like +so:

+
+   num_symbols: ###
+
+

where ### is the number of symbols found in the +binary. (For now, the only important distinction is whether the value +is 0, which it is for executables that lack debug information, or +not-0).

+ +

This is perhaps the hardest request to write code for, because in +addition to the GET request for this url, the server must accept POST +requests. This means that after the HTTP headers, pprof will pass in +a list of hex addresses connected by +, like so:

+
+   curl -d '0x0824d061+0x0824d1cf' http://remote_host:80/pprof/symbol
+
+ +

The server should read the POST data, which will be in one line, +and for each hex value, should write one line of output to the output +stream, like so:

+
+<hex address><tab><function name>
+
+

For instance:

+
+0x08b2dabd    _Update
+
+ +

The other reason this is the most difficult request to implement, +is that the application will have to figure out for itself how to map +from address to function name. One possibility is to run nm -C +-n <program name> to get the mappings at +program-compile-time. Another, at least on Linux, is to call out to +addr2line for every pprof/symbol call, for instance +addr2line -Cfse /proc//exe 0x12345678 0x876543210 +(presumably with some caching!)

+ +

pprof itself does just this for local profiles (not +ones that talk to remote servers); look at the subroutine +GetProcedureBoundaries.

+ + +
+Last modified: Mon Jun 12 21:30:14 PDT 2006 + + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/spanmap.dot b/trunk/3rdparty/gperftools-2-fit/docs/spanmap.dot new file mode 100644 index 000000000..3cb42abe5 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/spanmap.dot @@ -0,0 +1,22 @@ +digraph SpanMap { +node [shape=box, width=0.3, height=0.3] +nodesep=.05 + +map [shape=record, width=6, label="||||||||||"] +S0 [label="a"] +S1 [label="b"] +S2 [label="c"] +S3 [label="d"] +map:f0 -> S0 +map:f1 -> S0 +map:f2 -> S1 +map:f3 -> S2 +map:f4 -> S2 +map:f5 -> S2 +map:f6 -> S2 +map:f7 -> S2 +map:f8 -> S3 +map:f9 -> S3 +map:f10 -> S3 + +} diff --git a/trunk/3rdparty/gperftools-2-fit/docs/spanmap.gif b/trunk/3rdparty/gperftools-2-fit/docs/spanmap.gif new file mode 100644 index 0000000000000000000000000000000000000000..a0627f6a71a0e2ad21b3043f9d5fc9047afd5fb4 GIT binary patch literal 8482 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/t-test1.times.txt b/trunk/3rdparty/gperftools-2-fit/docs/t-test1.times.txt new file mode 100644 index 000000000..016369385 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/t-test1.times.txt @@ -0,0 +1,480 @@ +time.1.ptmalloc.64:0.56 user 0.02 system 0.57 elapsed 100% CPU +time.1.tcmalloc.64:0.38 user 0.02 system 0.40 elapsed 98% CPU +time.1.ptmalloc.128:0.61 user 0.01 system 0.61 elapsed 101% CPU +time.1.tcmalloc.128:0.35 user 0.00 system 0.35 elapsed 99% CPU +time.1.ptmalloc.256:0.59 user 0.01 system 0.60 elapsed 100% CPU +time.1.tcmalloc.256:0.27 user 0.02 system 0.28 elapsed 102% CPU +time.1.ptmalloc.512:0.57 user 0.00 system 0.57 elapsed 100% CPU +time.1.tcmalloc.512:0.25 user 0.01 system 0.25 elapsed 101% CPU +time.1.ptmalloc.1024:0.52 user 0.00 system 0.52 elapsed 99% CPU +time.1.tcmalloc.1024:0.22 user 0.02 system 0.24 elapsed 97% CPU +time.1.ptmalloc.2048:0.47 user 0.00 system 0.47 elapsed 99% CPU +time.1.tcmalloc.2048:0.22 user 0.02 system 0.25 elapsed 95% CPU +time.1.ptmalloc.4096:0.48 user 0.01 system 0.48 elapsed 100% CPU +time.1.tcmalloc.4096:0.25 user 0.01 system 0.25 elapsed 100% CPU +time.1.ptmalloc.8192:0.49 user 0.02 system 0.49 elapsed 102% CPU +time.1.tcmalloc.8192:0.27 user 0.02 system 0.28 elapsed 101% CPU +time.1.ptmalloc.16384:0.51 user 0.04 system 0.55 elapsed 99% CPU +time.1.tcmalloc.16384:0.35 user 0.02 system 0.37 elapsed 100% CPU +time.1.ptmalloc.32768:0.53 user 0.14 system 0.66 elapsed 100% CPU +time.1.tcmalloc.32768:0.67 user 0.02 system 0.69 elapsed 99% CPU +time.1.ptmalloc.65536:0.68 user 0.31 system 0.98 elapsed 100% CPU +time.1.tcmalloc.65536:0.71 user 0.01 system 0.72 elapsed 99% CPU +time.1.ptmalloc.131072:0.90 user 0.72 system 1.62 elapsed 99% CPU +time.1.tcmalloc.131072:0.94 user 0.03 system 0.97 elapsed 99% CPU +time.2.ptmalloc.64:1.05 user 0.00 system 0.53 elapsed 196% CPU +time.2.tcmalloc.64:0.66 user 0.03 system 0.37 elapsed 185% CPU +time.2.ptmalloc.128:1.77 user 0.01 system 0.89 elapsed 198% CPU +time.2.tcmalloc.128:0.53 user 0.01 system 0.29 elapsed 184% CPU +time.2.ptmalloc.256:1.14 user 0.01 system 0.62 elapsed 182% CPU +time.2.tcmalloc.256:0.45 user 0.02 system 0.26 elapsed 180% CPU +time.2.ptmalloc.512:1.26 user 0.40 system 1.79 elapsed 92% CPU +time.2.tcmalloc.512:0.43 user 0.02 system 0.27 elapsed 166% CPU +time.2.ptmalloc.1024:0.98 user 0.03 system 0.56 elapsed 179% CPU +time.2.tcmalloc.1024:0.44 user 0.02 system 0.34 elapsed 134% CPU +time.2.ptmalloc.2048:0.87 user 0.02 system 0.44 elapsed 199% CPU +time.2.tcmalloc.2048:0.49 user 0.02 system 0.34 elapsed 148% CPU +time.2.ptmalloc.4096:0.92 user 0.03 system 0.48 elapsed 196% CPU +time.2.tcmalloc.4096:0.50 user 0.02 system 0.49 elapsed 105% CPU +time.2.ptmalloc.8192:1.05 user 0.04 system 0.55 elapsed 196% CPU +time.2.tcmalloc.8192:0.59 user 0.01 system 0.51 elapsed 116% CPU +time.2.ptmalloc.16384:1.30 user 0.14 system 0.72 elapsed 198% CPU +time.2.tcmalloc.16384:0.63 user 0.03 system 0.68 elapsed 96% CPU +time.2.ptmalloc.32768:1.33 user 0.56 system 1.00 elapsed 189% CPU +time.2.tcmalloc.32768:1.16 user 0.01 system 1.17 elapsed 99% CPU +time.2.ptmalloc.65536:1.86 user 1.79 system 2.01 elapsed 181% CPU +time.2.tcmalloc.65536:1.35 user 0.01 system 1.35 elapsed 100% CPU +time.2.ptmalloc.131072:2.61 user 5.19 system 4.81 elapsed 162% CPU +time.2.tcmalloc.131072:1.86 user 0.04 system 1.90 elapsed 100% CPU +time.3.ptmalloc.64:1.79 user 0.03 system 0.67 elapsed 268% CPU +time.3.tcmalloc.64:1.58 user 0.04 system 0.62 elapsed 260% CPU +time.3.ptmalloc.128:2.77 user 1.34 system 3.07 elapsed 133% CPU +time.3.tcmalloc.128:1.19 user 0.01 system 0.50 elapsed 236% CPU +time.3.ptmalloc.256:2.14 user 0.02 system 0.85 elapsed 252% CPU +time.3.tcmalloc.256:0.96 user 0.01 system 0.41 elapsed 236% CPU +time.3.ptmalloc.512:3.37 user 1.31 system 3.33 elapsed 140% CPU +time.3.tcmalloc.512:0.93 user 0.04 system 0.39 elapsed 243% CPU +time.3.ptmalloc.1024:1.66 user 0.01 system 0.64 elapsed 260% CPU +time.3.tcmalloc.1024:0.81 user 0.02 system 0.44 elapsed 187% CPU +time.3.ptmalloc.2048:2.07 user 0.01 system 0.82 elapsed 252% CPU +time.3.tcmalloc.2048:1.10 user 0.04 system 0.59 elapsed 191% CPU +time.3.ptmalloc.4096:2.01 user 0.03 system 0.79 elapsed 258% CPU +time.3.tcmalloc.4096:0.87 user 0.03 system 0.65 elapsed 137% CPU +time.3.ptmalloc.8192:2.22 user 0.11 system 0.83 elapsed 280% CPU +time.3.tcmalloc.8192:0.96 user 0.06 system 0.75 elapsed 135% CPU +time.3.ptmalloc.16384:2.56 user 0.47 system 1.02 elapsed 295% CPU +time.3.tcmalloc.16384:0.99 user 0.04 system 1.03 elapsed 99% CPU +time.3.ptmalloc.32768:3.29 user 1.75 system 1.96 elapsed 256% CPU +time.3.tcmalloc.32768:1.67 user 0.02 system 1.69 elapsed 99% CPU +time.3.ptmalloc.65536:4.04 user 6.62 system 4.92 elapsed 216% CPU +time.3.tcmalloc.65536:1.91 user 0.02 system 1.98 elapsed 97% CPU +time.3.ptmalloc.131072:5.55 user 17.86 system 12.44 elapsed 188% CPU +time.3.tcmalloc.131072:2.78 user 0.02 system 2.82 elapsed 99% CPU +time.4.ptmalloc.64:3.42 user 1.36 system 3.20 elapsed 149% CPU +time.4.tcmalloc.64:2.42 user 0.02 system 0.71 elapsed 341% CPU +time.4.ptmalloc.128:3.98 user 1.79 system 3.89 elapsed 148% CPU +time.4.tcmalloc.128:1.87 user 0.02 system 0.58 elapsed 325% CPU +time.4.ptmalloc.256:4.06 user 2.14 system 4.12 elapsed 150% CPU +time.4.tcmalloc.256:1.69 user 0.02 system 0.51 elapsed 331% CPU +time.4.ptmalloc.512:4.48 user 2.15 system 4.39 elapsed 150% CPU +time.4.tcmalloc.512:1.62 user 0.03 system 0.52 elapsed 314% CPU +time.4.ptmalloc.1024:3.18 user 0.03 system 0.84 elapsed 381% CPU +time.4.tcmalloc.1024:1.53 user 0.02 system 0.56 elapsed 274% CPU +time.4.ptmalloc.2048:3.24 user 0.02 system 0.84 elapsed 384% CPU +time.4.tcmalloc.2048:1.44 user 0.04 system 0.66 elapsed 221% CPU +time.4.ptmalloc.4096:3.50 user 0.04 system 0.91 elapsed 389% CPU +time.4.tcmalloc.4096:1.31 user 0.01 system 0.89 elapsed 148% CPU +time.4.ptmalloc.8192:6.77 user 3.85 system 4.14 elapsed 256% CPU +time.4.tcmalloc.8192:1.20 user 0.05 system 0.97 elapsed 127% CPU +time.4.ptmalloc.16384:7.08 user 5.06 system 4.63 elapsed 262% CPU +time.4.tcmalloc.16384:1.27 user 0.03 system 1.25 elapsed 103% CPU +time.4.ptmalloc.32768:5.57 user 4.22 system 3.31 elapsed 295% CPU +time.4.tcmalloc.32768:2.17 user 0.03 system 2.25 elapsed 97% CPU +time.4.ptmalloc.65536:6.11 user 15.05 system 9.19 elapsed 230% CPU +time.4.tcmalloc.65536:2.51 user 0.02 system 2.57 elapsed 98% CPU +time.4.ptmalloc.131072:7.58 user 33.15 system 21.28 elapsed 191% CPU +time.4.tcmalloc.131072:3.57 user 0.07 system 3.66 elapsed 99% CPU +time.5.ptmalloc.64:4.44 user 2.08 system 4.37 elapsed 148% CPU +time.5.tcmalloc.64:2.87 user 0.02 system 0.79 elapsed 361% CPU +time.5.ptmalloc.128:4.77 user 2.77 system 5.14 elapsed 146% CPU +time.5.tcmalloc.128:2.65 user 0.03 system 0.72 elapsed 367% CPU +time.5.ptmalloc.256:5.82 user 2.88 system 5.49 elapsed 158% CPU +time.5.tcmalloc.256:2.33 user 0.01 system 0.66 elapsed 352% CPU +time.5.ptmalloc.512:6.27 user 3.11 system 5.34 elapsed 175% CPU +time.5.tcmalloc.512:2.14 user 0.03 system 0.70 elapsed 307% CPU +time.5.ptmalloc.1024:6.82 user 3.18 system 5.23 elapsed 191% CPU +time.5.tcmalloc.1024:2.20 user 0.02 system 0.70 elapsed 313% CPU +time.5.ptmalloc.2048:6.57 user 3.46 system 5.22 elapsed 192% CPU +time.5.tcmalloc.2048:2.15 user 0.03 system 0.82 elapsed 264% CPU +time.5.ptmalloc.4096:8.75 user 5.09 system 5.26 elapsed 263% CPU +time.5.tcmalloc.4096:1.68 user 0.03 system 1.08 elapsed 158% CPU +time.5.ptmalloc.8192:4.48 user 0.61 system 1.51 elapsed 335% CPU +time.5.tcmalloc.8192:1.47 user 0.07 system 1.18 elapsed 129% CPU +time.5.ptmalloc.16384:5.71 user 1.98 system 2.14 elapsed 358% CPU +time.5.tcmalloc.16384:1.58 user 0.03 system 1.52 elapsed 105% CPU +time.5.ptmalloc.32768:7.19 user 7.81 system 5.53 elapsed 270% CPU +time.5.tcmalloc.32768:2.63 user 0.05 system 2.72 elapsed 98% CPU +time.5.ptmalloc.65536:8.45 user 23.51 system 14.30 elapsed 223% CPU +time.5.tcmalloc.65536:3.12 user 0.05 system 3.21 elapsed 98% CPU +time.5.ptmalloc.131072:10.22 user 43.63 system 27.84 elapsed 193% CPU +time.5.tcmalloc.131072:4.42 user 0.07 system 4.51 elapsed 99% CPU +time.6.ptmalloc.64:5.57 user 2.56 system 5.08 elapsed 159% CPU +time.6.tcmalloc.64:3.20 user 0.01 system 0.89 elapsed 360% CPU +time.6.ptmalloc.128:5.98 user 3.52 system 5.71 elapsed 166% CPU +time.6.tcmalloc.128:2.76 user 0.02 system 0.78 elapsed 355% CPU +time.6.ptmalloc.256:4.61 user 0.02 system 1.19 elapsed 389% CPU +time.6.tcmalloc.256:2.65 user 0.02 system 0.74 elapsed 356% CPU +time.6.ptmalloc.512:8.28 user 3.88 system 6.61 elapsed 183% CPU +time.6.tcmalloc.512:2.60 user 0.02 system 0.72 elapsed 362% CPU +time.6.ptmalloc.1024:4.75 user 0.00 system 1.22 elapsed 387% CPU +time.6.tcmalloc.1024:2.56 user 0.02 system 0.79 elapsed 325% CPU +time.6.ptmalloc.2048:8.90 user 4.59 system 6.15 elapsed 219% CPU +time.6.tcmalloc.2048:2.37 user 0.06 system 0.96 elapsed 250% CPU +time.6.ptmalloc.4096:11.41 user 7.02 system 6.31 elapsed 291% CPU +time.6.tcmalloc.4096:1.82 user 0.03 system 1.19 elapsed 154% CPU +time.6.ptmalloc.8192:11.64 user 8.25 system 5.97 elapsed 332% CPU +time.6.tcmalloc.8192:1.83 user 0.07 system 1.38 elapsed 136% CPU +time.6.ptmalloc.16384:7.44 user 2.98 system 3.01 elapsed 345% CPU +time.6.tcmalloc.16384:1.83 user 0.08 system 1.80 elapsed 105% CPU +time.6.ptmalloc.32768:8.69 user 12.35 system 8.04 elapsed 261% CPU +time.6.tcmalloc.32768:3.14 user 0.06 system 3.24 elapsed 98% CPU +time.6.ptmalloc.65536:10.52 user 35.43 system 20.75 elapsed 221% CPU +time.6.tcmalloc.65536:3.62 user 0.03 system 3.72 elapsed 98% CPU +time.6.ptmalloc.131072:11.74 user 59.00 system 36.93 elapsed 191% CPU +time.6.tcmalloc.131072:5.33 user 0.04 system 5.42 elapsed 98% CPU +time.7.ptmalloc.64:6.60 user 3.45 system 6.01 elapsed 167% CPU +time.7.tcmalloc.64:3.50 user 0.04 system 0.94 elapsed 376% CPU +time.7.ptmalloc.128:7.09 user 4.25 system 6.69 elapsed 169% CPU +time.7.tcmalloc.128:3.13 user 0.03 system 0.84 elapsed 374% CPU +time.7.ptmalloc.256:9.28 user 4.85 system 7.20 elapsed 196% CPU +time.7.tcmalloc.256:3.06 user 0.02 system 0.82 elapsed 375% CPU +time.7.ptmalloc.512:9.13 user 4.78 system 6.79 elapsed 204% CPU +time.7.tcmalloc.512:2.99 user 0.03 system 0.83 elapsed 359% CPU +time.7.ptmalloc.1024:10.85 user 6.41 system 7.52 elapsed 229% CPU +time.7.tcmalloc.1024:3.05 user 0.04 system 0.89 elapsed 345% CPU +time.7.ptmalloc.2048:5.65 user 0.08 system 1.47 elapsed 388% CPU +time.7.tcmalloc.2048:3.01 user 0.01 system 0.98 elapsed 306% CPU +time.7.ptmalloc.4096:6.09 user 0.08 system 1.58 elapsed 389% CPU +time.7.tcmalloc.4096:2.25 user 0.03 system 1.32 elapsed 171% CPU +time.7.ptmalloc.8192:6.73 user 0.85 system 1.99 elapsed 379% CPU +time.7.tcmalloc.8192:2.22 user 0.08 system 1.61 elapsed 142% CPU +time.7.ptmalloc.16384:8.87 user 4.66 system 4.04 elapsed 334% CPU +time.7.tcmalloc.16384:2.07 user 0.07 system 2.07 elapsed 103% CPU +time.7.ptmalloc.32768:10.61 user 17.85 system 11.22 elapsed 253% CPU +time.7.tcmalloc.32768:3.68 user 0.06 system 3.79 elapsed 98% CPU +time.7.ptmalloc.65536:13.05 user 45.97 system 27.28 elapsed 216% CPU +time.7.tcmalloc.65536:4.16 user 0.07 system 4.31 elapsed 98% CPU +time.7.ptmalloc.131072:13.22 user 62.67 system 41.33 elapsed 183% CPU +time.7.tcmalloc.131072:6.10 user 0.06 system 6.25 elapsed 98% CPU +time.8.ptmalloc.64:7.31 user 3.92 system 6.39 elapsed 175% CPU +time.8.tcmalloc.64:4.00 user 0.01 system 1.04 elapsed 383% CPU +time.8.ptmalloc.128:9.40 user 5.41 system 7.67 elapsed 192% CPU +time.8.tcmalloc.128:3.61 user 0.02 system 0.94 elapsed 386% CPU +time.8.ptmalloc.256:10.61 user 6.35 system 7.96 elapsed 212% CPU +time.8.tcmalloc.256:3.30 user 0.02 system 0.99 elapsed 335% CPU +time.8.ptmalloc.512:12.42 user 7.10 system 8.79 elapsed 221% CPU +time.8.tcmalloc.512:3.35 user 0.04 system 0.94 elapsed 358% CPU +time.8.ptmalloc.1024:13.63 user 8.54 system 8.95 elapsed 247% CPU +time.8.tcmalloc.1024:3.44 user 0.02 system 0.96 elapsed 359% CPU +time.8.ptmalloc.2048:6.45 user 0.03 system 1.67 elapsed 386% CPU +time.8.tcmalloc.2048:3.55 user 0.05 system 1.09 elapsed 328% CPU +time.8.ptmalloc.4096:6.83 user 0.26 system 1.80 elapsed 393% CPU +time.8.tcmalloc.4096:2.78 user 0.06 system 1.53 elapsed 185% CPU +time.8.ptmalloc.8192:7.59 user 1.29 system 2.36 elapsed 376% CPU +time.8.tcmalloc.8192:2.57 user 0.07 system 1.84 elapsed 142% CPU +time.8.ptmalloc.16384:10.15 user 6.20 system 5.20 elapsed 314% CPU +time.8.tcmalloc.16384:2.40 user 0.05 system 2.42 elapsed 101% CPU +time.8.ptmalloc.32768:11.82 user 24.48 system 14.60 elapsed 248% CPU +time.8.tcmalloc.32768:4.37 user 0.05 system 4.47 elapsed 98% CPU +time.8.ptmalloc.65536:15.41 user 58.94 system 34.42 elapsed 215% CPU +time.8.tcmalloc.65536:4.90 user 0.04 system 4.96 elapsed 99% CPU +time.8.ptmalloc.131072:16.07 user 82.93 system 52.51 elapsed 188% CPU +time.8.tcmalloc.131072:7.13 user 0.04 system 7.19 elapsed 99% CPU +time.9.ptmalloc.64:8.44 user 4.59 system 6.92 elapsed 188% CPU +time.9.tcmalloc.64:4.00 user 0.02 system 1.05 elapsed 382% CPU +time.9.ptmalloc.128:10.92 user 6.14 system 8.31 elapsed 205% CPU +time.9.tcmalloc.128:3.88 user 0.02 system 1.01 elapsed 382% CPU +time.9.ptmalloc.256:13.01 user 7.75 system 9.12 elapsed 227% CPU +time.9.tcmalloc.256:3.89 user 0.01 system 1.00 elapsed 386% CPU +time.9.ptmalloc.512:14.96 user 8.89 system 9.73 elapsed 244% CPU +time.9.tcmalloc.512:3.80 user 0.03 system 1.01 elapsed 377% CPU +time.9.ptmalloc.1024:15.42 user 10.20 system 9.80 elapsed 261% CPU +time.9.tcmalloc.1024:3.86 user 0.03 system 1.19 elapsed 325% CPU +time.9.ptmalloc.2048:7.24 user 0.02 system 1.87 elapsed 388% CPU +time.9.tcmalloc.2048:3.98 user 0.05 system 1.26 elapsed 319% CPU +time.9.ptmalloc.4096:7.96 user 0.18 system 2.06 elapsed 394% CPU +time.9.tcmalloc.4096:3.27 user 0.04 system 1.69 elapsed 195% CPU +time.9.ptmalloc.8192:9.00 user 1.63 system 2.79 elapsed 380% CPU +time.9.tcmalloc.8192:3.00 user 0.06 system 2.05 elapsed 148% CPU +time.9.ptmalloc.16384:12.07 user 8.13 system 6.55 elapsed 308% CPU +time.9.tcmalloc.16384:2.85 user 0.05 system 2.75 elapsed 105% CPU +time.9.ptmalloc.32768:13.99 user 29.65 system 18.02 elapsed 242% CPU +time.9.tcmalloc.32768:4.98 user 0.06 system 5.13 elapsed 98% CPU +time.9.ptmalloc.65536:16.89 user 70.42 system 42.11 elapsed 207% CPU +time.9.tcmalloc.65536:5.55 user 0.04 system 5.65 elapsed 98% CPU +time.9.ptmalloc.131072:18.53 user 94.11 system 61.17 elapsed 184% CPU +time.9.tcmalloc.131072:8.06 user 0.04 system 8.16 elapsed 99% CPU +time.10.ptmalloc.64:9.81 user 5.70 system 7.42 elapsed 208% CPU +time.10.tcmalloc.64:4.43 user 0.03 system 1.20 elapsed 370% CPU +time.10.ptmalloc.128:12.69 user 7.81 system 9.02 elapsed 227% CPU +time.10.tcmalloc.128:4.27 user 0.02 system 1.13 elapsed 378% CPU +time.10.ptmalloc.256:15.04 user 9.53 system 9.92 elapsed 247% CPU +time.10.tcmalloc.256:4.23 user 0.02 system 1.09 elapsed 388% CPU +time.10.ptmalloc.512:17.30 user 10.46 system 10.61 elapsed 261% CPU +time.10.tcmalloc.512:4.14 user 0.05 system 1.10 elapsed 379% CPU +time.10.ptmalloc.1024:16.96 user 9.38 system 9.30 elapsed 283% CPU +time.10.tcmalloc.1024:4.27 user 0.06 system 1.18 elapsed 366% CPU +time.10.ptmalloc.2048:8.07 user 0.03 system 2.06 elapsed 393% CPU +time.10.tcmalloc.2048:4.49 user 0.07 system 1.33 elapsed 342% CPU +time.10.ptmalloc.4096:8.66 user 0.25 system 2.25 elapsed 394% CPU +time.10.tcmalloc.4096:3.61 user 0.05 system 1.78 elapsed 205% CPU +time.10.ptmalloc.8192:21.52 user 17.43 system 10.41 elapsed 374% CPU +time.10.tcmalloc.8192:3.59 user 0.10 system 2.33 elapsed 158% CPU +time.10.ptmalloc.16384:20.55 user 24.85 system 12.55 elapsed 361% CPU +time.10.tcmalloc.16384:3.29 user 0.04 system 3.22 elapsed 103% CPU +time.10.ptmalloc.32768:15.23 user 38.13 system 22.49 elapsed 237% CPU +time.10.tcmalloc.32768:5.62 user 0.05 system 5.72 elapsed 99% CPU +time.10.ptmalloc.65536:19.80 user 85.42 system 49.98 elapsed 210% CPU +time.10.tcmalloc.65536:6.23 user 0.09 system 6.36 elapsed 99% CPU +time.10.ptmalloc.131072:20.91 user 106.97 system 69.08 elapsed 185% CPU +time.10.tcmalloc.131072:8.94 user 0.09 system 9.09 elapsed 99% CPU +time.11.ptmalloc.64:10.82 user 6.34 system 7.92 elapsed 216% CPU +time.11.tcmalloc.64:4.80 user 0.03 system 1.24 elapsed 387% CPU +time.11.ptmalloc.128:14.58 user 8.61 system 9.81 elapsed 236% CPU +time.11.tcmalloc.128:4.65 user 0.03 system 1.21 elapsed 384% CPU +time.11.ptmalloc.256:17.38 user 10.98 system 10.75 elapsed 263% CPU +time.11.tcmalloc.256:4.51 user 0.03 system 1.18 elapsed 384% CPU +time.11.ptmalloc.512:19.18 user 11.71 system 10.95 elapsed 282% CPU +time.11.tcmalloc.512:4.57 user 0.02 system 1.19 elapsed 384% CPU +time.11.ptmalloc.1024:19.94 user 12.41 system 10.48 elapsed 308% CPU +time.11.tcmalloc.1024:4.71 user 0.05 system 1.29 elapsed 367% CPU +time.11.ptmalloc.2048:8.70 user 0.04 system 2.35 elapsed 371% CPU +time.11.tcmalloc.2048:4.97 user 0.07 system 1.43 elapsed 350% CPU +time.11.ptmalloc.4096:22.47 user 18.43 system 10.82 elapsed 377% CPU +time.11.tcmalloc.4096:4.22 user 0.03 system 1.91 elapsed 221% CPU +time.11.ptmalloc.8192:11.61 user 2.38 system 3.73 elapsed 374% CPU +time.11.tcmalloc.8192:3.74 user 0.09 system 2.46 elapsed 155% CPU +time.11.ptmalloc.16384:14.13 user 13.38 system 9.60 elapsed 286% CPU +time.11.tcmalloc.16384:3.61 user 0.03 system 3.63 elapsed 100% CPU +time.11.ptmalloc.32768:17.92 user 43.84 system 26.74 elapsed 230% CPU +time.11.tcmalloc.32768:6.31 user 0.03 system 6.45 elapsed 98% CPU +time.11.ptmalloc.65536:22.40 user 96.38 system 58.30 elapsed 203% CPU +time.11.tcmalloc.65536:6.92 user 0.12 system 6.98 elapsed 100% CPU +time.11.ptmalloc.131072:21.03 user 108.04 system 72.78 elapsed 177% CPU +time.11.tcmalloc.131072:9.79 user 0.08 system 9.94 elapsed 99% CPU +time.12.ptmalloc.64:12.23 user 7.16 system 8.38 elapsed 231% CPU +time.12.tcmalloc.64:5.21 user 0.05 system 1.41 elapsed 371% CPU +time.12.ptmalloc.128:16.97 user 10.19 system 10.47 elapsed 259% CPU +time.12.tcmalloc.128:5.10 user 0.02 system 1.31 elapsed 390% CPU +time.12.ptmalloc.256:19.99 user 12.10 system 11.57 elapsed 277% CPU +time.12.tcmalloc.256:5.01 user 0.03 system 1.29 elapsed 390% CPU +time.12.ptmalloc.512:21.85 user 12.66 system 11.46 elapsed 300% CPU +time.12.tcmalloc.512:5.05 user 0.00 system 1.32 elapsed 379% CPU +time.12.ptmalloc.1024:9.40 user 0.04 system 2.40 elapsed 393% CPU +time.12.tcmalloc.1024:5.14 user 0.02 system 1.39 elapsed 369% CPU +time.12.ptmalloc.2048:9.72 user 0.04 system 2.49 elapsed 391% CPU +time.12.tcmalloc.2048:5.74 user 0.05 system 1.62 elapsed 355% CPU +time.12.ptmalloc.4096:10.64 user 0.20 system 2.75 elapsed 393% CPU +time.12.tcmalloc.4096:4.45 user 0.03 system 2.04 elapsed 218% CPU +time.12.ptmalloc.8192:12.66 user 3.30 system 4.30 elapsed 371% CPU +time.12.tcmalloc.8192:4.21 user 0.13 system 2.65 elapsed 163% CPU +time.12.ptmalloc.16384:15.73 user 15.68 system 11.14 elapsed 281% CPU +time.12.tcmalloc.16384:4.17 user 0.06 system 4.10 elapsed 102% CPU +time.12.ptmalloc.32768:19.45 user 56.00 system 32.74 elapsed 230% CPU +time.12.tcmalloc.32768:6.96 user 0.08 system 7.14 elapsed 98% CPU +time.12.ptmalloc.65536:23.33 user 110.45 system 65.06 elapsed 205% CPU +time.12.tcmalloc.65536:7.77 user 0.15 system 7.72 elapsed 102% CPU +time.12.ptmalloc.131072:24.03 user 124.74 system 82.94 elapsed 179% CPU +time.12.tcmalloc.131072:10.81 user 0.06 system 10.94 elapsed 99% CPU +time.13.ptmalloc.64:14.08 user 7.60 system 8.85 elapsed 244% CPU +time.13.tcmalloc.64:5.51 user 0.01 system 1.47 elapsed 375% CPU +time.13.ptmalloc.128:18.20 user 10.98 system 10.99 elapsed 265% CPU +time.13.tcmalloc.128:5.34 user 0.01 system 1.39 elapsed 382% CPU +time.13.ptmalloc.256:21.48 user 13.94 system 12.25 elapsed 289% CPU +time.13.tcmalloc.256:5.33 user 0.01 system 1.39 elapsed 381% CPU +time.13.ptmalloc.512:24.22 user 14.84 system 12.97 elapsed 301% CPU +time.13.tcmalloc.512:5.49 user 0.02 system 1.41 elapsed 389% CPU +time.13.ptmalloc.1024:25.26 user 17.03 system 12.85 elapsed 328% CPU +time.13.tcmalloc.1024:5.65 user 0.04 system 1.50 elapsed 378% CPU +time.13.ptmalloc.2048:10.41 user 0.03 system 2.69 elapsed 387% CPU +time.13.tcmalloc.2048:5.93 user 0.10 system 1.77 elapsed 339% CPU +time.13.ptmalloc.4096:11.37 user 0.52 system 3.04 elapsed 391% CPU +time.13.tcmalloc.4096:5.08 user 0.11 system 2.22 elapsed 233% CPU +time.13.ptmalloc.8192:21.76 user 18.54 system 10.58 elapsed 380% CPU +time.13.tcmalloc.8192:5.04 user 0.16 system 2.93 elapsed 177% CPU +time.13.ptmalloc.16384:26.35 user 34.47 system 17.01 elapsed 357% CPU +time.13.tcmalloc.16384:4.66 user 0.04 system 4.66 elapsed 100% CPU +time.13.ptmalloc.32768:21.41 user 63.59 system 38.14 elapsed 222% CPU +time.13.tcmalloc.32768:7.71 user 0.03 system 7.83 elapsed 98% CPU +time.13.ptmalloc.65536:24.99 user 120.80 system 71.59 elapsed 203% CPU +time.13.tcmalloc.65536:8.87 user 0.64 system 8.37 elapsed 113% CPU +time.13.ptmalloc.131072:25.97 user 142.27 system 96.00 elapsed 175% CPU +time.13.tcmalloc.131072:11.48 user 0.06 system 11.67 elapsed 98% CPU +time.14.ptmalloc.64:15.01 user 9.11 system 9.41 elapsed 256% CPU +time.14.tcmalloc.64:5.98 user 0.02 system 1.58 elapsed 378% CPU +time.14.ptmalloc.128:20.34 user 12.72 system 11.62 elapsed 284% CPU +time.14.tcmalloc.128:5.88 user 0.04 system 1.51 elapsed 392% CPU +time.14.ptmalloc.256:24.26 user 14.95 system 12.92 elapsed 303% CPU +time.14.tcmalloc.256:5.72 user 0.02 system 1.50 elapsed 381% CPU +time.14.ptmalloc.512:27.28 user 16.45 system 13.89 elapsed 314% CPU +time.14.tcmalloc.512:5.99 user 0.02 system 1.54 elapsed 388% CPU +time.14.ptmalloc.1024:25.84 user 16.99 system 12.61 elapsed 339% CPU +time.14.tcmalloc.1024:5.94 user 0.06 system 1.59 elapsed 375% CPU +time.14.ptmalloc.2048:11.96 user 0.01 system 3.12 elapsed 382% CPU +time.14.tcmalloc.2048:6.39 user 0.07 system 1.79 elapsed 359% CPU +time.14.ptmalloc.4096:20.19 user 11.77 system 8.26 elapsed 386% CPU +time.14.tcmalloc.4096:5.65 user 0.05 system 2.32 elapsed 244% CPU +time.14.ptmalloc.8192:22.01 user 16.39 system 9.89 elapsed 387% CPU +time.14.tcmalloc.8192:5.44 user 0.11 system 3.07 elapsed 180% CPU +time.14.ptmalloc.16384:18.15 user 22.40 system 15.02 elapsed 269% CPU +time.14.tcmalloc.16384:5.29 user 0.08 system 5.34 elapsed 100% CPU +time.14.ptmalloc.32768:24.29 user 72.07 system 42.63 elapsed 225% CPU +time.14.tcmalloc.32768:8.47 user 0.02 system 8.62 elapsed 98% CPU +time.14.ptmalloc.65536:27.63 user 130.56 system 78.64 elapsed 201% CPU +time.14.tcmalloc.65536:9.85 user 1.61 system 9.04 elapsed 126% CPU +time.14.ptmalloc.131072:28.87 user 146.38 system 100.54 elapsed 174% CPU +time.14.tcmalloc.131072:12.46 user 0.11 system 12.71 elapsed 98% CPU +time.15.ptmalloc.64:16.25 user 10.05 system 9.82 elapsed 267% CPU +time.15.tcmalloc.64:6.30 user 0.02 system 1.64 elapsed 385% CPU +time.15.ptmalloc.128:22.33 user 13.23 system 12.24 elapsed 290% CPU +time.15.tcmalloc.128:6.08 user 0.03 system 1.59 elapsed 384% CPU +time.15.ptmalloc.256:26.56 user 16.57 system 13.70 elapsed 314% CPU +time.15.tcmalloc.256:6.14 user 0.03 system 1.61 elapsed 382% CPU +time.15.ptmalloc.512:29.68 user 18.08 system 14.56 elapsed 327% CPU +time.15.tcmalloc.512:6.12 user 0.04 system 1.68 elapsed 364% CPU +time.15.ptmalloc.1024:17.07 user 6.22 system 6.26 elapsed 371% CPU +time.15.tcmalloc.1024:6.38 user 0.02 system 1.75 elapsed 364% CPU +time.15.ptmalloc.2048:26.64 user 17.25 system 11.51 elapsed 381% CPU +time.15.tcmalloc.2048:6.77 user 0.18 system 1.92 elapsed 361% CPU +time.15.ptmalloc.4096:13.21 user 0.74 system 3.57 elapsed 390% CPU +time.15.tcmalloc.4096:6.03 user 0.09 system 2.36 elapsed 258% CPU +time.15.ptmalloc.8192:22.92 user 17.51 system 10.50 elapsed 385% CPU +time.15.tcmalloc.8192:5.96 user 0.12 system 3.36 elapsed 180% CPU +time.15.ptmalloc.16384:19.37 user 24.87 system 16.69 elapsed 264% CPU +time.15.tcmalloc.16384:5.88 user 0.07 system 5.84 elapsed 101% CPU +time.15.ptmalloc.32768:25.43 user 82.30 system 48.98 elapsed 219% CPU +time.15.tcmalloc.32768:9.11 user 0.05 system 9.30 elapsed 98% CPU +time.15.ptmalloc.65536:29.31 user 140.07 system 83.78 elapsed 202% CPU +time.15.tcmalloc.65536:8.51 user 1.59 system 9.75 elapsed 103% CPU +time.15.ptmalloc.131072:30.22 user 163.15 system 109.50 elapsed 176% CPU +time.15.tcmalloc.131072:13.35 user 0.10 system 13.54 elapsed 99% CPU +time.16.ptmalloc.64:17.69 user 10.11 system 10.11 elapsed 274% CPU +time.16.tcmalloc.64:6.63 user 0.04 system 1.72 elapsed 387% CPU +time.16.ptmalloc.128:23.05 user 14.37 system 12.75 elapsed 293% CPU +time.16.tcmalloc.128:6.61 user 0.02 system 1.71 elapsed 387% CPU +time.16.ptmalloc.256:29.11 user 19.35 system 14.57 elapsed 332% CPU +time.16.tcmalloc.256:6.62 user 0.03 system 1.73 elapsed 382% CPU +time.16.ptmalloc.512:31.65 user 18.71 system 14.71 elapsed 342% CPU +time.16.tcmalloc.512:6.63 user 0.04 system 1.73 elapsed 383% CPU +time.16.ptmalloc.1024:31.99 user 21.22 system 14.87 elapsed 357% CPU +time.16.tcmalloc.1024:6.81 user 0.04 system 1.79 elapsed 382% CPU +time.16.ptmalloc.2048:30.35 user 21.36 system 13.30 elapsed 388% CPU +time.16.tcmalloc.2048:6.91 user 0.50 system 2.01 elapsed 367% CPU +time.16.ptmalloc.4096:18.85 user 7.18 system 6.61 elapsed 393% CPU +time.16.tcmalloc.4096:6.70 user 0.10 system 2.62 elapsed 259% CPU +time.16.ptmalloc.8192:22.19 user 14.30 system 9.37 elapsed 389% CPU +time.16.tcmalloc.8192:6.18 user 0.19 system 3.58 elapsed 177% CPU +time.16.ptmalloc.16384:31.22 user 46.78 system 22.92 elapsed 340% CPU +time.16.tcmalloc.16384:6.79 user 0.07 system 6.86 elapsed 99% CPU +time.16.ptmalloc.32768:27.31 user 87.32 system 52.00 elapsed 220% CPU +time.16.tcmalloc.32768:9.85 user 0.06 system 10.07 elapsed 98% CPU +time.16.ptmalloc.65536:32.83 user 160.62 system 95.67 elapsed 202% CPU +time.16.tcmalloc.65536:10.18 user 0.09 system 10.41 elapsed 98% CPU +time.16.ptmalloc.131072:31.99 user 173.41 system 115.98 elapsed 177% CPU +time.16.tcmalloc.131072:14.52 user 0.05 system 14.67 elapsed 99% CPU +time.17.ptmalloc.64:19.38 user 11.61 system 10.61 elapsed 291% CPU +time.17.tcmalloc.64:7.11 user 0.02 system 1.84 elapsed 386% CPU +time.17.ptmalloc.128:26.25 user 16.15 system 13.53 elapsed 313% CPU +time.17.tcmalloc.128:6.97 user 0.02 system 1.78 elapsed 390% CPU +time.17.ptmalloc.256:30.66 user 18.36 system 14.97 elapsed 327% CPU +time.17.tcmalloc.256:6.94 user 0.04 system 1.80 elapsed 387% CPU +time.17.ptmalloc.512:33.71 user 22.79 system 15.95 elapsed 354% CPU +time.17.tcmalloc.512:7.00 user 0.02 system 1.83 elapsed 381% CPU +time.17.ptmalloc.1024:33.49 user 22.47 system 15.00 elapsed 373% CPU +time.17.tcmalloc.1024:7.20 user 0.03 system 1.90 elapsed 380% CPU +time.17.ptmalloc.2048:23.87 user 11.92 system 9.26 elapsed 386% CPU +time.17.tcmalloc.2048:6.01 user 1.83 system 2.15 elapsed 363% CPU +time.17.ptmalloc.4096:14.69 user 0.95 system 3.98 elapsed 392% CPU +time.17.tcmalloc.4096:7.25 user 0.10 system 2.62 elapsed 279% CPU +time.17.ptmalloc.8192:22.44 user 13.52 system 9.39 elapsed 382% CPU +time.17.tcmalloc.8192:7.21 user 0.24 system 3.95 elapsed 188% CPU +time.17.ptmalloc.16384:23.33 user 33.67 system 21.89 elapsed 260% CPU +time.17.tcmalloc.16384:7.28 user 0.06 system 7.10 elapsed 103% CPU +time.17.ptmalloc.32768:29.35 user 103.11 system 60.36 elapsed 219% CPU +time.17.tcmalloc.32768:10.53 user 0.07 system 10.71 elapsed 98% CPU +time.17.ptmalloc.65536:33.21 user 170.89 system 100.84 elapsed 202% CPU +time.17.tcmalloc.65536:10.85 user 0.05 system 11.04 elapsed 98% CPU +time.17.ptmalloc.131072:34.98 user 182.87 system 122.05 elapsed 178% CPU +time.17.tcmalloc.131072:15.27 user 0.09 system 15.49 elapsed 99% CPU +time.18.ptmalloc.64:21.08 user 12.15 system 11.43 elapsed 290% CPU +time.18.tcmalloc.64:7.45 user 0.03 system 1.95 elapsed 383% CPU +time.18.ptmalloc.128:27.65 user 17.26 system 14.03 elapsed 320% CPU +time.18.tcmalloc.128:7.46 user 0.03 system 1.92 elapsed 389% CPU +time.18.ptmalloc.256:32.78 user 20.55 system 15.70 elapsed 339% CPU +time.18.tcmalloc.256:7.31 user 0.02 system 1.88 elapsed 389% CPU +time.18.ptmalloc.512:33.31 user 20.06 system 15.05 elapsed 354% CPU +time.18.tcmalloc.512:7.33 user 0.02 system 1.91 elapsed 383% CPU +time.18.ptmalloc.1024:35.46 user 24.83 system 16.30 elapsed 369% CPU +time.18.tcmalloc.1024:7.60 user 0.06 system 2.05 elapsed 373% CPU +time.18.ptmalloc.2048:19.98 user 6.80 system 6.76 elapsed 395% CPU +time.18.tcmalloc.2048:6.89 user 1.29 system 2.28 elapsed 357% CPU +time.18.ptmalloc.4096:15.99 user 0.93 system 4.32 elapsed 391% CPU +time.18.tcmalloc.4096:7.70 user 0.10 system 2.77 elapsed 280% CPU +time.18.ptmalloc.8192:23.51 user 14.84 system 9.97 elapsed 384% CPU +time.18.tcmalloc.8192:8.16 user 0.27 system 4.25 elapsed 197% CPU +time.18.ptmalloc.16384:35.79 user 52.41 system 26.47 elapsed 333% CPU +time.18.tcmalloc.16384:7.81 user 0.07 system 7.61 elapsed 103% CPU +time.18.ptmalloc.32768:33.17 user 116.07 system 68.64 elapsed 217% CPU +time.18.tcmalloc.32768:11.34 user 0.13 system 11.57 elapsed 99% CPU +time.18.ptmalloc.65536:35.91 user 177.82 system 106.75 elapsed 200% CPU +time.18.tcmalloc.65536:11.54 user 0.06 system 11.74 elapsed 98% CPU +time.18.ptmalloc.131072:36.38 user 187.18 system 126.91 elapsed 176% CPU +time.18.tcmalloc.131072:16.34 user 0.05 system 16.43 elapsed 99% CPU +time.19.ptmalloc.64:22.90 user 13.23 system 11.82 elapsed 305% CPU +time.19.tcmalloc.64:7.81 user 0.02 system 2.01 elapsed 388% CPU +time.19.ptmalloc.128:30.13 user 18.58 system 14.77 elapsed 329% CPU +time.19.tcmalloc.128:7.74 user 0.02 system 2.01 elapsed 386% CPU +time.19.ptmalloc.256:35.33 user 21.41 system 16.35 elapsed 347% CPU +time.19.tcmalloc.256:7.79 user 0.04 system 2.04 elapsed 382% CPU +time.19.ptmalloc.512:39.30 user 26.22 system 17.84 elapsed 367% CPU +time.19.tcmalloc.512:7.80 user 0.06 system 2.05 elapsed 381% CPU +time.19.ptmalloc.1024:35.70 user 23.90 system 15.66 elapsed 380% CPU +time.19.tcmalloc.1024:8.08 user 0.06 system 2.16 elapsed 376% CPU +time.19.ptmalloc.2048:18.33 user 3.28 system 5.47 elapsed 394% CPU +time.19.tcmalloc.2048:8.71 user 0.05 system 2.40 elapsed 363% CPU +time.19.ptmalloc.4096:16.94 user 0.89 system 4.64 elapsed 383% CPU +time.19.tcmalloc.4096:8.21 user 0.07 system 2.85 elapsed 289% CPU +time.19.ptmalloc.8192:25.61 user 17.15 system 11.33 elapsed 377% CPU +time.19.tcmalloc.8192:8.79 user 0.30 system 4.58 elapsed 198% CPU +time.19.ptmalloc.16384:27.11 user 46.66 system 29.67 elapsed 248% CPU +time.19.tcmalloc.16384:8.64 user 0.05 system 8.58 elapsed 101% CPU +time.19.ptmalloc.32768:33.80 user 117.69 system 70.65 elapsed 214% CPU +time.19.tcmalloc.32768:11.88 user 0.07 system 12.04 elapsed 99% CPU +time.19.ptmalloc.65536:36.90 user 180.21 system 109.01 elapsed 199% CPU +time.19.tcmalloc.65536:12.17 user 0.07 system 12.40 elapsed 98% CPU +time.19.ptmalloc.131072:38.50 user 195.15 system 132.81 elapsed 175% CPU +time.19.tcmalloc.131072:17.44 user 0.10 system 17.65 elapsed 99% CPU +time.20.ptmalloc.64:23.37 user 13.74 system 11.86 elapsed 312% CPU +time.20.tcmalloc.64:8.18 user 0.02 system 2.10 elapsed 389% CPU +time.20.ptmalloc.128:31.29 user 19.97 system 15.53 elapsed 329% CPU +time.20.tcmalloc.128:8.03 user 0.02 system 2.12 elapsed 378% CPU +time.20.ptmalloc.256:38.40 user 25.65 system 18.25 elapsed 350% CPU +time.20.tcmalloc.256:8.05 user 0.05 system 2.12 elapsed 380% CPU +time.20.ptmalloc.512:40.60 user 27.70 system 18.46 elapsed 369% CPU +time.20.tcmalloc.512:8.22 user 0.08 system 2.20 elapsed 375% CPU +time.20.ptmalloc.1024:40.02 user 28.52 system 17.56 elapsed 390% CPU +time.20.tcmalloc.1024:8.50 user 0.07 system 2.19 elapsed 391% CPU +time.20.ptmalloc.2048:16.13 user 0.23 system 4.23 elapsed 386% CPU +time.20.tcmalloc.2048:8.98 user 0.03 system 2.45 elapsed 367% CPU +time.20.ptmalloc.4096:17.14 user 0.87 system 4.60 elapsed 391% CPU +time.20.tcmalloc.4096:8.93 user 0.20 system 2.97 elapsed 306% CPU +time.20.ptmalloc.8192:25.24 user 17.16 system 11.14 elapsed 380% CPU +time.20.tcmalloc.8192:9.78 user 0.30 system 5.14 elapsed 195% CPU +time.20.ptmalloc.16384:39.93 user 60.36 system 30.24 elapsed 331% CPU +time.20.tcmalloc.16384:9.57 user 0.09 system 9.43 elapsed 102% CPU +time.20.ptmalloc.32768:36.44 user 130.23 system 76.79 elapsed 217% CPU +time.20.tcmalloc.32768:12.71 user 0.09 system 12.97 elapsed 98% CPU +time.20.ptmalloc.65536:39.79 user 202.09 system 120.34 elapsed 200% CPU +time.20.tcmalloc.65536:12.93 user 0.06 system 13.15 elapsed 98% CPU +time.20.ptmalloc.131072:41.91 user 202.76 system 138.51 elapsed 176% CPU +time.20.tcmalloc.131072:18.23 user 0.07 system 18.42 elapsed 99% CPU diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..8c0ae6b59c2950c54db6f0c4f9b7fd585bcfdb71 GIT binary patch literal 1882 zcmV-g2c`IlP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3i*hxe|RCt{2o6m3CHWbG_1VwMleJiSeVA#$>h6(#4jNX>NVEu7v zvSup_6j*P`A5fsVH^X}9AqBFQ3wH3SFoqq1p>UWXK#SIBxPzL^kphPe`bMN&o z1w6Xef;IWW@|*4E>U#gny?xkiw#3WU?X~$5@MarAxw3gP46a}4MNtcOe_0UETfz0R zHeLF?!sAfE?rYGBZ4s1!S6guB;#bR^ zUSl;lUe;|~yWokJe}}6jiW5>aeu4__bHPG71K&9?o-Zvn0c0zBOb~)j%`KhJz{I~O z+{moz$#9r*KB+1f1dj_&EAW4U4#@$GKVFcBFBl*^{>$$r#d@w__faowtZ7&849b;o zYw1|q%|~uv?~w)tL-E-rD!RAv$-<*+``AWs1as-b1mg>z@=PuczE4fg8N892oGa+v zNKCGK|Ni|AClFRrlXF#smDJ?i!84Qlz(K_YA8^4-T<{Af*l#kyLx---flV&x_jq6* znBZY?hCl-2CKHT&mzPKb>`EpW2>`(XQH}*-k~0UDGpM-W`T!iCv6q93OfXg*KRu+S z_H21xZ*Cj*;V)Y=u? z$l~Ofq!S2iaD6ZfAcKQhK*Lm24vJv5(G4_u)dk!H<319-Rn|GD2@<_k0zTt{x$ulHTF+qS;QExcd- zn%C~vY62BCd(O5{BH`ROdbgMTXh8ftAHm!rB;n$ujj7@|xYLPaPjx=Y6hY^I8!fU! z*2V((YF^8sO4dew=ofpq2>yYaxm>yK7-t9DxXBO8f`7My>5ZP6tRN+w5-7N!d_<067F?~qQQG4Ei9yV=2Kw=k(0KyU)t@l_LaQrs~>=>p#3DuMwj zF6g9a-VW*oPS&d?=oDUKE1GR|ijo0WF$W4dIQ~vfR}>~F9l-TU6cruhw-HRxC7zQ5 z*@`Z)j%pOyAq%!5JJw-KiUbOhEKSieQMZ5+(n(nbikl=*=}%8qqqsx@lNar36l06w zTR_YOsuIP>V)zyi>!nKlKnBXGiWUpZKz{^AW!IrA_NFMx(JTN<$uiHA%>t$?hL$Ih zt*W||DD^y~xm93!64?v@X9Hx#sg@I1oQ@5|Fi5G>At@@NVu0ovT@=+&D>vFFfkj1S z9#9nrHg9y#WKb3^kgEelQI5VIv6I1_@e_GlnhZvZ$*vCBdN>z_E8PzBKDVJ3eL z^_U?0pR;k33qD}}J2<`q?rG3QCP-Y%w}71V-hq9gH*YYPyi+BA+4A%!#K5G&oRqrv z@dwTk7Ta&6U=lJoz}z8j@F=-QFEA8(4|Be+FOOG!i^W=78R$c5QOQE7$iVO+q*LZ6 zsE8IAAs9VO!LH1zic1PGKdkCTR@KJ{c7|2mNWr%VCib(9o28-RUA@`GQ@?tsC{jgr z*KA`j?3@v}m4Qj;jKD3kSNDeCT2|G4?A2AQxu?PYvd$c1Rks`OpXHo^vjSt;LAN={ z15N{@fCcuw=;fb{wa-0<;`66l|32j?9;n+t9rz5z10}CF6$@CW~x&QzG literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..24b2a27410fdd5b14b0b59ab74eaef125e097108 GIT binary patch literal 1731 zcmV;!20ZzRP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3iK}keGRCt{2oK0&RM;OOdObN6k`T%v=V=tx0P{={_3p6L;Lrc|D zkA1n=ZcM!?f#w!}fIxgL_Q8ix5|ERL$w7w_d?+E5;Es!+A-HHAg1fS%-KR6NGpm)f zFY`Q-*Kw;c8jqL#?f;pXXWmz?05Mc%;0!!#a7lb#zYx)?{EGtwuiD^>pCa%B@#*;@ zGPfRg_N>5#_j$MHx7Oz8yD#DKolCVK+=Ea5o?mv0zz%~Izq#bC`dX?3XX*t_{M=@l?sv-9U=(cVFed17*KXGvR?vV z#`Hi&IoFk`R1h30n0Lczf{1_s!%J6~8W^x3Jovq)1_tP1!IS%PU;sEmgG>$#UEw!x z;lSQ~IWQ0upWl;;_&h$ma$gP%VD3NldOSy9IR75aZDpHac427_K%U`vBNEC>b+$^sv2(8q$z zfQVhTA<)BuoC@AB;MlHx0jLu~xh&9l4#R@RSD7l`GC>y$nmoFQF(6s0A!hKH4Agy2 zka9GU4>r#V>|w^`WOd*{o$$*8ccWeF$XX1z8SRsM1Q5vJx>yBpy_0PdqE$dEQpAAq zx7$pL{Vw6w?!%!fHxIvW< z@;4lW0chQ^P6W!fkO*rkF;ZvM@2Xpev= zc`65Siox5-wUr1#hN2o99?3|mz~`0r=yIN=gVK`l-MLUMP6O!9ja5fhgOqz=fBOB4 z?)6IbWdA}V0+$kCdh-b1c?1s~!B^a^!-^y9Ql;9<1?3cPCxE$6KotRx3UCY@byn3; z|11pcS7G!3dI%i$IR*#)=nNmAG4eo>$3*KG8Iv3Pl{ulf6+L7OOqw_}LWULRAY&Rk z1`Z87-9}~u9S4&ZwT8{h2l?Q4zn00RfTkjaYqhhv6i_EZ;aUzJ4B7wKYzAfp`a__c zOENnU%)2Wp$j;og1@+r9DuhfsxB=7ZXrVxG#_}XTg zWWeO5oj|@N~}9@A+=ObA2j

52$?VnwDv!cl2$GDYn9 zqXda>1ZhR=5!(Q?4O>Hro?Su( zP99{67PgLhJ>3OunpLXbTeZhP$d1}<-;nE3aM7R+PqjL&>k#b1*{sTE;0*l#fLull zO8IiALj=j+oDFxW;1==Q!6D+c-Z(^gB!c7LsJ8_v;oO1hMWRga{s3cVv!wVHUmeCn~hZLev-8fcGFXAiCc z{ku|8rXDi=Zge2Q;I0PMt4qpMd87c<*wjs9>H`TL#-?s+@K}P%e|BWF6f52q(I4{C zwj&i?t;laD^XSEeGXR?gRE0ADo5@n$kHIx#YFn1-Eor$U!2YsGbfu{~t@GzOGq5Z$ zWQVfb%<2L2z`!GceJ6PNTWjqjhoJb^ljc89D2g3^#>R literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..183a77b9c9f2c969793de0185503e6c6daf2806c GIT binary patch literal 1314 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 FV1iolL~;NC literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..169546f2406351f10c7c227524cb0f938561b3bb GIT binary patch literal 1877 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..18715e3a5abfbb2d8534c2ee3809057a39a872b4 GIT binary patch literal 1516 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..aea1d676471c03d918d78838004355f524d1e74c GIT binary patch literal 1683 zcmV;E25k9>P)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3i5lKWrRCt{2o6l<-M-<05nBqgI^#{~tkG+&0Lm>xIdT&p{hnDKr zW7=M9*P>oSpt;3=Kp?)`P#|$SC+K#T0L@ArEcKTLexm-nj*7xZ zo%1s-aOq>&?mD&2#l`k3c=~Xm*zCIS)jx}?RvOq4P;sg&_PX;u2ze$!W%ZU_*-N#t zV6_!!71o_QP?HBHR3t3htDmQV%MIZuaM}J&fnE6vI10RFe=}m`1jP?!`=@$svv9E5 zfP42BitRT?@O9zf$27&s!5;lW7c{xxShxnS9OxCeAY0L7f?zidT9^+(>|(HA0uW)= zU5paG_p{0c!Q_HT54=r~5D1{Ra9j8T0~LhFe-!6Lbk)kPX<)9dx=((9Ru{Zr-5C z9kdAZ-8kq`Cd!$BE(er8IJWRk2e%x5`a%cGj-Mujo@^E|Ep$0=K3wTI{vuc#94Z_( zC^=wYpv)EYEGFo3!H$@)EupK(0Q2f=$45S>J4G4;b(=?q zpdf&d2`KeJY|Sh%JZk9&&E}CIsM$QmZ6tuh&ucc1>A+$f)NCHUjWQEZvt4n(=%_Td zw!%EM%o zfs6z(^l2g(tAb0zM9|T2*omM{_}_pQ7ZhAjazUF5I$RK9^Hm}^m?2XY*`OJ&0yIN( z7QihWK3JHM))8NKkihsV;EIFsbq5KA+`;|^0`0P$GqPpD0xdFl%2nLxCnOmJu40fN z+&>tq4u)b-sw6g(dL$g`Pite4AUW$)^%%{`Evll$RD`Vn6nQB|HcF}@Fcl+^0%xO0 zan@`U3HL!VQlvDGj0PQ%yQ0ipk$abnugJYF#aHBBUg9VUA7or5Do&@!xGf`?tAJ2Z z(iNv%Td}X8&=muaeanKa$iDNyRwUj)$Uu>J$ex9w%w3Uoa-D@D?Qk{=MYqgVY%MWC zUCjwL>YWHrDx6a;=;}yLtd0{6a&kSMl$jv3N~IL`a?fdT!Gx{-6fjvb$;lHXlfYII znb@q796q@{x|dfS9iea4B>;V)%_~84Me%H~LE?H2r&~|d4bAr-tskAg>`{dW) z)dVF*0&;md)MSF}H)p+LF1X8lJJ=(>6J`$VSt@#iDSsY#jFGAS z9o(3dm=Z#jK3-CD@v(X>0K4jIXkh9bBmCso(M#M4eTb=IQT;sr>IFV_Rt>=-1RnJo zBP#@*N2rLYLsUc$bP;qP1t7k_(9bF!DL^60>Q0!|#|So~tnLKh1%kf+9AUH)DLzoq zpZL{*iHcUBC?CXaw4=fqfYlK63ugdU5x;6{!neMCKYnz{$48^~nRsVg)QEbS&zcz{t#fB8i$C3rs?tMyD dObPje{{dYTv%BVIT4?|P002ovPDHLkV1fWh2Rr}( literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..3a080de753381d204783087f8a7f387ea25e2d0c GIT binary patch literal 1656 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 A(f|Me literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..3a99cbc8b1fa25b069a6cb0e5f701bfdae71d215 GIT binary patch literal 1912 zcmV-;2Z#8HP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3i_DMuRRCt{2o6m0>MHI(fRVXLOkprdv2M|4@7WTk_Bd4ewko*T! z>W@nk8t7DtL~ijPP>CEkAT@^`dPpTV8AS-0ONkId6$)komRgmFtlMBV@p|_$GrO~E z?+?$si7`#&CwV>IozHw{X5YNoon2SJ(kfGM3jWWaNBHIgzVTe12>7SId5O5->cE!* zqykiX=HK6;24MF_3+nXqg%?}fE35tYcH1z&!RYhWQhinf-rfU`F0SA9+?&_@AmGJp zo+D3N?oC}AuY0h}!43!A{ullh%+np%Z@Dv74S02rXI)&s+T|c@c#QvQz|+Vyh6LjT^e}kO@wNB0}>Z>D_ zN`>e_P#{ZI?CwKv)HzY$YJ3;qGIfNvu~W`PcLB{*u}cRJ&(b_Hs0e8rdt~rvr=|mw zUhNKnVR_h-;5sDXB6A8p9u2OgVCJNYB8$gn7R=a@D2rHtLalggN^qwX1P;9@^aI@m z5(D_5aQf4MJeD|x)8F9ySY!v#FP{E%V8GGB=}!lSgb&uD=}!m3y2Cf$Sb*P)%}xmj zBfuZUrXc!gK{@5A2$liGXf6el$*4%t9|1%Z<`K^|}E?v=ALYYH0NTS+&+6JH@H zP$jgsms}U}jeY743Xh6cU#y8`;rk(wG{s9qHoGD{FH*n%I~ zf?wN$zY2@d=t0VxjbR5_uYSPQJTJ5!557Y7D#I2(Z;4&?S> z?t0bG9+B)7vZ*aAMJ#xjR2BOy;A~t~Waj{Umx8zzr1rqm2gJI=u#@|myrm$ju0!`7 zn7R(#1z_qr1Y+tseBVKlU~=D)ebH100$_(#7DUkAu~s{?OHX(ZtN28Lh!ZKnJGP3D zfW#I=DyFA{;lMGhlbbv1@f6cGn&V>{9ix}2a-jY54w8W8&MLvx<13mw>+#wMDadR= zYei#c9h;(YoEw{>v9pd%(b!qXrfBS}Cs~nBT#-#&(R4s6klHFb6IZ0_F2Jw=^+wP! z6cs3fj`6cOK;K&xoJSFKS|agt4F{&yog-MqO_88n)J~DxWdta~91(RCpApa9HKT(e zK*B|-KEP@e%UwPXQr@v_Xc8$rEgD6!Hz@RlB1K=+Q0IagML+r!9L$4^>v{S}pivB> zBLx$D9(1{;uaB>~xJsgj(k7rM&!lz^(J9iXhlMT(VPMFw*)Mc@=X1t1d}3KRKrXw?$5{^xACZ42JF{C9A84e%DV z(GrBJEofsW4wNs*$ya#fWGo*SSNX>i3zJNwDCNB`9t8#>Te}&9a+=u}Dfx1q_$ANL zGqDu-B(k*{3Una$C>er@0=)-9QKU9$e1Q-MFnADyJ*uiIUyYefs=B7C zx*@<$Qq{E>JQASvpDnSOPZaO+&2M7YqpDCOu_C)W*hV+$oD^&*PaBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3i7fD1xRCt{2+re%VM;HL$Ak=bda;#LMlw&FA@h1mB<62)`uRDoJ!$BgK(1pp(@85dZ3jt8)~&kLEuCb*4g#W-+$I?@6PPZ z+ViV&>#!p^8E5zN|Ig0sdS_zK0I|%Ju!R2`7{Nn^znC>V2A>8a@Na*^T|&g>mWXKI#+~!`F1AG*!4gX4WI{fFmNw*g=Snih=1D6@;~9$k|4OwPeWI!*a-#u!JQn;R%G?A;QR;G~~{{YvcHt|1j0582}|L zVF^oE!ha9))6|HMsjx9|xJ!jFarlS|*~Fnoh1aPNCJxCXXYzymT{t_$HHUP++7Qb_ zL>N(Fk2DL|ot|01o~Tja#`M4`Iy<(gaEiL4Nrh0tcN&U|D=lI;HIUv$m^gHZkbBbu z$#W~1IIIvMCy&*MLztqo!=*x|h5l&hY2k~}u%m_7Mnhi*AAEIcBou`yaNqI!SHDqE zzR~r%i}SwP)Sagt9Fogm7Ut-!d+#jo@;>WJ-MUqRWm?kj;v;? z%~c20OtracR>^oSQ-F0nyq1OhDDU7%cbY3lHJZ~v{^4jCXfg%(Rtu%>ICgdLS1pu| z>R&nsFGs_g7IHO@9L(*J6sCjOHb#2apAM@KGVrwls+Z>+R9|^ejx|ua>u?N^>ms@- z>=|6{6=PUSVQ7S2am43fD#|cd+gLL~tF?%xR~ zZw#>Oj(~vyYVQ%Gl6~bAJ{T2H9<3?-VWg8T0x8VDo#smRB4BlE?aTG?VRm3y!R+R_;`1kQA1 znri-k0emx8AMTTWB1m&^q~-;2x@`E|H^aL8G@jgfIVjINL^)8N$H}HU8T;{ofl@@W zX-Ar1kaKYkX-67h_JF2kGt-eN%(m%Z19TFMFf5)AjUU9z}Mg~N9&TNpV&`(j8igS%g#M6ANh%p3u7k>_Uw7@wEo z8&CF74A)1br6(58U7g!t5p$2IQsSEh>CIUH_Xa;Yov&{Bmf27C?agSpWsrsF3>Y z;GSnb@}`oskqC85)nh?QnL5a;cxaE>z?YT*u6v6BYYgBfc6=y4_*HQsI&J}9#>!sH zgB`5&VblXSe$|4gi35av-vPen0$lb0UgOn1{0X=EP27qV_8o&2tn^`s@3IkZ0sL0M zJ1#MDui{_dV$>J-#vR_pt)0g>7O~=f=>lusO!n3*l4fN33GRhl7Z(Fk^Ry2Zh*6!pY5(MEPr~` jZt#VrvD-LCnLPXl9t*u)OgN6&00000NkvXXu0mjfzO*XI literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.12.threads.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.12.threads.png new file mode 100644 index 0000000000000000000000000000000000000000..d45458ac1a0280496a5b47a63d9deac91661c0bb GIT binary patch literal 2216 zcmV;Z2v_%sP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3kCP_p=RCt{2o6m0)Hx$QHAvK4p$*CvOz7t ztzwBVJN9S3&wk&Tv1fM2z_W~16be1R1Zuo(tZi_VphZkAUVbfE0n<`q$DR>G3Y_&YW1>p&9uKI%Q-LXbx zJOdwyzWf_Pe7%q*4m^)hM`#FE%7*|( zzTk)vO{1x^M$7HCD6oGuvm6TUe*P5+Udt?}gCRVeiQo(Y&Rk0@ce1v&cDn{1KaArX zPU0XeWtP(wv;Mtq2^`EUr-M(jHV^L*ij?K%@TL<|uX@!hNAPjI>evyyU9U1?TCg)eBlo0veObxdIB3yyq2 zVBRZ~99Gb`Z> z8uDQV4f!yGh7-#S8cr-TXh@`GzRG+-?h6WEkWQopq;EVH@Wfk@y>CTwNnl;Dc!S&* z6uuzo02@f2$~KTZmERdiUIT0(c@40xSeY-#4PbP}01A`hQ(v%S04eKOLCQJ_xNQI_ z2Utgya)1@29FTyIeL-#jDeKrlZUBV|6bA6R38eFDd7eW!;NO8J=TO$MdX=({9V8rJ z2MGt*`$#yz;qjU`C}=Rg=AiRc!x8hriH!Fp1302V+yOZ_#8v@mK^>5;0=B8idsE_5@3r^EC&dE zhB_7rv@Y4(E}FT6Dxo{T0P^@xmU`U**0og{tL^~9sB$${)&R_cOcCwXSpqJiU?w7x zzfUnRGM*i2Dz!HS29T-$dnl%{YA-*MKB8wwk%1&u%>gdgoH$m^0W?@`syQG5nORZf zvKq+kirO{6zM9KwP_U1IwQ&>}7?>5&G#8`Fks8Ct5~L@(X(~`~J)X^46zkT>=Q$%z zt^!c&q^kf44rl6$wa<0y6f-L=RHcYqwhneNP$2QvK`b=2VAi3*x?=6K%bXmw4!uUM zg@!oEwz$TvLq8>}E7q)&fInIkG3(Hy%CLA{K(z?{NMt(n8yf=JMl~H#?gr|L!b1_U z4%tWau3rbirifUF1oa6@b&qw{kroE^;K`egu2>!C1YET$3LL}~k@-8TgARSvtwW9~ zavb3VR*P<(CW@6Qi=$#PqLtTXBq(%x-$OAOQE$b{Ycp5HNS7@(Z@~dPFKY=bY=(fr{mm1Q51iC6qPp4iv6s$4a6TD zD|?+46GrI(1)@(l)kHcgree%fQAwn;Vk#yyu>RDVI83=a2My23)hNpz6rlO^ z^#y%@9Xu4q44@_JqbF$nDHsL%l>ZzUEz6-j+=FO#9^kr|0a)SyH)P_&_={hQ3`TEz z5Y5Ytot}U#xsigSA;8;%9*nxuAp93OL0e(~mj%Glx`cm|wLw?b$_@TAhXuKjf}vcB zjG`XEABzA##m>DZ_r8&;ukOg&d$P9wRC-Zvu7HJ zRfc*=*1p&Qn3o$9&p?KHDObEJd(oGn!a9TSIi!lqQt?r)cpw$K$1?s;8El5RVz>n< z7)r1cgK;01Wgo+=kE4UQk8c1Ldt8EfABS>O2fKSPoVp?>l{Y3Knv-fDE2BC%l%qO( zj=_o?)v2j`RK4?f3jROAv_OA_q=fUNH*#dGY% q_R949mxp_uXnNMUj}GPigZ}_aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3jSV=@dRCt{2o6T<9Mi9qU1gH;1?FWcqzeQspc6I0j^aWb@6$$~E&lNm`;LaDl z_9b_ZUeH>dzPQN)2kpA&2==c*(DLSHAG&%p*g1F(0𝔏F8Y-x7NAf@?Oo!riS1X zzlVQAd`0ocIPd^pgZP7oFR4_drKv|QI9F$ag`&zp2Xg?U>C58XYX%5gzt_V!{v>86 z@N_c_cGdunok6h@v>GR)5X?dHCT01@^8FC0Fn`Jo9uoq7dMXq2y#RYmPze z@h%0<-$*2P+H5xO6JT1$83Kfrq2y?fsU4EwP;xpD=1GqhlG`u4luQXmWtVm!><6Wb z?ZD_WCJ4{D;2SRZHy2EXeikUW;4T-`Hlz;J4qZC1&jqz<)q;Wx>e8wOb!pXty0mJ+ z0T+xsCa6oR9`w23YvP<0s7b3H)TC7pYSNm4QJtJT2qQS~Nzmtle;C22zUL9erz$R* z(tA9nzRf07rAJd%)x(ZyF6VJUQ90;yLFFuVVxV$_G=a*lJTXu?2AIHz3o11?IZ$vx zzj9EeIU}gj+~h!&=8T|9bCUyAVl^*yy~;tM2BQl)(ARi;!3A47P^~BfsL)&j?r=d} zNGh?KL51cL@K-JBHI1oX9_P=mL)AZS6K3o8HP8kD00wOUnZ&H|)0cQ#O8 zM_O|hS*2(6HlR>~@t8x;S7RG2E5TOW2RI&EaR$_zmRgT}dKHkEPlYixY!1a_J~6Vy zunNeoQG<$AKw_kH5^z@;P-3KX67c?nKysY30m*UBqIb~4mDP5)|Ixt>14tEFC5MuZ z6-Y_P3ZxW}fNd@a29T1D-Om;t7ZhC3uN?}Y+I(8r-oil;alnErHlXwhGAR!$) zkdTfgC`iy;M+KN3X+fV0lAGu?s2jnubdoyyMzE}aNrPqSnAcW`m8D~u)v|PKK|z8I zGx&f4BePc1l_Cec|4}`Hxp$Oz%x$w;lFr#c&kU9{XR(?~tfV=M)tm3DG(Jr5b9MxVukNbR{;q2=M5f<#iN;(Db(V~I+|IrKr)ts z6;*Bx7FBLFCs%^{HF9c2m7fjN?viEZ5#UWO2sWVLf<6J-GzSUVWVKjc0T`4%TGp|k za{H{Z!Gg*yXB{+X^G~Ow@&sJB0SjWa_eg+tbu6gdKC67tuN;&wZ~%kir-_5I%Buin zl{@|@zHDJzHoez5lpLB&W>eA&ayMUnaK!-xq#8? zjvhy)zBO1l{imzPQ3vsCL6N>?**UF2@o9^L5<}U*tJS<^*<)#wDDNrn`R0ras_#@w zigU+b$sl>7Jo%f|6Hf-UE~Rf+D`b^$N$2{g0P0*yQ-`QtXveZkK^#Fm_{iX?RI0I~ zqH+!jWG+Cdwo$z(xdNHn$CDdor=-<9dD>LQdQukoK{LDjK+08N!E%A>9nI9_s0*ur z=MIwx$+{Ix=4Gp5YR#YMvO&QG*^@xYTtF$UE}(QPf>WsZOPs*`nBmKLae7>pBe>uwJ+5GsjeO1`&&FCt?`S?KgLcn&p2kBi2gKAKH1A2P0LD|L z=_-H&u5&@|)4_dT+XSQy>&OIg0>T41_MZczRZQ(s7ovqlfLs1Nz={C4jSU~hH-0rd z7<}kJw1@}09Ur#wAO#1w7WweD1A{gSMEu-?XvG7#>f`EW1L0q=G-zWf9*Ca=Ea5>4 zhByulq7J}s4S*kG<=()v@6qcU?0?}SEbYBOE#iUqtp}q0Xb7HM9fn$eh}XrTUdOYy z(QA7hL%o8f`?z3T#DnRVfT3Q=JU+x)^e|M|@F08zsmE3H_$>4I7Cp9)G5*gz*a|a` z;WngTh+r!Q<2tTl9m8QA2XEs#z6WS@1cF%|`?7D;3Og;BUp=%2+mE4xV0&u?!QKzWUv)Je sFM0brYjcZV9(7yM+=6u-Ev$O*ABX<5^a%U>egFUf07*qoM6N<$g4lYn`Tzg` literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.2.threads.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.2.threads.png new file mode 100644 index 0000000000000000000000000000000000000000..52d7aee49039dda55cd45704f04de7ec060406b1 GIT binary patch literal 2163 zcmV-(2#oiMP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3j@kvBMRCt{2o6m0)Hx$P~QOltMjy*I={tTj$bSv>^v{n9uwn8O9 z)VLJ~ZsZTB+8isv0WLHVVPhdw<P=u<2$R-M5lFZJ$KF_bUJ$^G|)24;) zld_r_`!nC?=Qm#4vpE5tc47z)!T$`n8lT3`$Q@jUwjUTm`@_q-Paisit8jl~ac+Y< zgB;qOoiDnpUSP1j5jum{5Iop39IyaKrFVE9Gfvs^|-jwLC$i=-5C9a{%Kr=lR|r9w4+gTA}nm@!1JHS_*^J zd4PRqkk1CoGY6PAC*8ns2|?ze*jbc{?rmH-zx3snY$G^=n!TN1JoLvRQV!M6~MTb^JfjvI_yo6Loa zPyLIozA*_f0ApV;VxHhp%M(1j;0eC!HTR=>s0hkF&xZOs2p) zx81?D&{?QTy_Na(i36}uL8_kN^Nk`;6i#*|4^DB%dRt9#~puw69P}`_?T}=k4 zQPrzDfVy)vsZ)$OIA7JnQIk4(aAL%SUc?%K5rSMV;J0*WRGe=Tm_hS|5a`>vofN9$!w};_ILxuTM1|;r#$bMiFz=xYFAUx z`W*2}Fnv0NJD6C{TE}`f17x;xavVs&MR~MMl~;gCa9;eqAUO^Uz~|O-GRqUNBaiIw zwX4CzZduF80b~FYZ_-&UNc5OD$bCU^>>!n_wIG#qwIG#q$wc>*CzuuzAeD2qAeD2k z1y;6^%DMV&8U9azttwE^U@WRYI-_bpBIjNYEY?;wBXX`jszlDc9ymjS5t(yI8!K{k zn##EvFxdA51!9~8q3Y>aCvvVPsth9L1In&gx4V*ntin}@>^Y~c=4_<^pU|MFQiNR^ z)b~deOYUgja81B~0uv;jCP8VObTwYA1Z~^h>4OoyWAiniS;aQRv?JoB5emc!N5tuO z0qo^SDFW##0KxvaMN#A~_fMAg6pNXa&DFvO7Qbf&I|Qgm+Z7WlgM-m#AO3U!6=S85 zN8isWl?{AlHn7-1(oLwaF-m(D}yJWhl-Z9HM=mdNtk4jT(Z3q|US4hLC zLSTLqRIEER=c1UEO3Cif%v=a7-64#s#+{7fs(#ctqg(+^QkMw!^wP#{jEt}!(JVH|<9ZYpVoivkvpgVfv{MWkuFR(WsDs3+eS#A|LTh2Le6K%Zk*rKRPUd`OHeB zmv~muBgbG!$92VmK(*!Ss$1>2!Z^)h(*&x{n5>L);3seHBGD$bkyeU}}8yL`gTwEBS zb=_gHoU`|1M1S`b`}dBS1Lf{e!I-|yQ66qr#V8M}9c1JfQv6=XS@C001#)r+IEE2F zMcLyOVChwq>TLRg%Uu!R+i4OEs@~|a_^h9zfD0rTR=<3_&%6{7nWw<0>OE#L8V90gVhP}IQ(K8i_pjQDg1!@r+>K!JZ-K41Wz znG^YfvXOqE@C5^3F!BYlk)ELN1p{9&@&#eq7YuyC$QP8unIE|B3wpcy{{xTnpF`7C zfCrea0(`&)U(olzgOvqdW6Rp;3F17$5A?A&4vgn8w7XjnPfP+_6XO809N-3ad?_R+=2WwpcD|nECQ6J!Ny9-eV6NLZJgLsw!ToM3#iwOUOr9lTv@qmBNVG0jY zFg%jm?_Gf3aNxTxGxsW9eTAyeahet0#nK**YyuD1XAF4fZU!D)%3N*T!FtlwD|qz= zs&*F8)r(mAWDQ^v56(OSboFAccn4e2LswyuLHHO_#W_@bkSlJZVrL)yKh2;W=8EA8 zq+p2PvIJ!t=dg`o*2ZXCw(%7X;$4nl-o`#g^Q5$t_!*{7it&#@<~ p^J9}A?QSi{V-t@-qMc literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.20.threads.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.20.threads.png new file mode 100644 index 0000000000000000000000000000000000000000..da0328a6a7bf899533096001d79f9a2608a02660 GIT binary patch literal 2147 zcmV-p2%PtcP)aBOdMAa-SPb7^mGATusEAaG%HV`yw;c4cfJGazqnAWUg)b$B2$E;KGO zGA(CkIctq$djJ3j;Ymb6RCt{2+)Zy2M;HKLS5=!+lT%Mb$xrC5L?WpV{Q*5iTw3KX zv_d67)J!D~y^$Y)TK9%z4sd})m}G>i%D3i7D`O_es;EH4L=e_wz590d!|~3?J74*r ztuj)Q{d)4w%)YbUSvJ%lu+&cBDg3v<;U#!L`A_N#<8=}RLAXnz8(+-KZxBy7{FX%5 zKkawU`bLajk*Kvgd1k{KMj1>xb>ayJa}c%2%=B&Fh?a5+Pa(ioJrFLiK)Bfmg-bg% zuQE}>`>fBu$NVeJR;2>%lH(qeBBF%-_!1EI9*#Gpsn4^Hk+bY0K8RjcV4(r+X=Q4zqGUd>S&}INHKTu(rayT4(vQwMVMbxF7 zFgj|p0I$JR5O^#5MgkzqzR>_U)*@mmlJ z#LvgLsyo_W&JdSQSR!K3T2*vlS$Y*8Shm|vbYR&a`uSml=!MRDhfG2t4TUTeVkh$W zAeI4Eh-H8kVi{nCSO(aqNF)@}P{=|dewvO8A{k(ZNCwy;k^y#zWPrmQnS??b3Rx&b zuhcfEKam+s-w%ZF&OYkoU`kQgHb-1SA($i91EGH2lEYujkfM;9Av=1= z%uu^0hgU-(zI$}cQA2a)=(F4*SKk5DURhn*h(j<#?IrneFuUd;_p5m!7;I&~H4r8y zNDXj^%mOf2%mUi@&3s-M77-2su~~o_Zf8pdh)mdPaPzpJZX_QLT1JO;Q%2IQe&IuRN%wn5EEK4z#H$!={# zV6kL^ngMw@ShqpVfXv&-jvkJBg?dL^GD3WAHTp+9JuH@xr(`7m!F*v{5(F;e5%YgN z)$PpNi05ilc8@oNaxAI?(gOQs_vj&*M+XDlfOL4kz83=XLUaQ%hr}2$D+r|Kh!lkk zg|z&sj^rHn%@G+2BNP&4L4bLs%=1Sa>Th%pj;C6W6?C zQV}cAWf~~woViyk5#^k7o(Ae5e%C?9i*n9cK6EOGh}&}5K%fvs2W=7a1E>noHVP4$ zCL-7(Qgy!(3a7va3e}Wy&In_4#b;9H1BKcp%09m|KYlctnikHJ7(Z3CO8qgj87bfa0$ZbIu5fuqNi5V?^c$iDA_-V!o5QLiytD z48_Bwd@w=zb4EDAF=Br5U%5j0vvf}fjZdx1TK}bky65C_#MeYuRnr6Z^322yZB^A- zfHF<3-0hCv2r~C-k#5yDlp_OFx71Z=ns;P{=HDx`57T*6w^UNVF>}g19TF$VRNwH9 zSe}}v)eR`5svn<_F??o>I2vMgO++Ptuz?gme$znt6=`kRC7}GZg)%20)fHC!7}RRT zBc5vK+;WJR5UACrBq+Vdr(A#!HhwNa^UKwha-T?0?4AT)Ta%#ijb&0<-jy>)=pMrx z(`j9T_-l?*%5TfL+N|s}z1+R4B)Kx*KPbYbE3L~gy`?`=E^TF4?T_TXlt^M<4b<_t z-^?2NtZ7NW_jLog*=$nvP$I1T>Uik@`4ZG~hhlNPSV7>u+@T_R+>#wp#GpH?ys%Ix z6dxE#E6z~pR=>mO^1vS@43% z`9KKCq7FL!jpyPL4TG@v@#5m*d0`e1@K>e9EFc6nLSg7%2M?Ly6ddyvk}16*aZ04o&W8b9%I_Ttwvf#hu$(s{nH-DR-F7YdjR0p7moLek+0 zLVxN*x);B!rbAHDY z-{E`v{8GjE0{Myn?c6Eh;9^op#=)8JLT!1q4kleu}mF!>00RWFPp z-sY|7^Qyu+f%q{L5m$M{2cw8Dc*G8$nqT~gz-By(7;ixVV-8yx%-Xohvj0P)Xk+ps zYvUV$U|c7rcyo&%fUkQ?YT)7%V+_~kO`_1Vn)*B5#>VDi$OGhDjIN6X{C*=F3mo&s4` zD~rHK3-E-);X>SP!R+cwXV|$1T@E{&D;)N}(@fE@h-b-@_S($+XS=;tIy2|oMu&3p Z@E;<6pkY}U^P>O&002ovPDHLkV1hVe1f~E0 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.3.threads.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.3.threads.png new file mode 100644 index 0000000000000000000000000000000000000000..1093e81ca6b7c9507b2c79497928fe39c6921275 GIT binary patch literal 2270 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 AO8@`> literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.5.threads.png b/trunk/3rdparty/gperftools-2-fit/docs/tcmalloc-opspersec.vs.size.5.threads.png new file mode 100644 index 0000000000000000000000000000000000000000..779eec60bc04f7e23ebb4804f66c0bb72ca5b5e5 GIT binary patch literal 1995 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 iczV`(j1J}a!M_32oUZ3qtF3SV0000 + + + +TCMalloc : Thread-Caching Malloc + + + + + +

TCMalloc : Thread-Caching Malloc

+ +
Sanjay Ghemawat
+ +

Motivation

+ +

TCMalloc is faster than the glibc 2.3 malloc (available as a +separate library called ptmalloc2) and other mallocs that I have +tested. ptmalloc2 takes approximately 300 nanoseconds to execute a +malloc/free pair on a 2.8 GHz P4 (for small objects). The TCMalloc +implementation takes approximately 50 nanoseconds for the same +operation pair. Speed is important for a malloc implementation +because if malloc is not fast enough, application writers are inclined +to write their own custom free lists on top of malloc. This can lead +to extra complexity, and more memory usage unless the application +writer is very careful to appropriately size the free lists and +scavenge idle objects out of the free list.

+ +

TCMalloc also reduces lock contention for multi-threaded programs. +For small objects, there is virtually zero contention. For large +objects, TCMalloc tries to use fine grained and efficient spinlocks. +ptmalloc2 also reduces lock contention by using per-thread arenas but +there is a big problem with ptmalloc2's use of per-thread arenas. In +ptmalloc2 memory can never move from one arena to another. This can +lead to huge amounts of wasted space. For example, in one Google +application, the first phase would allocate approximately 300MB of +memory for its URL canonicalization data structures. When the first +phase finished, a second phase would be started in the same address +space. If this second phase was assigned a different arena than the +one used by the first phase, this phase would not reuse any of the +memory left after the first phase and would add another 300MB to the +address space. Similar memory blowup problems were also noticed in +other applications.

+ +

Another benefit of TCMalloc is space-efficient representation of +small objects. For example, N 8-byte objects can be allocated while +using space approximately 8N * 1.01 bytes. I.e., a +one-percent space overhead. ptmalloc2 uses a four-byte header for +each object and (I think) rounds up the size to a multiple of 8 bytes +and ends up using 16N bytes.

+ + +

Usage

+ +

To use TCMalloc, just link TCMalloc into your application via the +"-ltcmalloc" linker flag.

+ +

You can use TCMalloc in applications you didn't compile yourself, +by using LD_PRELOAD:

+
+   $ LD_PRELOAD="/usr/lib/libtcmalloc.so" 
+
+

LD_PRELOAD is tricky, and we don't necessarily recommend this mode +of usage.

+ +

TCMalloc includes a heap checker +and heap profiler as well.

+ +

If you'd rather link in a version of TCMalloc that does not include +the heap profiler and checker (perhaps to reduce binary size for a +static binary), you can link in libtcmalloc_minimal +instead.

+ + +

Overview

+ +

TCMalloc assigns each thread a thread-local cache. Small +allocations are satisfied from the thread-local cache. Objects are +moved from central data structures into a thread-local cache as +needed, and periodic garbage collections are used to migrate memory +back from a thread-local cache into the central data structures.

+
+ +

TCMalloc treats objects with size <= 256K ("small" objects) +differently from larger objects. Large objects are allocated directly +from the central heap using a page-level allocator (a page is a 8K +aligned region of memory). I.e., a large object is always +page-aligned and occupies an integral number of pages.

+ +

A run of pages can be carved up into a sequence of small objects, +each equally sized. For example a run of one page (4K) can be carved +up into 32 objects of size 128 bytes each.

+ + +

Small Object Allocation

+ +

Each small object size maps to one of approximately 88 allocatable +size-classes. For example, all allocations in the range 961 to 1024 +bytes are rounded up to 1024. The size-classes are spaced so that +small sizes are separated by 8 bytes, larger sizes by 16 bytes, even +larger sizes by 32 bytes, and so forth. The maximal spacing is +controlled so that not too much space is wasted when an allocation +request falls just past the end of a size class and has to be rounded +up to the next class.

+ +

A thread cache contains a singly linked list of free objects per +size-class.

+
+ +

When allocating a small object: (1) We map its size to the +corresponding size-class. (2) Look in the corresponding free list in +the thread cache for the current thread. (3) If the free list is not +empty, we remove the first object from the list and return it. When +following this fast path, TCMalloc acquires no locks at all. This +helps speed-up allocation significantly because a lock/unlock pair +takes approximately 100 nanoseconds on a 2.8 GHz Xeon.

+ +

If the free list is empty: (1) We fetch a bunch of objects from a +central free list for this size-class (the central free list is shared +by all threads). (2) Place them in the thread-local free list. (3) +Return one of the newly fetched objects to the applications.

+ +

If the central free list is also empty: (1) We allocate a run of +pages from the central page allocator. (2) Split the run into a set +of objects of this size-class. (3) Place the new objects on the +central free list. (4) As before, move some of these objects to the +thread-local free list.

+ +

+ Sizing Thread Cache Free Lists

+ +

It is important to size the thread cache free lists correctly. If +the free list is too small, we'll need to go to the central free list +too often. If the free list is too big, we'll waste memory as objects +sit idle in the free list.

+ +

Note that the thread caches are just as important for deallocation +as they are for allocation. Without a cache, each deallocation would +require moving the memory to the central free list. Also, some threads +have asymmetric alloc/free behavior (e.g. producer and consumer threads), +so sizing the free list correctly gets trickier.

+ +

To size the free lists appropriately, we use a slow-start algorithm +to determine the maximum length of each individual free list. As the +free list is used more frequently, its maximum length grows. However, +if a free list is used more for deallocation than allocation, its +maximum length will grow only up to a point where the whole list can +be efficiently moved to the central free list at once.

+ +

The psuedo-code below illustrates this slow-start algorithm. Note +that num_objects_to_move is specific to each size class. +By moving a list of objects with a well-known length, the central +cache can efficiently pass these lists between thread caches. If +a thread cache wants fewer than num_objects_to_move, +the operation on the central free list has linear time complexity. +The downside of always using num_objects_to_move as +the number of objects to transfer to and from the central cache is +that it wastes memory in threads that don't need all of those objects. + +

+Start each freelist max_length at 1.
+
+Allocation
+  if freelist empty {
+    fetch min(max_length, num_objects_to_move) from central list;
+    if max_length < num_objects_to_move {  // slow-start
+      max_length++;
+    } else {
+      max_length += num_objects_to_move;
+    }
+  }
+
+Deallocation
+  if length > max_length {
+    // Don't try to release num_objects_to_move if we don't have that many.
+    release min(max_length, num_objects_to_move) objects to central list
+    if max_length < num_objects_to_move {
+      // Slow-start up to num_objects_to_move.
+      max_length++;
+    } else if max_length > num_objects_to_move {
+      // If we consistently go over max_length, shrink max_length.
+      overages++;
+      if overages > kMaxOverages {
+        max_length -= num_objects_to_move;
+        overages = 0;
+      }
+    }
+  }
+
+ +See also the section on Garbage Collection +to see how it affects the max_length. + +

Medium Object Allocation

+ +

A medium object size (256K ≤ size ≤ 1MB) is rounded up to a page +size (8K) and is handled by a central page heap. The central page heap +includes an array of 128 free lists. The kth entry is a +free list of runs that consist of k + 1 pages:

+
+ +

An allocation for k pages is satisfied by looking in +the kth free list. If that free list is empty, we look +in the next free list, and so forth. If no medium-object free list +can satisfy the allocation, the allocation is treated as a large object. + + +

Large Object Allocation

+ +Allocations of 1MB or more are considered large allocations. Spans +of free memory which can satisfy these allocations are tracked in +a red-black tree sorted by size. Allocations follow the best-fit +algorithm: the tree is searched to find the smallest span of free +space which is larger than the requested allocation. The allocation +is carved out of that span, and the remaining space is reinserted +either into the large object tree or possibly into one of the smaller +free-lists as appropriate. + +If no span of free memory is located that can fit the requested +allocation, we fetch memory from the system (using sbrk, +mmap, or by mapping in portions of +/dev/mem).

+ +

If an allocation for k pages is satisfied by a run +of pages of length > k, the remainder of the +run is re-inserted back into the appropriate free list in the +page heap.

+ + +

Spans

+ +

The heap managed by TCMalloc consists of a set of pages. A run of +contiguous pages is represented by a Span object. A span +can either be allocated, or free. If free, the span +is one of the entries in a page heap linked-list. If allocated, it is +either a large object that has been handed off to the application, or +a run of pages that have been split up into a sequence of small +objects. If split into small objects, the size-class of the objects +is recorded in the span.

+ +

A central array indexed by page number can be used to find the span to +which a page belongs. For example, span a below occupies 2 +pages, span b occupies 1 page, span c occupies 5 +pages and span d occupies 3 pages.

+
+ +

In a 32-bit address space, the central array is represented by a a +2-level radix tree where the root contains 32 entries and each leaf +contains 2^14 entries (a 32-bit address space has 2^19 8K pages, and +the first level of tree divides the 2^19 pages by 2^5). This leads to +a starting memory usage of 64KB of space (2^14*4 bytes) for the +central array, which seems acceptable.

+ +

On 64-bit machines, we use a 3-level radix tree.

+ + +

Deallocation

+ +

When an object is deallocated, we compute its page number and look +it up in the central array to find the corresponding span object. The +span tells us whether or not the object is small, and its size-class +if it is small. If the object is small, we insert it into the +appropriate free list in the current thread's thread cache. If the +thread cache now exceeds a predetermined size (2MB by default), we run +a garbage collector that moves unused objects from the thread cache +into central free lists.

+ +

If the object is large, the span tells us the range of pages covered +by the object. Suppose this range is [p,q]. We also +lookup the spans for pages p-1 and q+1. If +either of these neighboring spans are free, we coalesce them with the +[p,q] span. The resulting span is inserted into the +appropriate free list in the page heap.

+ + +

Central Free Lists for Small Objects

+ +

As mentioned before, we keep a central free list for each +size-class. Each central free list is organized as a two-level data +structure: a set of spans, and a linked list of free objects per +span.

+ +

An object is allocated from a central free list by removing the +first entry from the linked list of some span. (If all spans have +empty linked lists, a suitably sized span is first allocated from the +central page heap.)

+ +

An object is returned to a central free list by adding it to the +linked list of its containing span. If the linked list length now +equals the total number of small objects in the span, this span is now +completely free and is returned to the page heap.

+ + +

Garbage Collection of Thread Caches

+ +

Garbage collecting objects from a thread cache keeps the size of +the cache under control and returns unused objects to the central free +lists. Some threads need large caches to perform well while others +can get by with little or no cache at all. When a thread cache goes +over its max_size, garbage collection kicks in and then the +thread competes with the other threads for a larger cache.

+ +

Garbage collection is run only during a deallocation. We walk over +all free lists in the cache and move some number of objects from the +free list to the corresponding central list.

+ +

The number of objects to be moved from a free list is determined +using a per-list low-water-mark L. L +records the minimum length of the list since the last garbage +collection. Note that we could have shortened the list by +L objects at the last garbage collection without +requiring any extra accesses to the central list. We use this past +history as a predictor of future accesses and move L/2 +objects from the thread cache free list to the corresponding central +free list. This algorithm has the nice property that if a thread +stops using a particular size, all objects of that size will quickly +move from the thread cache to the central free list where they can be +used by other threads.

+ +

If a thread consistently deallocates more objects of a certain size +than it allocates, this L/2 behavior will cause at least +L/2 objects to always sit in the free list. To avoid +wasting memory this way, we shrink the maximum length of the freelist +to converge on num_objects_to_move (see also +Sizing Thread Cache Free Lists). + +

+Garbage Collection
+  if (L != 0 && max_length > num_objects_to_move) {
+    max_length = max(max_length - num_objects_to_move, num_objects_to_move)
+  }
+
+ +

The fact that the thread cache went over its max_size is +an indication that the thread would benefit from a larger cache. Simply +increasing max_size would use an inordinate amount of memory +in programs that have lots of active threads. Developers can bound the +memory used with the flag --tcmalloc_max_total_thread_cache_bytes.

+ +

Each thread cache starts with a small max_size +(e.g. 64KB) so that idle threads won't pre-allocate memory they don't +need. Each time the cache runs a garbage collection, it will also try +to grow its max_size. If the sum of the thread cache +sizes is less than --tcmalloc_max_total_thread_cache_bytes, +max_size grows easily. If not, thread cache 1 will try +to steal from thread cache 2 (picked round-robin) by decreasing thread +cache 2's max_size. In this way, threads that are more +active will steal memory from other threads more often than they are +have memory stolen from themselves. Mostly idle threads end up with +small caches and active threads end up with big caches. Note that +this stealing can cause the sum of the thread cache sizes to be +greater than --tcmalloc_max_total_thread_cache_bytes until thread +cache 2 deallocates some memory to trigger a garbage collection.

+ +

Performance Notes

+ +

PTMalloc2 unittest

+ +

The PTMalloc2 package (now part of glibc) contains a unittest +program t-test1.c. This forks a number of threads and +performs a series of allocations and deallocations in each thread; the +threads do not communicate other than by synchronization in the memory +allocator.

+ +

t-test1 (included in +tests/tcmalloc/, and compiled as +ptmalloc_unittest1) was run with a varying numbers of +threads (1-20) and maximum allocation sizes (64 bytes - +32Kbytes). These tests were run on a 2.4GHz dual Xeon system with +hyper-threading enabled, using Linux glibc-2.3.2 from RedHat 9, with +one million operations per thread in each test. In each case, the test +was run once normally, and once with +LD_PRELOAD=libtcmalloc.so. + +

The graphs below show the performance of TCMalloc vs PTMalloc2 for +several different metrics. Firstly, total operations (millions) per +elapsed second vs max allocation size, for varying numbers of +threads. The raw data used to generate these graphs (the output of the +time utility) is available in +t-test1.times.txt.

+ + + + + + + + + + + + + + + + + +
+ + +
    +
  • TCMalloc is much more consistently scalable than PTMalloc2 - for + all thread counts >1 it achieves ~7-9 million ops/sec for small + allocations, falling to ~2 million ops/sec for larger + allocations. The single-thread case is an obvious outlier, + since it is only able to keep a single processor busy and hence + can achieve fewer ops/sec. PTMalloc2 has a much higher variance + on operations/sec - peaking somewhere around 4 million ops/sec + for small allocations and falling to <1 million ops/sec for + larger allocations. + +
  • TCMalloc is faster than PTMalloc2 in the vast majority of + cases, and particularly for small allocations. Contention + between threads is less of a problem in TCMalloc. + +
  • TCMalloc's performance drops off as the allocation size + increases. This is because the per-thread cache is + garbage-collected when it hits a threshold (defaulting to + 2MB). With larger allocation sizes, fewer objects can be stored + in the cache before it is garbage-collected. + +
  • There is a noticeable drop in TCMalloc's performance at ~32K + maximum allocation size; at larger sizes performance drops less + quickly. This is due to the 32K maximum size of objects in the + per-thread caches; for objects larger than this TCMalloc + allocates from the central page heap. +
+ +

Next, operations (millions) per second of CPU time vs number of +threads, for max allocation size 64 bytes - 128 Kbytes.

+ + + + + + + + + + + + + + + + + +
+ +

Here we see again that TCMalloc is both more consistent and more +efficient than PTMalloc2. For max allocation sizes <32K, TCMalloc +typically achieves ~2-2.5 million ops per second of CPU time with a +large number of threads, whereas PTMalloc achieves generally 0.5-1 +million ops per second of CPU time, with a lot of cases achieving much +less than this figure. Above 32K max allocation size, TCMalloc drops +to 1-1.5 million ops per second of CPU time, and PTMalloc drops almost +to zero for large numbers of threads (i.e. with PTMalloc, lots of CPU +time is being burned spinning waiting for locks in the heavily +multi-threaded case).

+ + +

Modifying Runtime Behavior

+ +

You can more finely control the behavior of the tcmalloc via +environment variables.

+ +

Generally useful flags:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
TCMALLOC_SAMPLE_PARAMETERdefault: 0 + The approximate gap between sampling actions. That is, we + take one sample approximately once every + tcmalloc_sample_parmeter bytes of allocation. + This sampled heap information is available via + MallocExtension::GetHeapSample() or + MallocExtension::ReadStackTraces(). A reasonable + value is 524288. +
TCMALLOC_RELEASE_RATEdefault: 1.0 + Rate at which we release unused memory to the system, via + madvise(MADV_DONTNEED), on systems that support + it. Zero means we never release memory back to the system. + Increase this flag to return memory faster; decrease it + to return memory slower. Reasonable rates are in the + range [0,10]. +
TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLDdefault: 1073741824 + Allocations larger than this value cause a stack trace to be + dumped to stderr. The threshold for dumping stack traces is + increased by a factor of 1.125 every time we print a message so + that the threshold automatically goes up by a factor of ~1000 + every 60 messages. This bounds the amount of extra logging + generated by this flag. Default value of this flag is very large + and therefore you should see no extra logging unless the flag is + overridden. +
TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTESdefault: 16777216 + Bound on the total amount of bytes allocated to thread caches. This + bound is not strict, so it is possible for the cache to go over this + bound in certain circumstances. This value defaults to 16MB. For + applications with many threads, this may not be a large enough cache, + which can affect performance. If you suspect your application is not + scaling to many threads due to lock contention in TCMalloc, you can + try increasing this value. This may improve performance, at a cost + of extra memory use by TCMalloc. See + Garbage Collection for more details. +
+ +

Advanced "tweaking" flags, that control more precisely how tcmalloc +tries to allocate memory from the kernel.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TCMALLOC_SKIP_MMAPdefault: false + If true, do not try to use mmap to obtain memory + from the kernel. +
TCMALLOC_SKIP_SBRKdefault: false + If true, do not try to use sbrk to obtain memory + from the kernel. +
TCMALLOC_DEVMEM_STARTdefault: 0 + Physical memory starting location in MB for /dev/mem + allocation. Setting this to 0 disables /dev/mem + allocation. +
TCMALLOC_DEVMEM_LIMITdefault: 0 + Physical memory limit location in MB for /dev/mem + allocation. Setting this to 0 means no limit. +
TCMALLOC_DEVMEM_DEVICEdefault: /dev/mem + Device to use for allocating unmanaged memory. +
TCMALLOC_MEMFS_MALLOC_PATHdefault: "" + If set, specify a path where hugetlbfs or tmpfs is mounted. + This may allow for speedier allocations. +
TCMALLOC_MEMFS_LIMIT_MBdefault: 0 + Limit total memfs allocation size to specified number of MB. + 0 means "no limit". +
TCMALLOC_MEMFS_ABORT_ON_FAILdefault: false + If true, abort() whenever memfs_malloc fails to satisfy an allocation. +
TCMALLOC_MEMFS_IGNORE_MMAP_FAILdefault: false + If true, ignore failures from mmap. +
TCMALLOC_MEMFS_MAP_PRIVATEdefault: false + If true, use MAP_PRIVATE when mapping via memfs, not MAP_SHARED. +
+ + +

Modifying Behavior In Code

+ +

The MallocExtension class, in +malloc_extension.h, provides a few knobs that you can +tweak in your program, to affect tcmalloc's behavior.

+ +

Releasing Memory Back to the System

+ +

By default, tcmalloc will release no-longer-used memory back to the +kernel gradually, over time. The tcmalloc_release_rate flag controls how quickly +this happens. You can also force a release at a given point in the +progam execution like so:

+
+   MallocExtension::instance()->ReleaseFreeMemory();
+
+ +

You can also call SetMemoryReleaseRate() to change the +tcmalloc_release_rate value at runtime, or +GetMemoryReleaseRate to see what the current release rate +is.

+ +

Memory Introspection

+ +

There are several routines for getting a human-readable form of the +current memory usage:

+
+   MallocExtension::instance()->GetStats(buffer, buffer_length);
+   MallocExtension::instance()->GetHeapSample(&string);
+   MallocExtension::instance()->GetHeapGrowthStacks(&string);
+
+ +

The last two create files in the same format as the heap-profiler, +and can be passed as data files to pprof. The first is human-readable +and is meant for debugging.

+ +

Generic Tcmalloc Status

+ +

TCMalloc has support for setting and retrieving arbitrary +'properties':

+
+   MallocExtension::instance()->SetNumericProperty(property_name, value);
+   MallocExtension::instance()->GetNumericProperty(property_name, &value);
+
+ +

It is possible for an application to set and get these properties, +but the most useful is when a library sets the properties so the +application can read them. Here are the properties TCMalloc defines; +you can access them with a call like +MallocExtension::instance()->GetNumericProperty("generic.heap_size", +&value);:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
generic.current_allocated_bytes + Number of bytes used by the application. This will not typically + match the memory use reported by the OS, because it does not + include TCMalloc overhead or memory fragmentation. +
generic.heap_size + Bytes of system memory reserved by TCMalloc. +
tcmalloc.pageheap_free_bytes + Number of bytes in free, mapped pages in page heap. These bytes + can be used to fulfill allocation requests. They always count + towards virtual memory usage, and unless the underlying memory is + swapped out by the OS, they also count towards physical memory + usage. +
tcmalloc.pageheap_unmapped_bytes + Number of bytes in free, unmapped pages in page heap. These are + bytes that have been released back to the OS, possibly by one of + the MallocExtension "Release" calls. They can be used to fulfill + allocation requests, but typically incur a page fault. They + always count towards virtual memory usage, and depending on the + OS, typically do not count towards physical memory usage. +
tcmalloc.slack_bytes + Sum of pageheap_free_bytes and pageheap_unmapped_bytes. Provided + for backwards compatibility only. Do not use. +
tcmalloc.max_total_thread_cache_bytes + A limit to how much memory TCMalloc dedicates for small objects. + Higher numbers trade off more memory use for -- in some situations + -- improved efficiency. +
tcmalloc.current_total_thread_cache_bytes + A measure of some of the memory TCMalloc is using (for + small objects). +
+ +

Caveats

+ +

For some systems, TCMalloc may not work correctly with +applications that aren't linked against libpthread.so (or +the equivalent on your OS). It should work on Linux using glibc 2.3, +but other OS/libc combinations have not been tested.

+ +

TCMalloc may be somewhat more memory hungry than other mallocs, +(but tends not to have the huge blowups that can happen with other +mallocs). In particular, at startup TCMalloc allocates approximately +240KB of internal memory.

+ +

Don't try to load TCMalloc into a running binary (e.g., using JNI +in Java programs). The binary will have allocated some objects using +the system malloc, and may try to pass them to TCMalloc for +deallocation. TCMalloc will not be able to handle such objects.

+ +
+ +
Sanjay Ghemawat, Paul Menage
+ + +Last modified: Sat Feb 24 13:11:38 PST 2007 (csilvers) + +
+ + + diff --git a/trunk/3rdparty/gperftools-2-fit/docs/threadheap.dot b/trunk/3rdparty/gperftools-2-fit/docs/threadheap.dot new file mode 100644 index 000000000..b2dba7203 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/docs/threadheap.dot @@ -0,0 +1,21 @@ +digraph ThreadHeap { +rankdir=LR +node [shape=box, width=0.3, height=0.3] +nodesep=.05 + +heap [shape=record, height=2, label="class 0|class 1|class 2|..."] +O0 [label=""] +O1 [label=""] +O2 [label=""] +O3 [label=""] +O4 [label=""] +O5 [label=""] +sep1 [shape=plaintext, label="..."] +sep2 [shape=plaintext, label="..."] +sep3 [shape=plaintext, label="..."] + +heap:f0 -> O0 -> O1 -> sep1 +heap:f1 -> O2 -> O3 -> sep2 +heap:f2 -> O4 -> O5 -> sep3 + +} diff --git a/trunk/3rdparty/gperftools-2-fit/docs/threadheap.gif b/trunk/3rdparty/gperftools-2-fit/docs/threadheap.gif new file mode 100644 index 0000000000000000000000000000000000000000..c43d0a31018143264bd5ab8b3d7e36a03e833ff9 GIT binary patch literal 7571 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 literal 0 HcmV?d00001 diff --git a/trunk/3rdparty/gperftools-2-fit/gperftools.sln b/trunk/3rdparty/gperftools-2-fit/gperftools.sln new file mode 100644 index 000000000..1f1483c59 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/gperftools.sln @@ -0,0 +1,307 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtcmalloc_minimal", "vsprojects\libtcmalloc_minimal\libtcmalloc_minimal.vcxproj", "{55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcmalloc_minimal_unittest", "vsprojects\tcmalloc_minimal_unittest\tcmalloc_minimal_unittest.vcxproj", "{7CC73D97-C057-43A6-82EF-E6B567488D02}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcmalloc_minimal_large_unittest", "vsprojects\tcmalloc_minimal_large\tcmalloc_minimal_large_unittest.vcxproj", "{2D8B9599-C74C-4298-B723-6CF6077563E3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "addressmap_unittest", "vsprojects\addressmap_unittest\addressmap_unittest.vcxproj", "{32EECEB6-7D18-477E-BC7A-30CE98457A88}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "frag_unittest", "vsprojects\frag_unittest\frag_unittest.vcxproj", "{24754725-DE0D-4214-8979-324247AAD78E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "low_level_alloc_unittest", "vsprojects\low_level_alloc_unittest\low_level_alloc_unittest.vcxproj", "{A765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "malloc_hook_test", "vsprojects\malloc_hook_test\malloc_hook_test.vcxproj", "{3765198D-AA05-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "malloc_extension_test", "vsprojects\malloc_extension_test\malloc_extension_test.vcxproj", "{3765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "markidle_unittest", "vsprojects\markidle_unittest\markidle_unittest.vcxproj", "{4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "current_allocated_bytes_test", "vsprojects\current_allocated_bytes_test\current_allocated_bytes_test.vcxproj", "{4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packed-cache_test", "vsprojects\packed-cache_test\packed-cache_test.vcxproj", "{605D3CED-B530-424E-B7D2-2A31F14FD570}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pagemap_unittest", "vsprojects\pagemap_unittest\pagemap_unittest.vcxproj", "{9765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "page_heap_test", "vsprojects\page_heap_test\page_heap_test.vcxproj", "{9765198D-5305-4AB0-9A21-A0CD8201EB2B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "realloc_unittest", "vsprojects\realloc_unittest\realloc_unittest.vcxproj", "{4765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sampler_test", "vsprojects\sampler_test\sampler_test.vcxproj", "{B765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stack_trace_table_test", "vsprojects\stack_trace_table_test\stack_trace_table_test.vcxproj", "{A4754725-DE0D-4214-8979-324247AAD78E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "thread_dealloc_unittest", "vsprojects\thread_dealloc_unittest\thread_dealloc_unittest.vcxproj", "{6CFFBD0F-09E3-4282-A711-0564451FDF74}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "preamble_patcher_test", "vsprojects\preamble_patcher_test\preamble_patcher_test.vcxproj", "{5765198D-5305-4AB0-9A21-A0CD8201EB2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "addr2line-pdb", "vsprojects\addr2line-pdb\addr2line-pdb.vcxproj", "{81CA712E-90B8-4AE5-9E89-5B436578D6DA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nm-pdb", "vsprojects\nm-pdb\nm-pdb.vcxproj", "{3A559C75-FD26-4300-B86B-165FD43EE1CE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "system-alloc_unittest", "vsprojects\system-alloc_unittest\system-alloc_unittest.vcxproj", "{387F753A-0312-4A7B-A1D6-B2795E832E96}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release-Override|x64 = Release-Override|x64 + Release-Override|x86 = Release-Override|x86 + Release-Patch|x64 = Release-Patch|x64 + Release-Patch|x86 = Release-Patch|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Debug|x64.ActiveCfg = Debug|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Debug|x64.Build.0 = Debug|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Debug|x86.ActiveCfg = Debug|Win32 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Debug|x86.Build.0 = Debug|Win32 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Override|x64.Build.0 = Release-Override|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Override|x86.Build.0 = Release-Override|Win32 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Debug|x64.ActiveCfg = Debug|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Debug|x64.Build.0 = Debug|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Debug|x86.ActiveCfg = Debug|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Debug|x86.Build.0 = Debug|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Override|x64.Build.0 = Release-Override|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Override|x86.Build.0 = Release-Override|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {7CC73D97-C057-43A6-82EF-E6B567488D02}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Debug|x64.ActiveCfg = Debug|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Debug|x64.Build.0 = Debug|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Debug|x86.ActiveCfg = Debug|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Debug|x86.Build.0 = Debug|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Override|x64.Build.0 = Release-Override|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Override|x86.Build.0 = Release-Override|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {2D8B9599-C74C-4298-B723-6CF6077563E3}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Debug|x64.ActiveCfg = Debug|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Debug|x64.Build.0 = Debug|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Debug|x86.ActiveCfg = Debug|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Debug|x86.Build.0 = Debug|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Override|x64.Build.0 = Release-Override|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Override|x86.Build.0 = Release-Override|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {32EECEB6-7D18-477E-BC7A-30CE98457A88}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Debug|x64.ActiveCfg = Debug|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Debug|x64.Build.0 = Debug|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Debug|x86.ActiveCfg = Debug|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Debug|x86.Build.0 = Debug|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x64.Build.0 = Release-Override|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x86.Build.0 = Release-Override|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {24754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {A765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {3765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x64.ActiveCfg = Debug|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x64.Build.0 = Debug|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x86.ActiveCfg = Debug|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x86.Build.0 = Debug|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x64.Build.0 = Release-Override|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x86.Build.0 = Release-Override|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x64.ActiveCfg = Debug|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x64.Build.0 = Debug|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x86.ActiveCfg = Debug|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Debug|x86.Build.0 = Debug|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x64.Build.0 = Release-Override|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Override|x86.Build.0 = Release-Override|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug|x64.ActiveCfg = Debug|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug|x64.Build.0 = Debug|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug|x86.ActiveCfg = Debug|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Debug|x86.Build.0 = Debug|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Override|x64.Build.0 = Release-Override|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Override|x86.Build.0 = Release-Override|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {605D3CED-B530-424E-B7D2-2A31F14FD570}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Debug|x64.ActiveCfg = Debug|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Debug|x64.Build.0 = Debug|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Debug|x86.ActiveCfg = Debug|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Debug|x86.Build.0 = Debug|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Override|x64.Build.0 = Release-Override|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Override|x86.Build.0 = Release-Override|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {9765198D-5305-4AB0-9A21-A0CD8201EB2B}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {4765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.Build.0 = Debug|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.Build.0 = Debug|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.Build.0 = Release-Override|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.Build.0 = Release-Override|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {B765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Debug|x64.ActiveCfg = Debug|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Debug|x64.Build.0 = Debug|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Debug|x86.ActiveCfg = Debug|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Debug|x86.Build.0 = Debug|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x64.Build.0 = Release-Override|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Override|x86.Build.0 = Release-Override|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {A4754725-DE0D-4214-8979-324247AAD78E}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug|x64.ActiveCfg = Debug|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug|x64.Build.0 = Debug|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug|x86.ActiveCfg = Debug|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Debug|x86.Build.0 = Debug|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Override|x64.Build.0 = Release-Override|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Override|x86.Build.0 = Release-Override|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {6CFFBD0F-09E3-4282-A711-0564451FDF74}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x64.ActiveCfg = Debug|x64 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Debug|x86.ActiveCfg = Debug|Win32 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {5765198D-5305-4AB0-9A21-A0CD8201EB2A}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug|x64.ActiveCfg = Debug|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug|x64.Build.0 = Debug|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug|x86.ActiveCfg = Debug|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Debug|x86.Build.0 = Debug|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Override|x64.Build.0 = Release-Override|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Override|x86.Build.0 = Release-Override|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {81CA712E-90B8-4AE5-9E89-5B436578D6DA}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Debug|x64.ActiveCfg = Debug|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Debug|x64.Build.0 = Debug|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Debug|x86.ActiveCfg = Debug|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Debug|x86.Build.0 = Debug|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Override|x64.Build.0 = Release-Override|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Override|x86.Build.0 = Release-Override|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {3A559C75-FD26-4300-B86B-165FD43EE1CE}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug|x64.ActiveCfg = Debug|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug|x64.Build.0 = Debug|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug|x86.ActiveCfg = Debug|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Debug|x86.Build.0 = Debug|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Override|x64.ActiveCfg = Release-Override|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Override|x64.Build.0 = Release-Override|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Override|x86.ActiveCfg = Release-Override|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Override|x86.Build.0 = Release-Override|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Patch|x64.ActiveCfg = Release-Patch|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Patch|x64.Build.0 = Release-Patch|x64 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Patch|x86.ActiveCfg = Release-Patch|Win32 + {387F753A-0312-4A7B-A1D6-B2795E832E96}.Release-Patch|x86.Build.0 = Release-Patch|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/trunk/3rdparty/gperftools-2-fit/install-sh b/trunk/3rdparty/gperftools-2-fit/install-sh new file mode 100755 index 000000000..ec298b537 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/install-sh @@ -0,0 +1,541 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2020-11-14.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 + +backupsuffix= +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. + -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -p) cpprog="$cpprog -p";; + + -s) stripcmd=$stripprog;; + + -S) backupsuffix="$2" + shift;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi + + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/trunk/3rdparty/gperftools-2-fit/libtool b/trunk/3rdparty/gperftools-2-fit/libtool new file mode 100755 index 000000000..7ed60a9d4 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/libtool @@ -0,0 +1,11911 @@ +#! /bin/sh +# Generated automatically by config.status (gperftools) 2.9.1 +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: ${LT_SYS_LIBRARY_PATH=""} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=2.4.6 +macro_revision=2.4.6 + +# Whether or not to build shared libraries. +build_libtool_libs=yes + +# Whether or not to build static libraries. +build_old_libs=yes + +# What type of objects to build. +pic_mode=default + +# Whether or not to optimize for fast installation. +fast_install=needless + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec= + +# Shell to use when invoking shell scripts. +SHELL="/bin/sh" + +# An echo program that protects backslashes. +ECHO="printf %s\\n" + +# The PATH separator for the build system. +PATH_SEPARATOR=":" + +# The host system. +host_alias= +host=x86_64-pc-linux-gnu +host_os=linux-gnu + +# The build system. +build_alias= +build=x86_64-pc-linux-gnu +build_os=linux-gnu + +# A sed program that does not truncate output. +SED="/bin/sed" + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP="/bin/grep" + +# An ERE matcher. +EGREP="/bin/grep -E" + +# A literal string matcher. +FGREP="/bin/grep -F" + +# A BSD- or MS-compatible name lister. +NM="/usr/bin/nm -B" + +# Whether we need soft or hard links. +LN_S="ln -s" + +# What is the maximum length of a command? +max_cmd_len=1572864 + +# Object file suffix (normally "o"). +objext=o + +# Executable file suffix (normally ""). +exeext= + +# whether the shell understands "unset". +lt_unset=unset + +# turn spaces into newlines. +SP2NL="tr \\040 \\012" + +# turn newlines into spaces. +NL2SP="tr \\015\\012 \\040\\040" + +# convert $build file names to $host format. +to_host_file_cmd=func_convert_file_noop + +# convert $build files to toolchain format. +to_tool_file_cmd=func_convert_file_noop + +# An object symbol dumper. +OBJDUMP="objdump" + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method="pass_all" + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd="\$MAGIC_CMD" + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob="" + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob="no" + +# DLL creation program. +DLLTOOL="false" + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd="printf %s\\n" + +# The archiver. +AR="ar" + +# Flags to create an archive. +AR_FLAGS="cr" + +# How to feed a file listing to the archiver. +archiver_list_spec="@" + +# A symbol stripping program. +STRIP="strip" + +# Commands used to install an old-style archive. +RANLIB="ranlib" +old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$tool_oldlib" +old_postuninstall_cmds="" + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=no + +# A C compiler. +LTCC="gcc" + +# LTCC compiler flags. +LTCFLAGS="-g -O2" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p' | sed '/ __gnu_lto/d'" + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/extern char \\1;/p'" + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import="" + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p'" + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(lib.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"lib\\1\", (void *) \\&\\1},/p'" + +# The name lister interface. +nm_interface="BSD nm" + +# Specify filename containing input files for $NM. +nm_file_list_spec="@" + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot= + +# Command to truncate a binary pipe. +lt_truncate_bin="/bin/dd bs=4096 count=1" + +# The name of the directory that contains temporary libtool files. +objdir=.libs + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=file + +# Must we lock files when doing compilation? +need_locks="no" + +# Manifest tool. +MANIFEST_TOOL=":" + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL="" + +# Tool to change global to local symbols on Mac OS X. +NMEDIT="" + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO="" + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL="" + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64="" + +# Old archive suffix (normally "a"). +libext=a + +# Shared library suffix (normally ".so"). +shrext_cmds=".so" + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds="" + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + +# Do we need the "lib" prefix for modules? +need_lib_prefix=no + +# Do we need a version for libraries? +need_version=no + +# Library versioning type. +version_type=linux + +# Shared library runtime path variable. +runpath_var=LD_RUN_PATH + +# Shared library path variable. +shlibpath_var=LD_LIBRARY_PATH + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=yes + +# Format of library name prefix. +libname_spec="lib\$name" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec="\$libname\$release\$shared_ext\$versuffix \$libname\$release\$shared_ext\$major \$libname\$shared_ext" + +# The coded name of the library, if different from the real name. +soname_spec="\$libname\$release\$shared_ext\$major" + +# Permission mode override for installation of shared libraries. +install_override_mode="" + +# Command to use after installation of a shared archive. +postinstall_cmds="" + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds="" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir" + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval="" + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=yes + +# Compile-time system search path for libraries. +sys_lib_search_path_spec="/usr/lib/gcc/x86_64-linux-gnu/10 /usr/lib/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib " + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/x86_64-linux-gnu/libfakeroot /usr/local/lib/i386-linux-gnu /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /usr/local/lib/i686-linux-gnu /lib/i686-linux-gnu /usr/lib/i686-linux-gnu /usr/local/lib /usr/local/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /lib32 /usr/lib32 /libx32 /usr/libx32 " + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path="" + +# Whether dlopen is supported. +dlopen_support=unknown + +# Whether dlopen of programs is supported. +dlopen_self=unknown + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=unknown + +# Commands to strip libraries. +old_striplib="strip --strip-debug" +striplib="strip --strip-unneeded" + + +# The linker used to build libraries. +LD="/usr/bin/ld -m elf_x86_64" + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# Commands used to build an old-style archive. +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$tool_oldlib" + +# A language specific compiler. +CC="gcc" + +# Is the compiler the GNU compiler? +with_gcc=yes + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# Additional compiler flags for building library objects. +pic_flag=" -fPIC -DPIC" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=no + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=no + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\$wl--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\$wl--whole-archive\$convenience \$wl--no-whole-archive" + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object="no" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build a shared archive. +archive_cmds="\$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \$wl-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="echo \\\"{ global:\\\" > \$output_objdir/\$libname.ver~ + cat \$export_symbols | sed -e \\\"s/\\\\(.*\\\\)/\\\\1;/\\\" >> \$output_objdir/\$libname.ver~ + echo \\\"local: *; };\\\" >> \$output_objdir/\$libname.ver~ + \$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \$wl-soname \$wl\$soname \$wl-version-script \$wl\$output_objdir/\$libname.ver -o \$lib" + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds="" +module_expsym_cmds="" + +# Whether we are building with GNU ld or not. +with_gnu_ld="yes" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that enforces no undefined symbols. +no_undefined_flag="" + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist +hardcode_libdir_flag_spec="\$wl-rpath \$wl\$libdir" + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator="" + +# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=no + +# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting $shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=no + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=no + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=no + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=no + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=no + +# Set to "yes" if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*" + +# Symbols that must always be exported. +include_expsyms="" + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds="" + +# Commands necessary for finishing linking programs. +postlink_cmds="" + +# Specify filename containing input files. +file_list_spec="" + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs="" + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects="" +postdep_objects="" +predeps="" +postdeps="" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="" + +# ### END LIBTOOL CONFIG + + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-15" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-07.11; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote_for_eval ${1+"$@"} +# # my_options_prep_result=$func_quote_for_eval_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_rc_options=false + + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote_for_eval ${1+"$@"} + func_options_result=$func_quote_for_eval_result + fi + + $_G_rc_options +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi + + $_G_rc_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_parse_options +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-15 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + # -static-* direct GCC to link specific libraries statically + # -fcilkplus Cilk Plus language extension features for C/C++ + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD="/usr/bin/ld -m elf_x86_64" + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# Commands used to build an old-style archive. +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$tool_oldlib" + +# A language specific compiler. +CC="g++ -std=gnu++11" + +# Is the compiler the GNU compiler? +with_gcc=yes + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# Additional compiler flags for building library objects. +pic_flag=" -fPIC -DPIC" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=no + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=no + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\$wl--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\$wl--whole-archive\$convenience \$wl--no-whole-archive" + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object="no" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build a shared archive. +archive_cmds="\$CC \$pic_flag -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \$wl-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="\$CC \$pic_flag -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \$wl-soname \$wl\$soname \$wl-retain-symbols-file \$wl\$export_symbols -o \$lib" + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds="" +module_expsym_cmds="" + +# Whether we are building with GNU ld or not. +with_gnu_ld="yes" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that enforces no undefined symbols. +no_undefined_flag="" + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist +hardcode_libdir_flag_spec="\$wl-rpath \$wl\$libdir" + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator="" + +# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=no + +# Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting $shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=no + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=no + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=no + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=no + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=no + +# Set to "yes" if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*" + +# Symbols that must always be exported. +include_expsyms="" + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds="" + +# Commands necessary for finishing linking programs. +postlink_cmds="" + +# Specify filename containing input files. +file_list_spec="" + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs="/usr/lib/gcc/x86_64-linux-gnu/10 /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu /usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /usr/lib/gcc/x86_64-linux-gnu/10/../../.." + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects="/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o" +postdep_objects="/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o" +predeps="" +postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="-L/usr/lib/gcc/x86_64-linux-gnu/10 -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/10/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/10/../../.." + +# ### END LIBTOOL TAG CONFIG: CXX diff --git a/trunk/3rdparty/gperftools-2-fit/ltmain.sh b/trunk/3rdparty/gperftools-2-fit/ltmain.sh new file mode 100755 index 000000000..21e5e0784 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/ltmain.sh @@ -0,0 +1,11251 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-15" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-07.11; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote_for_eval ${1+"$@"} +# # my_options_prep_result=$func_quote_for_eval_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_rc_options=false + + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote_for_eval ${1+"$@"} + func_options_result=$func_quote_for_eval_result + fi + + $_G_rc_options +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi + + $_G_rc_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_parse_options +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-15 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result + fi + + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + # -fuse-ld=* Linker select flags for GCC + # -static-* direct GCC to link specific libraries statically + # -fcilkplus Cilk Plus language extension features for C/C++ + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ac_have_attribute.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ac_have_attribute.m4 new file mode 100644 index 000000000..19f4021e9 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ac_have_attribute.m4 @@ -0,0 +1,16 @@ +AC_DEFUN([AX_C___ATTRIBUTE__], [ + AC_MSG_CHECKING(for __attribute__) + AC_CACHE_VAL(ac_cv___attribute__, [ + AC_TRY_COMPILE( + [#include + static void foo(void) __attribute__ ((unused)); + void foo(void) { exit(1); }], + [], + ac_cv___attribute__=yes, + ac_cv___attribute__=no + )]) + if test "$ac_cv___attribute__" = "yes"; then + AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__]) + fi + AC_MSG_RESULT($ac_cv___attribute__) +]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/acx_nanosleep.m4 b/trunk/3rdparty/gperftools-2-fit/m4/acx_nanosleep.m4 new file mode 100644 index 000000000..1d443926f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/acx_nanosleep.m4 @@ -0,0 +1,35 @@ +# Check for support for nanosleep. It's defined in , but on +# some systems, such as solaris, you need to link in a library to use it. +# We set acx_nanosleep_ok if nanosleep is supported; in that case, +# NANOSLEEP_LIBS is set to whatever libraries are needed to support +# nanosleep. + +AC_DEFUN([ACX_NANOSLEEP], +[AC_MSG_CHECKING(if nanosleep requires any libraries) + AC_LANG_SAVE + AC_LANG_C + acx_nanosleep_ok="no" + NANOSLEEP_LIBS= + # For most folks, this should just work + AC_TRY_LINK([#include ], + [static struct timespec ts; nanosleep(&ts, NULL);], + [acx_nanosleep_ok=yes]) + # For solaris, we may need -lrt + if test "x$acx_nanosleep_ok" != "xyes"; then + OLD_LIBS="$LIBS" + LIBS="-lrt $LIBS" + AC_TRY_LINK([#include ], + [static struct timespec ts; nanosleep(&ts, NULL);], + [acx_nanosleep_ok=yes]) + if test "x$acx_nanosleep_ok" = "xyes"; then + NANOSLEEP_LIBS="-lrt" + fi + LIBS="$OLD_LIBS" + fi + if test "x$acx_nanosleep_ok" != "xyes"; then + AC_MSG_ERROR([cannot find the nanosleep function]) + else + AC_MSG_RESULT(${NANOSLEEP_LIBS:-no}) + fi + AC_LANG_RESTORE +]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/acx_pthread.m4 b/trunk/3rdparty/gperftools-2-fit/m4/acx_pthread.m4 new file mode 100644 index 000000000..89d42c744 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/acx_pthread.m4 @@ -0,0 +1,397 @@ +# This was retrieved from +# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi +# See also (perhaps for new versions?) +# http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi +# +# We've rewritten the inconsistency check code (from avahi), to work +# more broadly. In particular, it no longer assumes ld accepts -zdefs. +# This caused a restructing of the code, but the functionality has only +# changed a little. + +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl @summary figure out how to build C programs using POSIX threads +dnl +dnl This macro figures out how to build C programs using POSIX threads. +dnl It sets the PTHREAD_LIBS output variable to the threads library and +dnl linker flags, and the PTHREAD_CFLAGS output variable to any special +dnl C compiler flags that are needed. (The user can also force certain +dnl compiler flags/libs to be tested by setting these environment +dnl variables.) +dnl +dnl Also sets PTHREAD_CC to any special C compiler that is needed for +dnl multi-threaded programs (defaults to the value of CC otherwise). +dnl (This is necessary on AIX to use the special cc_r compiler alias.) +dnl +dnl NOTE: You are assumed to not only compile your program with these +dnl flags, but also link it with them as well. e.g. you should link +dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +dnl $LIBS +dnl +dnl If you are only building threads programs, you may wish to use +dnl these variables in your default LIBS, CFLAGS, and CC: +dnl +dnl LIBS="$PTHREAD_LIBS $LIBS" +dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +dnl CC="$PTHREAD_CC" +dnl +dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +dnl +dnl ACTION-IF-FOUND is a list of shell commands to run if a threads +dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to +dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the +dnl default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, or +dnl if you have any other suggestions or comments. This macro was based +dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with +dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros +dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. +dnl We are also grateful for the helpful feedback of numerous users. +dnl +dnl @category InstalledPackages +dnl @author Steven G. Johnson +dnl @version 2006-05-29 +dnl @license GPLWithACException +dnl +dnl Checks for GCC shared/pthread inconsistency based on work by +dnl Marcin Owsiany + + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include ], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi + + # The next part tries to detect GCC inconsistency with -shared on some + # architectures and systems. The problem is that in certain + # configurations, when -shared is specified, GCC "forgets" to + # internally use various flags which are still necessary. + + # + # Prepare the flags + # + save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + save_CC="$CC" + + # Try with the flags determined by the earlier checks. + # + # -Wl,-z,defs forces link-time symbol resolution, so that the + # linking checks with -shared actually have any value + # + # FIXME: -fPIC is required for -shared on many architectures, + # so we specify it here, but the right way would probably be to + # properly detect whether it is actually required. + CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CC="$PTHREAD_CC" + + # In order not to create several levels of indentation, we test + # the value of "$done" until we find the cure or run out of ideas. + done="no" + + # First, make sure the CFLAGS we added are actually accepted by our + # compiler. If not (and OS X's ld, for instance, does not accept -z), + # then we can't do this test. + if test x"$done" = xno; then + AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies]) + AC_TRY_LINK(,, , [done=yes]) + + if test "x$done" = xyes ; then + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([yes]) + fi + fi + + if test x"$done" = xno; then + AC_MSG_CHECKING([whether -pthread is sufficient with -shared]) + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + fi + + # + # Linux gcc on some architectures such as mips/mipsel forgets + # about -lpthread + # + if test x"$done" = xno; then + AC_MSG_CHECKING([whether -lpthread fixes that]) + LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" + else + AC_MSG_RESULT([no]) + fi + fi + # + # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc + # + if test x"$done" = xno; then + AC_MSG_CHECKING([whether -lc_r fixes that]) + LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" + else + AC_MSG_RESULT([no]) + fi + fi + if test x"$done" = xno; then + # OK, we have run out of ideas + AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries]) + + # so it's not safe to assume that we may use pthreads + acx_pthread_ok=no + fi + + AC_MSG_CHECKING([whether what we have so far is sufficient with -nostdlib]) + CFLAGS="-nostdlib $CFLAGS" + # we need c with nostdlib + LIBS="$LIBS -lc" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes],[done=no]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + if test x"$done" = xno; then + AC_MSG_CHECKING([whether -lpthread saves the day]) + LIBS="-lpthread $LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [done=yes],[done=no]) + + if test "x$done" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries and -nostdlib]) + fi + fi + + CFLAGS="$save_CFLAGS" + LIBS="$save_LIBS" + CC="$save_CC" +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ax_cxx_compile_stdcxx.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 000000000..9e9eaedaa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,948 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ax_generate_changelog.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ax_generate_changelog.m4 new file mode 100644 index 000000000..d9d5cd105 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ax_generate_changelog.m4 @@ -0,0 +1,99 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_generate_changelog.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_GENERATE_CHANGELOG() +# +# DESCRIPTION +# +# Builds a rule for generating a ChangeLog file from version control +# system commit messages. Currently, the only supported VCS is git, but +# support for others could be added in future. +# +# Defines GENERATE_CHANGELOG_RULES which should be substituted in your +# Makefile. +# +# Usage example: +# +# configure.ac: +# +# AX_GENERATE_CHANGELOG +# +# Makefile.am: +# +# @GENERATE_CHANGELOG_RULES@ +# CHANGELOG_START = 0.2.3^ +# dist-hook: dist-ChangeLog +# +# ChangeLog (stub committed to VCS): +# +# The ChangeLog is auto-generated when releasing. +# If you are seeing this, use 'git log' for a detailed list of changes. +# +# This results in a "dist-ChangeLog" rule being added to the Makefile. +# When run, "dist-ChangeLog" will generate a ChangeLog in the +# $(top_distdir), using $(CHANGELOG_GIT_FLAGS) to format the output from +# "git log" being run in $(CHANGELOG_GIT_DIR). +# +# Unless Automake is initialised with the 'foreign' option, a dummy +# ChangeLog file must be committed to VCS in $(top_srcdir), containing the +# text above (for example). It will be substituted by the automatically +# generated ChangeLog during "make dist". +# +# LICENSE +# +# Copyright (c) 2015 David King +# Copyright (c) 2015 Philip Withnall +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_GENERATE_CHANGELOG],[ + # Find git, defaulting to the 'missing' script so the user gets a nice + # message if git is missing, rather than a plain 'command not found'. + AC_PATH_PROG([GIT],[git],[${am_missing_run}git]) + AC_SUBST([GIT]) + + # Build the ChangeLog rules. + m4_pattern_allow([AM_V_GEN]) +GENERATE_CHANGELOG_RULES=' +# Generate ChangeLog +# +# Optional: +# - CHANGELOG_START: git commit ID or tag name to output changelogs from +# (exclusive). (Default: include all commits) +# - CHANGELOG_GIT_FLAGS: General flags to pass to git-log when generating the +# ChangeLog. (Default: various) +# - CHANGELOG_GIT_DIR: .git directory to use. (Default: $(top_srcdir)/.git) + +# git-specific +CHANGELOG_GIT_FLAGS ?= --stat -M -C --name-status --no-color +CHANGELOG_GIT_DIR ?= $(top_srcdir)/.git + +ifeq ($(CHANGELOG_START),) +CHANGELOG_GIT_RANGE = +else +CHANGELOG_GIT_RANGE = $(CHANGELOG_START).. +endif + +# Generate a ChangeLog in $(top_distdir) +dist-ChangeLog: + $(AM_V_GEN)if $(GIT) \ + --git-dir=$(CHANGELOG_GIT_DIR) --work-tree=$(top_srcdir) log \ + $(CHANGELOG_GIT_FLAGS) $(CHANGELOG_GIT_RANGE) \ + | fmt --split-only >.ChangeLog.tmp; \ + then mv -f .ChangeLog.tmp "$(top_distdir)/ChangeLog"; \ + else rm -f .ChangeLog.tmp; exit 1; fi + +.PHONY: dist-ChangeLog +' + + AC_SUBST([GENERATE_CHANGELOG_RULES]) + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([GENERATE_CHANGELOG_RULES])]) +]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/install_prefix.m4 b/trunk/3rdparty/gperftools-2-fit/m4/install_prefix.m4 new file mode 100644 index 000000000..ef33f42e6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/install_prefix.m4 @@ -0,0 +1,8 @@ +AC_DEFUN([AC_INSTALL_PREFIX], + [ac_cv_install_prefix="$prefix"; + if test x"$ac_cv_install_prefix" = x"NONE" ; then + ac_cv_install_prefix="$ac_default_prefix"; + fi + AC_DEFINE_UNQUOTED(INSTALL_PREFIX, "$ac_cv_install_prefix", + [prefix where we look for installed files]) + ]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/libtool.m4 b/trunk/3rdparty/gperftools-2-fit/m4/libtool.m4 new file mode 100644 index 000000000..c4c02946d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/libtool.m4 @@ -0,0 +1,8394 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*|11.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cr} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD + if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # flang / f18. f95 an alias for gfortran or flang on Debian + flang* | f18* | f95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ltoptions.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ltoptions.m4 new file mode 100644 index 000000000..94b082976 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ltsugar.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ltsugar.m4 new file mode 100644 index 000000000..48bc9344a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/ltversion.m4 b/trunk/3rdparty/gperftools-2-fit/m4/ltversion.m4 new file mode 100644 index 000000000..fa04b52a3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/lt~obsolete.m4 b/trunk/3rdparty/gperftools-2-fit/m4/lt~obsolete.m4 new file mode 100644 index 000000000..c6b26f88f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/pc_from_ucontext.m4 b/trunk/3rdparty/gperftools-2-fit/m4/pc_from_ucontext.m4 new file mode 100644 index 000000000..159b01df6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/pc_from_ucontext.m4 @@ -0,0 +1,112 @@ +# 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). + +# OpenBSD doesn't have ucontext.h, but we can get PC from ucontext_t +# by using signal.h. + +# The first argument of AC_PC_FROM_UCONTEXT will be invoked when we +# cannot find a way to obtain PC from ucontext. + +AC_DEFUN([AC_PC_FROM_UCONTEXT], + [AC_CHECK_HEADERS(ucontext.h) + # Redhat 7 has , but it barfs if we #include it directly + # (this was fixed in later redhats). works fine, so use that. + if grep "Red Hat Linux release 7" /etc/redhat-release >/dev/null 2>&1; then + AC_DEFINE(HAVE_SYS_UCONTEXT_H, 0, [ is broken on redhat 7]) + ac_cv_header_sys_ucontext_h=no + else + AC_CHECK_HEADERS(sys/ucontext.h) # ucontext on OS X 10.6 (at least) + fi + AC_CHECK_HEADERS(cygwin/signal.h) # ucontext on cywgin + AC_CHECK_HEADERS(asm/ptrace.h) # get ptrace macros, e.g. PT_NIP + 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.pc" # Linux (mips) + pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc) + pc_fields="$pc_fields uc_mcontext.__gregs[[REG_PC]]" # Linux (riscv64) + pc_fields="$pc_fields uc_mcontext.psw.addr" # Linux (s390) + pc_fields="$pc_fields uc_mcontext.gregs[[R15]]" # Linux (arm old [untested]) + pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm arch 5) + pc_fields="$pc_fields uc_mcontext.cr0_hi" # Linux (e2k) + pc_fields="$pc_fields uc_mcontext.gp_regs[[PT_NIP]]" # Suse SLES 11 (ppc64) + pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386) + pc_fields="$pc_fields uc_mcontext.mc_srr0" # FreeBSD (powerpc, powerpc64) + pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [untested]) + pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_EIP]]" # NetBSD (i386) + pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_RIP]]" # NetBSD (x86_64) + pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4) + pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5) + pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64) + pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (>=10.5 [untested]) + pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [untested]) + pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (>=10.5 [untested]) + pc_fields="$pc_fields uc_mcontext->__ss.__pc" # OS X (arm64) + pc_field_found=false + for pc_field in $pc_fields; do + if ! $pc_field_found; then + # Prefer sys/ucontext.h to ucontext.h, for OS X's sake. + if test "x$ac_cv_header_cygwin_signal_h" = xyes; then + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include ], + [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) + elif test "x$ac_cv_header_asm_ptrace_h" = xyes -a "x$ac_cv_header_sys_ucontext_h" = xyes; then + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include + #include ], + [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) + elif test "x$ac_cv_header_sys_ucontext_h" = xyes; then + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include ], + [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) + elif test "x$ac_cv_header_ucontext_h" = xyes; then + AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include ], + [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) + else # hope some standard header gives it to us + AC_TRY_COMPILE([], + [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 + fi + done + if ! $pc_field_found; then + pc_fields=" sc_eip" # OpenBSD (i386) + pc_fields="$pc_fields sc_rip" # OpenBSD (x86_64) + for pc_field in $pc_fields; do + if ! $pc_field_found; then + AC_TRY_COMPILE([#include ], + [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 + fi + if ! $pc_field_found; then + [$1] + fi]) diff --git a/trunk/3rdparty/gperftools-2-fit/m4/program_invocation_name.m4 b/trunk/3rdparty/gperftools-2-fit/m4/program_invocation_name.m4 new file mode 100644 index 000000000..6161f66d2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/m4/program_invocation_name.m4 @@ -0,0 +1,19 @@ +# 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;], + [return *program_invocation_name;], + [ac_cv_have_program_invocation_name=yes], + [ac_cv_have_program_invocation_name=no]) + ) + if test "$ac_cv_have_program_invocation_name" = "yes"; then + AC_DEFINE(HAVE_PROGRAM_INVOCATION_NAME, 1, + [define if libc has program_invocation_name]) + fi + ]) + diff --git a/trunk/3rdparty/gperftools-2-fit/missing b/trunk/3rdparty/gperftools-2-fit/missing new file mode 100755 index 000000000..8d0eaad25 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb.sh b/trunk/3rdparty/gperftools-2-fit/packages/deb.sh new file mode 100755 index 000000000..31b423c12 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb.sh @@ -0,0 +1,74 @@ +#!/bin/bash -e + +# This takes one commandline argument, the name of the package. If no +# name is given, then we'll end up just using the name associated with +# an arbitrary .tar.gz file in the rootdir. That's fine: there's probably +# only one. +# +# Run this from the 'packages' directory, just under rootdir + +## Set LIB to lib if exporting a library, empty-string else +LIB= +#LIB=lib + +PACKAGE="$1" +VERSION="$2" + +# We can only build Debian packages, if the Debian build tools are installed +if [ \! -x /usr/bin/debuild ]; then + echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2 + exit 0 +fi + +# Double-check we're in the packages directory, just under rootdir +if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then + echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2 + echo "Also, you must run \"make dist\" before running this script." 1>&2 + exit 0 +fi + +# Find the top directory for this package +topdir="${PWD%/*}" + +# Find the tar archive built by "make dist" +archive="${PACKAGE}-${VERSION}" +archive_with_underscore="${PACKAGE}_${VERSION}" +if [ -z "${archive}" ]; then + echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2 + exit 0 +fi + +# Create a pristine directory for building the Debian package files +trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM + +rm -rf tmp +mkdir -p tmp +cd tmp + +# Debian has very specific requirements about the naming of build +# directories, and tar archives. It also wants to write all generated +# packages to the parent of the source directory. We accommodate these +# requirements by building directly from the tar file. +ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz" +# Some version of debuilder want foo.orig.tar.gz with _ between versions. +ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive_with_underscore}.orig.tar.gz" +tar zfx "${LIB}${archive}.orig.tar.gz" +[ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}" +cd "${LIB}${archive}" +# This is one of those 'specific requirements': where the deb control files live +cp -a "packages/deb" "debian" + +# Now, we can call Debian's standard build tool +debuild -uc -us +cd ../.. # get back to the original top-level dir + +# We'll put the result in a subdirectory that's named after the OS version +# we've made this .deb file for. +destdir="debian-$(cat /etc/debian_version 2>/dev/null || echo UNKNOWN)" + +rm -rf "$destdir" +mkdir -p "$destdir" +mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir" + +echo +echo "The Debian package files are located in $PWD/$destdir" diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/README b/trunk/3rdparty/gperftools-2-fit/packages/deb/README new file mode 100644 index 000000000..57becfda7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/README @@ -0,0 +1,7 @@ +The list of files here isn't complete. For a step-by-step guide on +how to set this package up correctly, check out + http://www.debian.org/doc/maint-guide/ + +Most of the files that are in this directory are boilerplate. +However, you may need to change the list of binary-arch dependencies +in 'rules'. diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/changelog b/trunk/3rdparty/gperftools-2-fit/packages/deb/changelog new file mode 100644 index 000000000..d67df6113 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/changelog @@ -0,0 +1,208 @@ +gperftools (2.1-1) unstable; urgency=low + + * New upstream release. + + -- gperftools Contributors Tue, 30 Jul 2013 11:51:13 +0300 + +gperftools (2.0.99-1) unstable; urgency=low + + * New upstream release. + + -- gperftools Contributors Sat, 20 Jul 2013 14:21:10 -0700 + +gperftools (2.0-1) unstable; urgency=low + + * New upstream release. + * Package renamed from google-perftools to gperftools. + + -- Google Inc. and others Fri, 03 Feb 2012 15:40:45 -0800 + +google-perftools (1.10-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 31 Jan 2012 10:43:50 -0800 + +google-perftools (1.9-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 22 Dec 2011 16:22:45 -0800 + +google-perftools (1.8-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 15 Jul 2011 16:10:51 -0700 + +google-perftools (1.7-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 04 Feb 2011 15:54:31 -0800 + +google-perftools (1.6-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 05 Aug 2010 12:48:03 -0700 + +google-perftools (1.5-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 19 Jan 2010 14:46:12 -0800 + +google-perftools (1.4-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 10 Sep 2009 13:51:15 -0700 + +google-perftools (1.3-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 09 Jun 2009 18:19:06 -0700 + +google-perftools (1.2-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 17 Apr 2009 16:40:48 -0700 + +google-perftools (1.1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 11 Mar 2009 11:25:34 -0700 + +google-perftools (1.0-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 06 Jan 2009 13:58:56 -0800 + +google-perftools (1.0rc1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 11 Dec 2008 16:01:32 -0800 + +google-perftools (0.99.1-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Sat, 20 Sep 2008 09:37:18 -0700 + +google-perftools (0.99-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 18 Sep 2008 16:00:27 -0700 + +google-perftools (0.98-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, 09 Jun 2008 16:47:03 -0700 + +google-perftools (0.97-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, 21 Apr 2008 15:20:52 -0700 + +google-perftools (0.96-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 18 Mar 2008 14:30:44 -0700 + +google-perftools (0.95-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 12 Feb 2008 12:28:32 -0800 + +google-perftools (0.94-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 29 Nov 2007 07:59:43 -0800 + +google-perftools (0.93-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 17 Aug 2007 12:32:56 -0700 + +google-perftools (0.92-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 17 Jul 2007 22:26:27 -0700 + +google-perftools (0.91-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 18 Apr 2007 16:43:55 -0700 + +google-perftools (0.90-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 13 Apr 2007 14:50:51 -0700 + +google-perftools (0.8-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 14 Jun 2006 15:11:14 -0700 + +google-perftools (0.7-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Thu, 13 Apr 2006 20:59:09 -0700 + +google-perftools (0.6-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 27 Jan 2006 14:04:27 -0800 + +google-perftools (0.5-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Mon, Nov 14 17:28:59 2005 -0800 + +google-perftools (0.4-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Wed, 26 Oct 2005 15:19:16 -0700 + +google-perftools (0.3-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Fri, 24 Jun 2005 18:02:26 -0700 + +google-perftools (0.2-1) unstable; urgency=low + + * New upstream release. + + -- Google Inc. Tue, 31 May 2005 08:14:38 -0700 + +google-perftools (0.1-1) unstable; urgency=low + + * 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 Inc. Fri, 11 Mar 2005 08:07:33 -0800 diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/compat b/trunk/3rdparty/gperftools-2-fit/packages/deb/compat new file mode 100644 index 000000000..b8626c4cf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/compat @@ -0,0 +1 @@ +4 diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/control b/trunk/3rdparty/gperftools-2-fit/packages/deb/control new file mode 100644 index 000000000..37c34a518 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/control @@ -0,0 +1,25 @@ +Source: gperftools +Priority: optional +Maintainer: gperftools Contributors +Build-Depends: debhelper (>= 4.0.0), binutils +Standards-Version: 3.6.1 + +Package: libgperftools-dev +Section: libdevel +Architecture: any +Depends: libgperftools0 (= ${Source-Version}) +Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc + The gperftools 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. The + devel package contains static and debug libraries and header files + for developing applications that use the gperftools package. + +Package: libgperftools0 +Section: libs +Architecture: any +Depends: ${shlibs:Depends} +Description: libraries for CPU and heap analysis, plus an efficient thread-caching malloc + The gperftools 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/trunk/3rdparty/gperftools-2-fit/packages/deb/copyright b/trunk/3rdparty/gperftools-2-fit/packages/deb/copyright new file mode 100644 index 000000000..db7c78e36 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/copyright @@ -0,0 +1,38 @@ +This package was debianized by gperftools Contributors +on Sat, 20 Jul 2013 14:21:10 -0700. + +It was downloaded from http://code.google.com/p/gperftools/downloads/list + +Upstream Author: google-perftools@googlegroups.com + +Copyright (c) 2005, Google Inc. +All rights reserved. + +Copyright (c) 2013, gperftools Contributors +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. diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/docs b/trunk/3rdparty/gperftools-2-fit/packages/deb/docs new file mode 100644 index 000000000..fc4806f2a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/docs @@ -0,0 +1,47 @@ +AUTHORS +COPYING +ChangeLog +INSTALL +NEWS +README +TODO +docs/cpuprofile.html +docs/cpuprofile-fileformat.html +docs/designstyle.css +docs/heap-example1.png +docs/heap_checker.html +docs/heapprofile.html +docs/index.html +docs/overview.gif +docs/pageheap.gif +docs/pprof-test-big.gif +docs/pprof-test.gif +docs/pprof-vsnprintf-big.gif +docs/pprof-vsnprintf.gif +docs/pprof.1 +docs/pprof_remote_servers.html +docs/spanmap.gif +docs/t-test1.times.txt +docs/tcmalloc-opspercpusec.vs.threads.1024.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.128.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.131072.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.16384.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.2048.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.256.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.32768.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.4096.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.512.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.64.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.65536.bytes.png +docs/tcmalloc-opspercpusec.vs.threads.8192.bytes.png +docs/tcmalloc-opspersec.vs.size.1.threads.png +docs/tcmalloc-opspersec.vs.size.12.threads.png +docs/tcmalloc-opspersec.vs.size.16.threads.png +docs/tcmalloc-opspersec.vs.size.2.threads.png +docs/tcmalloc-opspersec.vs.size.20.threads.png +docs/tcmalloc-opspersec.vs.size.3.threads.png +docs/tcmalloc-opspersec.vs.size.4.threads.png +docs/tcmalloc-opspersec.vs.size.5.threads.png +docs/tcmalloc-opspersec.vs.size.8.threads.png +docs/tcmalloc.html +docs/threadheap.gif diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.dirs b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.dirs new file mode 100644 index 000000000..8f883479b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.dirs @@ -0,0 +1,5 @@ +usr/lib +usr/lib/pkgconfig +usr/include +usr/include/google +usr/include/gperftools diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.install b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.install new file mode 100644 index 000000000..e863529f3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools-dev.install @@ -0,0 +1,12 @@ +usr/include/google/* +usr/include/gperftools/* +usr/lib/lib*.so +usr/lib/lib*.a +usr/lib/*.la +usr/lib/pkgconfig/*.pc +debian/tmp/usr/include/google/* +debian/tmp/usr/include/gperftools/* +debian/tmp/usr/lib/lib*.so +debian/tmp/usr/lib/lib*.a +debian/tmp/usr/lib/*.la +debian/tmp/usr/lib/pkgconfig/*.pc diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.dirs b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.dirs new file mode 100644 index 000000000..14f5b95d7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.dirs @@ -0,0 +1,2 @@ +usr/lib +usr/bin diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.install b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.install new file mode 100644 index 000000000..047eed5c6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.install @@ -0,0 +1,4 @@ +usr/lib/lib*.so.* +usr/bin/pprof* +debian/tmp/usr/lib/lib*.so.* +debian/tmp/usr/bin/pprof* diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.manpages b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.manpages new file mode 100644 index 000000000..8ecbfc4aa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/libgperftools0.manpages @@ -0,0 +1 @@ +docs/pprof.1 diff --git a/trunk/3rdparty/gperftools-2-fit/packages/deb/rules b/trunk/3rdparty/gperftools-2-fit/packages/deb/rules new file mode 100755 index 000000000..f520befd2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/deb/rules @@ -0,0 +1,117 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +# shared library versions, option 1 +#version=2.0.5 +#major=2 +# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so +version=`ls src/.libs/lib*.so.* | \ + awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` +major=`ls src/.libs/lib*.so.* | \ + awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` + +config.status: configure + dh_testdir + # Add here commands to configure the package. + CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info + + +build: build-stamp +build-stamp: config.status + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) distclean +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/tmp + $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/trunk/3rdparty/gperftools-2-fit/packages/rpm.sh b/trunk/3rdparty/gperftools-2-fit/packages/rpm.sh new file mode 100755 index 000000000..448a0327f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/rpm.sh @@ -0,0 +1,86 @@ +#!/bin/sh -e + +# Run this from the 'packages' directory, just under rootdir + +# We can only build rpm packages, if the rpm build tools are installed +if [ \! -x /usr/bin/rpmbuild ] +then + echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2 + exit 0 +fi + +# Check the commandline flags +PACKAGE="$1" +VERSION="$2" +fullname="${PACKAGE}-${VERSION}" +archive=../$fullname.tar.gz + +if [ -z "$1" -o -z "$2" ] +then + echo "Usage: $0 " 1>&2 + exit 0 +fi + +# Double-check we're in the packages directory, just under rootdir +if [ \! -r ../Makefile -a \! -r ../INSTALL ] +then + echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2 + echo "Also, you must run \"make dist\" before running this script." 1>&2 + exit 0 +fi + +if [ \! -r "$archive" ] +then + echo "Cannot find $archive. Run \"make dist\" first." 1>&2 + exit 0 +fi + +# Create the directory where the input lives, and where the output should live +RPM_SOURCE_DIR="/tmp/rpmsource-$fullname" +RPM_BUILD_DIR="/tmp/rpmbuild-$fullname" + +trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM + +rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR" +mkdir "$RPM_SOURCE_DIR" +mkdir "$RPM_BUILD_DIR" + +cp "$archive" "$RPM_SOURCE_DIR" + +# rpmbuild -- as far as I can tell -- asks the OS what CPU it has. +# This may differ from what kind of binaries gcc produces. dpkg +# does a better job of this, so if we can run 'dpkg --print-architecture' +# to get the build CPU, we use that in preference of the rpmbuild +# default. +target=`dpkg --print-architecture 2>/dev/null || echo ""` +if [ -n "$target" ] +then + target=" --target $target" +fi + +rpmbuild -bb rpm/rpm.spec $target \ + --define "NAME $PACKAGE" \ + --define "VERSION $VERSION" \ + --define "_sourcedir $RPM_SOURCE_DIR" \ + --define "_builddir $RPM_BUILD_DIR" \ + --define "_rpmdir $RPM_SOURCE_DIR" + +# We put the output in a directory based on what system we've built for +destdir=rpm-unknown +if [ -r /etc/issue ] +then + grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7 + grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8 + grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9 + grep "Fedora Core.*release 1" /etc/issue >/dev/null 2>&1 && destdir=fc1 + grep "Fedora Core.*release 2" /etc/issue >/dev/null 2>&1 && destdir=fc2 + grep "Fedora Core.*release 3" /etc/issue >/dev/null 2>&1 && destdir=fc3 +fi + +rm -rf "$destdir" +mkdir -p "$destdir" +# We want to get not only the main package but devel etc, hence the middle * +mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir" + +echo +echo "The rpm package file(s) are located in $PWD/$destdir" diff --git a/trunk/3rdparty/gperftools-2-fit/packages/rpm/rpm.spec b/trunk/3rdparty/gperftools-2-fit/packages/rpm/rpm.spec new file mode 100644 index 000000000..0690e4f6a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/packages/rpm/rpm.spec @@ -0,0 +1,77 @@ +%define RELEASE 1 +%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE} +%define prefix /usr + +Name: %NAME +Summary: Performance tools for C++ +Version: %VERSION +Release: %rel +Group: Development/Libraries +URL: http://code.google.com/p/gperftools/ +License: BSD +Vendor: gperftools Contributors +Packager: gperftools Contributors +Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz +Distribution: Redhat 7 and above. +Buildroot: %{_tmppath}/%{name}-root +Prefix: %prefix + +%description +The %name packages 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. + +%package devel +Summary: Performance tools for C++ +Group: Development/Libraries +Requires: %{NAME} = %{VERSION} + +%description devel +The %name-devel package contains static and debug libraries and header +files for developing applications that use the %name package. + +%changelog + * Mon Apr 20 2009 + - Change build rule to use a configure line more like '%configure' + - Change install to use DESTDIR instead of prefix for configure + - Use wildcards for doc/ and lib/ directories + + * Fri Mar 11 2005 + - First draft + +%prep +%setup + +%build +# I can't use '% configure', because it defines -m32 which breaks some +# of the low-level atomicops files in this package. But I do take +# as much from % configure (in /usr/lib/rpm/macros) as I can. +./configure --prefix=%{_prefix} --exec-prefix=%{_exec_prefix} --bindir=%{_bindir} --sbindir=%{_sbindir} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --libexecdir=%{_libexecdir} --localstatedir=%{_localstatedir} --sharedstatedir=%{_sharedstatedir} --mandir=%{_mandir} --infodir=%{_infodir} +make + +%install +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) + +%docdir %{prefix}/share/doc/%{NAME}-%{VERSION} +%{prefix}/share/doc/%{NAME}-%{VERSION}/* + +%{_libdir}/*.so.* +%{_bindir}/pprof +%{_mandir}/man1/pprof.1* + +%files devel +%defattr(-,root,root) + +%{_includedir}/google +%{_includedir}/gperftools +%{_libdir}/*.a +%{_libdir}/*.la +%{_libdir}/*.so +%{_libdir}/pkgconfig/*.pc diff --git a/trunk/3rdparty/gperftools-2-fit/pprof-symbolize b/trunk/3rdparty/gperftools-2-fit/pprof-symbolize new file mode 100755 index 000000000..3a816c62e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/pprof-symbolize @@ -0,0 +1,5580 @@ +#! /usr/bin/env perl + +# Copyright (c) 1998-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. + +# --- +# Program for printing the profile generated by common/profiler.cc, +# or by the heap profiler (common/debugallocation.cc) +# +# The profile contains a sequence of entries of the form: +# +# This program parses the profile, and generates user-readable +# output. +# +# Examples: +# +# % tools/pprof "program" "profile" +# Enters "interactive" mode +# +# % tools/pprof --text "program" "profile" +# Generates one line per procedure +# +# % tools/pprof --gv "program" "profile" +# Generates annotated call-graph and displays via "gv" +# +# % tools/pprof --gv --focus=Mutex "program" "profile" +# Restrict to code paths that involve an entry that matches "Mutex" +# +# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile" +# Restrict to code paths that involve an entry that matches "Mutex" +# and does not match "string" +# +# % tools/pprof --list=IBF_CheckDocid "program" "profile" +# Generates disassembly listing of all routines with at least one +# sample that match the --list= pattern. The listing is +# annotated with the flat and cumulative sample counts at each line. +# +# % tools/pprof --disasm=IBF_CheckDocid "program" "profile" +# Generates disassembly listing of all routines with at least one +# sample that match the --disasm= pattern. The listing is +# annotated with the flat and cumulative sample counts at each PC value. +# +# TODO: Use color to indicate files? + +use strict; +use warnings; +use Getopt::Long; +use Cwd; +use POSIX; + +my $PPROF_VERSION = "2.0"; + +# These are the object tools we use which can come from a +# user-specified location using --tools, from the PPROF_TOOLS +# environment variable, or from the environment. +my %obj_tool_map = ( + "objdump" => "objdump", + "nm" => "nm", + "addr2line" => "addr2line", + "c++filt" => "c++filt", + ## ConfigureObjTools may add architecture-specific entries: + #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables + #"addr2line_pdb" => "addr2line-pdb", # ditto + #"otool" => "otool", # equivalent of objdump on OS X +); +# NOTE: these are lists, so you can put in commandline flags if you want. +my @DOT = ("dot"); # leave non-absolute, since it may be in /usr/local +my @GV = ("gv"); +my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread +my @KCACHEGRIND = ("kcachegrind"); +my @PS2PDF = ("ps2pdf"); +# These are used for dynamic profiles +my @URL_FETCHER = ("curl", "-s"); + +# These are the web pages that servers need to support for dynamic profiles +my $HEAP_PAGE = "/pprof/heap"; +my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#" +my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param + # ?seconds=#&event=x&period=n +my $GROWTH_PAGE = "/pprof/growth"; +my $CONTENTION_PAGE = "/pprof/contention"; +my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter +my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?"; +my $CENSUSPROFILE_PAGE = "/pprof/censusprofile(?:\\?.*)?"; # must support cgi-param + # "?seconds=#", + # "?tags_regexp=#" and + # "?type=#". +my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST +my $PROGRAM_NAME_PAGE = "/pprof/cmdline"; + +# These are the web pages that can be named on the command line. +# All the alternatives must begin with /. +my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" . + "$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" . + "$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)"; + +# default binary name +my $UNKNOWN_BINARY = "(unknown)"; + +# There is a pervasive dependency on the length (in hex characters, +# i.e., nibbles) of an address, distinguishing between 32-bit and +# 64-bit profiles. To err on the safe size, default to 64-bit here: +my $address_length = 16; + +my $dev_null = "/dev/null"; +if (! -e $dev_null && $^O =~ /MSWin/) { # $^O is the OS perl was built for + $dev_null = "nul"; +} + +# A list of paths to search for shared object files +my @prefix_list = (); + +# Special routine name that should not have any symbols. +# Used as separator to parse "addr2line -i" output. +my $sep_symbol = '_fini'; +my $sep_address = undef; + +my @stackTraces; + +##### Argument parsing ##### + +sub usage_string { + return < + is a space separated list of profile names. +$0 [options] + is a list of profile files where each file contains + the necessary symbol mappings as well as profile data (likely generated + with --raw). +$0 [options] + is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE + + Each name can be: + /path/to/profile - a path to a profile file + host:port[/] - a location of a service to get profile from + + The / can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile, + $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, + $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. + For instance: + $0 http://myserver.com:80$HEAP_PAGE + If / is omitted, the service defaults to $PROFILE_PAGE (cpu profiling). +$0 --symbols + Maps addresses to symbol names. In this mode, stdin should be a + list of library mappings, in the same format as is found in the heap- + and cpu-profile files (this loosely matches that of /proc/self/maps + on linux), followed by a list of hex addresses to map, one per line. + + For more help with querying remote servers, including how to add the + necessary server-side support code, see this filename (or one like it): + + /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html + +Options: + --cum Sort by cumulative data + --base= Subtract from before display + --interactive Run in interactive mode (interactive "help" gives help) [default] + --seconds= Length of time for dynamic profiles [default=30 secs] + --add_lib= Read additional symbols and line info from the given library + --lib_prefix= Comma separated list of library path prefixes + --no_strip_temp Do not strip template arguments from function names + +Reporting Granularity: + --addresses Report at address level + --lines Report at source line level + --functions Report at function level [default] + --files Report at source file level + +Output type: + --text Generate text report + --stacks Generate stack traces similar to the heap profiler (requires --text) + --callgrind Generate callgrind format to stdout + --gv Generate Postscript and display + --evince Generate PDF and display + --web Generate SVG and display + --list= Generate source listing of matching routines + --disasm= Generate disassembly of matching routines + --symbols Print demangled symbol names found at given addresses + --dot Generate DOT file to stdout + --ps Generate Postscript to stdout + --pdf Generate PDF to stdout + --svg Generate SVG to stdout + --gif Generate GIF to stdout + --raw Generate symbolized pprof data (useful with remote fetch) + --collapsed Generate collapsed stacks for building flame graphs + (see http://www.brendangregg.com/flamegraphs.html) + +Heap-Profile Options: + --inuse_space Display in-use (mega)bytes [default] + --inuse_objects Display in-use objects + --alloc_space Display allocated (mega)bytes + --alloc_objects Display allocated objects + --show_bytes Display space in bytes + --drop_negative Ignore negative differences + +Contention-profile options: + --total_delay Display total delay at each region [default] + --contentions Display number of delays at each region + --mean_delay Display mean delay at each region + +Call-graph Options: + --nodecount= Show at most so many nodes [default=80] + --nodefraction= Hide nodes below *total [default=.005] + --edgefraction= Hide edges below *total [default=.001] + --maxdegree= Max incoming/outgoing edges per node [default=8] + --focus= Focus on nodes matching + --ignore= Ignore nodes matching + --scale= Set GV scaling [default=0] + --heapcheck Make nodes with non-0 object counts + (i.e. direct leak generators) more visible + +Miscellaneous: + --no-auto-signal-frm Automatically drop 2nd frame that is always same (cpu-only) + (assuming that it is artifact of bad stack captures + which include signal handler frames) + --show_addresses Always show addresses when applicable + --tools=[,...] \$PATH for object tool pathnames + --test Run unit tests + --help This message + --version Version information + +Environment Variables: + PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof + PPROF_TOOLS Prefix for object tools pathnames + +Examples: + +$0 /bin/ls ls.prof + Enters "interactive" mode +$0 --text /bin/ls ls.prof + Outputs one line per procedure +$0 --web /bin/ls ls.prof + Displays annotated call-graph in web browser +$0 --gv /bin/ls ls.prof + Displays annotated call-graph via 'gv' +$0 --gv --focus=Mutex /bin/ls ls.prof + Restricts to code paths including a .*Mutex.* entry +$0 --gv --focus=Mutex --ignore=string /bin/ls ls.prof + Code paths including Mutex but not string +$0 --list=getdir /bin/ls ls.prof + (Per-line) annotated source listing for getdir() +$0 --disasm=getdir /bin/ls ls.prof + (Per-PC) annotated disassembly for getdir() + +$0 http://localhost:1234/ + Enters "interactive" mode +$0 --text localhost:1234 + Outputs one line per procedure for localhost:1234 +$0 --raw localhost:1234 > ./local.raw +$0 --text ./local.raw + Fetches a remote profile for later analysis and then + analyzes it in text mode. +EOF +} + +sub version_string { + return < \$main::opt_help, + "version!" => \$main::opt_version, + "show_addresses!"=> \$main::opt_show_addresses, + "no-auto-signal-frm!"=> \$main::opt_no_auto_signal_frames, + "cum!" => \$main::opt_cum, + "base=s" => \$main::opt_base, + "seconds=i" => \$main::opt_seconds, + "add_lib=s" => \$main::opt_lib, + "lib_prefix=s" => \$main::opt_lib_prefix, + "functions!" => \$main::opt_functions, + "lines!" => \$main::opt_lines, + "addresses!" => \$main::opt_addresses, + "files!" => \$main::opt_files, + "text!" => \$main::opt_text, + "stacks!" => \$main::opt_stacks, + "callgrind!" => \$main::opt_callgrind, + "list=s" => \$main::opt_list, + "disasm=s" => \$main::opt_disasm, + "symbols!" => \$main::opt_symbols, + "gv!" => \$main::opt_gv, + "evince!" => \$main::opt_evince, + "web!" => \$main::opt_web, + "dot!" => \$main::opt_dot, + "ps!" => \$main::opt_ps, + "pdf!" => \$main::opt_pdf, + "svg!" => \$main::opt_svg, + "gif!" => \$main::opt_gif, + "raw!" => \$main::opt_raw, + "collapsed!" => \$main::opt_collapsed, + "interactive!" => \$main::opt_interactive, + "nodecount=i" => \$main::opt_nodecount, + "nodefraction=f" => \$main::opt_nodefraction, + "edgefraction=f" => \$main::opt_edgefraction, + "maxdegree=i" => \$main::opt_maxdegree, + "focus=s" => \$main::opt_focus, + "ignore=s" => \$main::opt_ignore, + "scale=i" => \$main::opt_scale, + "heapcheck" => \$main::opt_heapcheck, + "inuse_space!" => \$main::opt_inuse_space, + "inuse_objects!" => \$main::opt_inuse_objects, + "alloc_space!" => \$main::opt_alloc_space, + "alloc_objects!" => \$main::opt_alloc_objects, + "show_bytes!" => \$main::opt_show_bytes, + "drop_negative!" => \$main::opt_drop_negative, + "total_delay!" => \$main::opt_total_delay, + "contentions!" => \$main::opt_contentions, + "mean_delay!" => \$main::opt_mean_delay, + "tools=s" => \$main::opt_tools, + "no_strip_temp!" => \$main::opt_no_strip_temp, + "test!" => \$main::opt_test, + "debug!" => \$main::opt_debug, + # Undocumented flags used only by unittests: + "test_stride=i" => \$main::opt_test_stride, + ) || usage("Invalid option(s)"); + + # Deal with the standard --help and --version + if ($main::opt_help) { + print usage_string(); + exit(0); + } + + if ($main::opt_version) { + print version_string(); + exit(0); + } + + # Disassembly/listing/symbols mode requires address-level info + if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) { + $main::opt_functions = 0; + $main::opt_lines = 0; + $main::opt_addresses = 1; + $main::opt_files = 0; + } + + # Check heap-profiling flags + if ($main::opt_inuse_space + + $main::opt_inuse_objects + + $main::opt_alloc_space + + $main::opt_alloc_objects > 1) { + usage("Specify at most on of --inuse/--alloc options"); + } + + # Check output granularities + my $grains = + $main::opt_functions + + $main::opt_lines + + $main::opt_addresses + + $main::opt_files + + 0; + if ($grains > 1) { + usage("Only specify one output granularity option"); + } + if ($grains == 0) { + $main::opt_functions = 1; + } + + # Check output modes + my $modes = + $main::opt_text + + $main::opt_callgrind + + ($main::opt_list eq '' ? 0 : 1) + + ($main::opt_disasm eq '' ? 0 : 1) + + ($main::opt_symbols == 0 ? 0 : 1) + + $main::opt_gv + + $main::opt_evince + + $main::opt_web + + $main::opt_dot + + $main::opt_ps + + $main::opt_pdf + + $main::opt_svg + + $main::opt_gif + + $main::opt_raw + + $main::opt_collapsed + + $main::opt_interactive + + 0; + if ($modes > 1) { + usage("Only specify one output mode"); + } + if ($modes == 0) { + if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode + $main::opt_interactive = 1; + } else { + $main::opt_text = 1; + } + } + + if ($main::opt_test) { + RunUnitTests(); + # Should not return + exit(1); + } + + # Binary name and profile arguments list + $main::prog = ""; + @main::pfile_args = (); + + # Remote profiling without a binary (using $SYMBOL_PAGE instead) + if (@ARGV > 0) { + if (IsProfileURL($ARGV[0])) { + printf STDERR "Using remote profile at $ARGV[0].\n"; + $main::use_symbol_page = 1; + } elsif (IsSymbolizedProfileFile($ARGV[0])) { + $main::use_symbolized_profile = 1; + $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file + } + } + + if ($main::use_symbol_page || $main::use_symbolized_profile) { + # We don't need a binary! + my %disabled = ('--lines' => $main::opt_lines, + '--disasm' => $main::opt_disasm); + for my $option (keys %disabled) { + usage("$option cannot be used without a binary") if $disabled{$option}; + } + # Set $main::prog later... + scalar(@ARGV) || usage("Did not specify profile file"); + } elsif ($main::opt_symbols) { + # --symbols needs a binary-name (to run nm on, etc) but not profiles + $main::prog = shift(@ARGV) || usage("Did not specify program"); + } else { + $main::prog = shift(@ARGV) || usage("Did not specify program"); + scalar(@ARGV) || usage("Did not specify profile file"); + } + + # Parse profile file/location arguments + foreach my $farg (@ARGV) { + if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) { + my $machine = $1; + my $num_machines = $2; + my $path = $3; + for (my $i = 0; $i < $num_machines; $i++) { + unshift(@main::pfile_args, "$i.$machine$path"); + } + } else { + unshift(@main::pfile_args, $farg); + } + } + + if ($main::use_symbol_page) { + unless (IsProfileURL($main::pfile_args[0])) { + error("The first profile should be a remote form to use $SYMBOL_PAGE\n"); + } + CheckSymbolPage(); + $main::prog = FetchProgramName(); + } elsif (!$main::use_symbolized_profile) { # may not need objtools! + ConfigureObjTools($main::prog) + } + + # Break the opt_lib_prefix into the prefix_list array + @prefix_list = split (',', $main::opt_lib_prefix); + + # Remove trailing / from the prefixes, in the list to prevent + # searching things like /my/path//lib/mylib.so + foreach (@prefix_list) { + s|/+$||; + } +} + +sub Main() { + Init(); + $main::collected_profile = undef; + @main::profile_files = (); + $main::op_time = time(); + + # Printing symbols is special and requires a lot less info that most. + if ($main::opt_symbols) { + PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin + return; + } + + # Fetch all profile data + FetchDynamicProfiles(); + + # this will hold symbols that we read from the profile files + my $symbol_map = {}; + + # Read one profile, pick the last item on the list + my $data = ReadProfile($main::prog, pop(@main::profile_files)); + my $profile = $data->{profile}; + my $pcs = $data->{pcs}; + my $libs = $data->{libs}; # Info about main program and shared libraries + $symbol_map = MergeSymbols($symbol_map, $data->{symbols}); + + # Add additional profiles, if available. + if (scalar(@main::profile_files) > 0) { + foreach my $pname (@main::profile_files) { + my $data2 = ReadProfile($main::prog, $pname); + $profile = AddProfile($profile, $data2->{profile}); + $pcs = AddPcs($pcs, $data2->{pcs}); + $symbol_map = MergeSymbols($symbol_map, $data2->{symbols}); + } + } + + # Subtract base from profile, if specified + if ($main::opt_base ne '') { + my $base = ReadProfile($main::prog, $main::opt_base); + $profile = SubtractProfile($profile, $base->{profile}); + $pcs = AddPcs($pcs, $base->{pcs}); + $symbol_map = MergeSymbols($symbol_map, $base->{symbols}); + } + + # Get total data in profile + my $total = TotalProfile($profile); + + # Collect symbols + my $symbols; + if ($main::use_symbolized_profile) { + $symbols = FetchSymbols($pcs, $symbol_map); + } elsif ($main::use_symbol_page) { + $symbols = FetchSymbols($pcs); + } else { + # TODO(csilvers): $libs uses the /proc/self/maps data from profile1, + # which may differ from the data from subsequent profiles, especially + # if they were run on different machines. Use appropriate libs for + # each pc somehow. + $symbols = ExtractSymbols($libs, $pcs); + } + + # Remove uniniteresting stack items + $profile = RemoveUninterestingFrames($symbols, $profile); + + # Focus? + if ($main::opt_focus ne '') { + $profile = FocusProfile($symbols, $profile, $main::opt_focus); + } + + # Ignore? + if ($main::opt_ignore ne '') { + $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore); + } + + my $calls = ExtractCalls($symbols, $profile); + + # Reduce profiles to required output granularity, and also clean + # each stack trace so a given entry exists at most once. + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + # Print + if (!$main::opt_interactive) { + if ($main::opt_disasm) { + PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm); + } elsif ($main::opt_list) { + PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0); + } elsif ($main::opt_text) { + # Make sure the output is empty when have nothing to report + # (only matters when --heapcheck is given but we must be + # compatible with old branches that did not pass --heapcheck always): + if ($total != 0) { + printf("Total: %s %s\n", Unparse($total), Units()); + } + if ($main::opt_stacks) { + printf("Stacks:\n\n"); + PrintStacksForText($symbols, $profile); + } + PrintText($symbols, $flat, $cumulative, -1); + } elsif ($main::opt_raw) { + PrintSymbolizedProfile($symbols, $profile, $main::prog); + } elsif ($main::opt_collapsed) { + PrintCollapsedStacks($symbols, $profile); + } elsif ($main::opt_callgrind) { + PrintCallgrind($calls); + } else { + if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { + if ($main::opt_gv) { + RunGV(TempName($main::next_tmpfile, "ps"), ""); + } elsif ($main::opt_evince) { + RunEvince(TempName($main::next_tmpfile, "pdf"), ""); + } elsif ($main::opt_web) { + my $tmp = TempName($main::next_tmpfile, "svg"); + RunWeb($tmp); + # The command we run might hand the file name off + # to an already running browser instance and then exit. + # Normally, we'd remove $tmp on exit (right now), + # but fork a child to remove $tmp a little later, so that the + # browser has time to load it first. + delete $main::tempnames{$tmp}; + if (fork() == 0) { + sleep 5; + unlink($tmp); + exit(0); + } + } + } else { + cleanup(); + exit(1); + } + } + } else { + InteractiveMode($profile, $symbols, $libs, $total); + } + + cleanup(); + exit(0); +} + +##### Entry Point ##### + +Main(); + +# Temporary code to detect if we're running on a Goobuntu system. +# These systems don't have the right stuff installed for the special +# Readline libraries to work, so as a temporary workaround, we default +# to using the normal stdio code, rather than the fancier readline-based +# code +sub ReadlineMightFail { + if (-e '/lib/libtermcap.so.2') { + return 0; # libtermcap exists, so readline should be okay + } else { + return 1; + } +} + +sub RunGV { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + if (!system(ShellEscape(@GV, "--version") . " >$dev_null 2>&1")) { + # Options using double dash are supported by this gv version. + # Also, turn on noantialias to better handle bug in gv for + # postscript files with large dimensions. + # TODO: Maybe we should not pass the --noantialias flag + # if the gv version is known to work properly without the flag. + system(ShellEscape(@GV, "--scale=$main::opt_scale", "--noantialias", $fname) + . $bg); + } else { + # Old gv version - only supports options that use single dash. + print STDERR ShellEscape(@GV, "-scale", $main::opt_scale) . "\n"; + system(ShellEscape(@GV, "-scale", "$main::opt_scale", $fname) . $bg); + } +} + +sub RunEvince { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + system(ShellEscape(@EVINCE, $fname) . $bg); +} + +sub RunWeb { + my $fname = shift; + print STDERR "Loading web page file:///$fname\n"; + + if (`uname` =~ /Darwin/) { + # OS X: open will use standard preference for SVG files. + system("/usr/bin/open", $fname); + return; + } + + if (`uname` =~ /MINGW/) { + # Windows(MinGW): open will use standard preference for SVG files. + system("cmd", "/c", "start", $fname); + return; + } + + # Some kind of Unix; try generic symlinks, then specific browsers. + # (Stop once we find one.) + # Works best if the browser is already running. + my @alt = ( + "/etc/alternatives/gnome-www-browser", + "/etc/alternatives/x-www-browser", + "google-chrome", + "firefox", + ); + foreach my $b (@alt) { + if (system($b, $fname) == 0) { + return; + } + } + + print STDERR "Could not load web browser.\n"; +} + +sub RunKcachegrind { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + print STDERR "Starting '@KCACHEGRIND " . $fname . $bg . "'\n"; + system(ShellEscape(@KCACHEGRIND, $fname) . $bg); +} + + +##### Interactive helper routines ##### + +sub InteractiveMode { + $| = 1; # Make output unbuffered for interactive mode + my ($orig_profile, $symbols, $libs, $total) = @_; + + print STDERR "Welcome to pprof! For help, type 'help'.\n"; + + # Use ReadLine if it's installed and input comes from a console. + if ( -t STDIN && + !ReadlineMightFail() && + defined(eval {require Term::ReadLine}) ) { + my $term = new Term::ReadLine 'pprof'; + while ( defined ($_ = $term->readline('(pprof) '))) { + $term->addhistory($_) if /\S/; + if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { + last; # exit when we get an interactive command to quit + } + } + } else { # don't have readline + while (1) { + print STDERR "(pprof) "; + $_ = ; + last if ! defined $_ ; + s/\r//g; # turn windows-looking lines into unix-looking lines + + # Save some flags that might be reset by InteractiveCommand() + my $save_opt_lines = $main::opt_lines; + + if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { + last; # exit when we get an interactive command to quit + } + + # Restore flags + $main::opt_lines = $save_opt_lines; + } + } +} + +# Takes two args: orig profile, and command to run. +# Returns 1 if we should keep going, or 0 if we were asked to quit +sub InteractiveCommand { + my($orig_profile, $symbols, $libs, $total, $command) = @_; + $_ = $command; # just to make future m//'s easier + if (!defined($_)) { + print STDERR "\n"; + return 0; + } + if (m/^\s*quit/) { + return 0; + } + if (m/^\s*help/) { + InteractiveHelpMessage(); + return 1; + } + # Clear all the mode options -- mode is controlled by "$command" + $main::opt_text = 0; + $main::opt_callgrind = 0; + $main::opt_disasm = 0; + $main::opt_list = 0; + $main::opt_gv = 0; + $main::opt_evince = 0; + $main::opt_cum = 0; + + if (m/^\s*(text|top)(\d*)\s*(.*)/) { + $main::opt_text = 1; + + my $line_limit = ($2 ne "") ? int($2) : 10; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($3); + + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintText($symbols, $flat, $cumulative, $line_limit); + return 1; + } + if (m/^\s*callgrind\s*([^ \n]*)/) { + $main::opt_callgrind = 1; + + # Get derived profiles + my $calls = ExtractCalls($symbols, $orig_profile); + my $filename = $1; + if ( $1 eq '' ) { + $filename = TempName($main::next_tmpfile, "callgrind"); + } + PrintCallgrind($calls, $filename); + if ( $1 eq '' ) { + RunKcachegrind($filename, " & "); + $main::next_tmpfile++; + } + + return 1; + } + if (m/^\s*(web)?list\s*(.+)/) { + my $html = (defined($1) && ($1 eq "web")); + $main::opt_list = 1; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($2); + + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintListing($total, $libs, $flat, $cumulative, $routine, $html); + return 1; + } + if (m/^\s*disasm\s*(.+)/) { + $main::opt_disasm = 1; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($1); + + # Process current profile to account for various settings + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintDisassembly($libs, $flat, $cumulative, $routine); + return 1; + } + if (m/^\s*(gv|web|evince)\s*(.*)/) { + $main::opt_gv = 0; + $main::opt_evince = 0; + $main::opt_web = 0; + if ($1 eq "gv") { + $main::opt_gv = 1; + } elsif ($1 eq "evince") { + $main::opt_evince = 1; + } elsif ($1 eq "web") { + $main::opt_web = 1; + } + + my $focus; + my $ignore; + ($focus, $ignore) = ParseInteractiveArgs($2); + + # Process current profile to account for various settings + my $profile = ProcessProfile($total, $orig_profile, $symbols, + $focus, $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { + if ($main::opt_gv) { + RunGV(TempName($main::next_tmpfile, "ps"), " &"); + } elsif ($main::opt_evince) { + RunEvince(TempName($main::next_tmpfile, "pdf"), " &"); + } elsif ($main::opt_web) { + RunWeb(TempName($main::next_tmpfile, "svg")); + } + $main::next_tmpfile++; + } + return 1; + } + if (m/^\s*$/) { + return 1; + } + print STDERR "Unknown command: try 'help'.\n"; + return 1; +} + + +sub ProcessProfile { + my $total_count = shift; + my $orig_profile = shift; + my $symbols = shift; + my $focus = shift; + my $ignore = shift; + + # Process current profile to account for various settings + my $profile = $orig_profile; + printf("Total: %s %s\n", Unparse($total_count), Units()); + if ($focus ne '') { + $profile = FocusProfile($symbols, $profile, $focus); + my $focus_count = TotalProfile($profile); + printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n", + $focus, + Unparse($focus_count), Units(), + Unparse($total_count), ($focus_count*100.0) / $total_count); + } + if ($ignore ne '') { + $profile = IgnoreProfile($symbols, $profile, $ignore); + my $ignore_count = TotalProfile($profile); + printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n", + $ignore, + Unparse($ignore_count), Units(), + Unparse($total_count), + ($ignore_count*100.0) / $total_count); + } + + return $profile; +} + +sub InteractiveHelpMessage { + print STDERR <{$k}; + my @addrs = split(/\n/, $k); + if ($#addrs >= 0) { + my $depth = $#addrs + 1; + # int(foo / 2**32) is the only reliable way to get rid of bottom + # 32 bits on both 32- and 64-bit systems. + if ($big_endian) { + print pack('L*', int($count / 2**32), $count & 0xFFFFFFFF); + print pack('L*', int($depth / 2**32), $depth & 0xFFFFFFFF); + } + else { + print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32)); + print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32)); + } + + foreach my $full_addr (@addrs) { + my $addr = $full_addr; + $addr =~ s/0x0*//; # strip off leading 0x, zeroes + if (length($addr) > 16) { + print STDERR "Invalid address in profile: $full_addr\n"; + next; + } + my $low_addr = substr($addr, -8); # get last 8 hex chars + my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars + if ($big_endian) { + print pack('L*', hex('0x' . $high_addr), hex('0x' . $low_addr)); + } + else { + print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr)); + } + } + } + } +} + +# Print symbols and profile data +sub PrintSymbolizedProfile { + my $symbols = shift; + my $profile = shift; + my $prog = shift; + + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + + print '--- ', $symbol_marker, "\n"; + if (defined($prog)) { + print 'binary=', $prog, "\n"; + } + while (my ($pc, $name) = each(%{$symbols})) { + my $sep = ' '; + print '0x', $pc; + # We have a list of function names, which include the inlined + # calls. They are separated (and terminated) by --, which is + # illegal in function names. + for (my $j = 2; $j <= $#{$name}; $j += 3) { + print $sep, $name->[$j]; + $sep = '--'; + } + print "\n"; + } + print '---', "\n"; + + $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $profile_marker = $&; + print '--- ', $profile_marker, "\n"; + if (defined($main::collected_profile)) { + # if used with remote fetch, simply dump the collected profile to output. + open(SRC, "<$main::collected_profile"); + while () { + print $_; + } + close(SRC); + } else { + # dump a cpu-format profile to standard out + PrintProfileData($profile); + } +} + +# Print text output +sub PrintText { + my $symbols = shift; + my $flat = shift; + my $cumulative = shift; + my $line_limit = shift; + + if ($main::opt_stacks && @stackTraces) { + foreach (sort { (split " ", $b)[1] <=> (split " ", $a)[1]; } @stackTraces) { + print "$_\n" if $main::opt_debug; + my ($n1, $s1, $n2, $s2, @addrs) = split; + print "Leak of $s1 bytes in $n1 objects allocated from:\n"; + foreach my $pcstr (@addrs) { + $pcstr =~ s/^0x//; + my $sym; + if (! defined $symbols->{$pcstr}) { + $sym = "unknown"; + } else { + $sym = "$symbols->{$pcstr}[0] $symbols->{$pcstr}[1]"; + } + print "\t@ $pcstr $sym\n"; + } + } + print "\n"; + } + + my $total = TotalProfile($flat); + + # Which profile to sort by? + my $s = $main::opt_cum ? $cumulative : $flat; + + my $running_sum = 0; + my $lines = 0; + foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b } + keys(%{$cumulative})) { + my $f = GetEntry($flat, $k); + my $c = GetEntry($cumulative, $k); + $running_sum += $f; + + my $sym = $k; + if (exists($symbols->{$k})) { + $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1]; + if ($main::opt_addresses) { + $sym = $k . " " . $sym; + } + } + + if ($f != 0 || $c != 0) { + printf("%8s %6s %6s %8s %6s %s\n", + Unparse($f), + Percent($f, $total), + Percent($running_sum, $total), + Unparse($c), + Percent($c, $total), + $sym); + } + $lines++; + last if ($line_limit >= 0 && $lines >= $line_limit); + } +} + +# Callgrind format has a compression for repeated function and file +# names. You show the name the first time, and just use its number +# subsequently. This can cut down the file to about a third or a +# quarter of its uncompressed size. $key and $val are the key/value +# pair that would normally be printed by callgrind; $map is a map from +# value to number. +sub CompressedCGName { + my($key, $val, $map) = @_; + my $idx = $map->{$val}; + # For very short keys, providing an index hurts rather than helps. + if (length($val) <= 3) { + return "$key=$val\n"; + } elsif (defined($idx)) { + return "$key=($idx)\n"; + } else { + # scalar(keys $map) gives the number of items in the map. + $idx = scalar(keys(%{$map})) + 1; + $map->{$val} = $idx; + return "$key=($idx) $val\n"; + } +} + +# Print the call graph in a way that's suiteable for callgrind. +sub PrintCallgrind { + my $calls = shift; + my $filename; + my %filename_to_index_map; + my %fnname_to_index_map; + + if ($main::opt_interactive) { + $filename = shift; + print STDERR "Writing callgrind file to '$filename'.\n" + } else { + $filename = "&STDOUT"; + } + open(CG, ">$filename"); + print CG ("events: Hits\n\n"); + foreach my $call ( map { $_->[0] } + sort { $a->[1] cmp $b ->[1] || + $a->[2] <=> $b->[2] } + map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; + [$_, $1, $2] } + keys %$calls ) { + my $count = int($calls->{$call}); + $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; + my ( $caller_file, $caller_line, $caller_function, + $callee_file, $callee_line, $callee_function ) = + ( $1, $2, $3, $5, $6, $7 ); + + # TODO(csilvers): for better compression, collect all the + # caller/callee_files and functions first, before printing + # anything, and only compress those referenced more than once. + print CG CompressedCGName("fl", $caller_file, \%filename_to_index_map); + print CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map); + if (defined $6) { + print CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map); + print CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map); + print CG ("calls=$count $callee_line\n"); + } + print CG ("$caller_line $count\n\n"); + } +} + +# Print disassembly for all all routines that match $main::opt_disasm +sub PrintDisassembly { + my $libs = shift; + my $flat = shift; + my $cumulative = shift; + my $disasm_opts = shift; + + my $total = TotalProfile($flat); + + foreach my $lib (@{$libs}) { + my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts); + my $offset = AddressSub($lib->[1], $lib->[3]); + foreach my $routine (sort ByName keys(%{$symbol_table})) { + my $start_addr = $symbol_table->{$routine}->[0]; + my $end_addr = $symbol_table->{$routine}->[1]; + # See if there are any samples in this routine + my $length = hex(AddressSub($end_addr, $start_addr)); + my $addr = AddressAdd($start_addr, $offset); + for (my $i = 0; $i < $length; $i++) { + if (defined($cumulative->{$addr})) { + PrintDisassembledFunction($lib->[0], $offset, + $routine, $flat, $cumulative, + $start_addr, $end_addr, $total); + last; + } + $addr = AddressInc($addr); + } + } + } +} + +# Return reference to array of tuples of the form: +# [start_address, filename, linenumber, instruction, limit_address] +# E.g., +# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"] +sub Disassemble { + my $prog = shift; + my $offset = shift; + my $start_addr = shift; + my $end_addr = shift; + + my $objdump = $obj_tool_map{"objdump"}; + my $cmd = ShellEscape($objdump, "-C", "-d", "-l", "--no-show-raw-insn", + "--start-address=0x$start_addr", + "--stop-address=0x$end_addr", $prog); + open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); + my @result = (); + my $filename = ""; + my $linenumber = -1; + my $last = ["", "", "", ""]; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + chop; + if (m|\s*([^:\s]+):(\d+)\s*$|) { + # Location line of the form: + # : + $filename = $1; + $linenumber = $2; + } elsif (m/^ +([0-9a-f]+):\s*(.*)/) { + # Disassembly line -- zero-extend address to full length + my $addr = HexExtend($1); + my $k = AddressAdd($addr, $offset); + $last->[4] = $k; # Store ending address for previous instruction + $last = [$k, $filename, $linenumber, $2, $end_addr]; + push(@result, $last); + } + } + close(OBJDUMP); + return @result; +} + +# The input file should contain lines of the form /proc/maps-like +# output (same format as expected from the profiles) or that looks +# like hex addresses (like "0xDEADBEEF"). We will parse all +# /proc/maps output, and for all the hex addresses, we will output +# "short" symbol names, one per line, in the same order as the input. +sub PrintSymbols { + my $maps_and_symbols_file = shift; + + # ParseLibraries expects pcs to be in a set. Fine by us... + my @pclist = (); # pcs in sorted order + my $pcs = {}; + my $map = ""; + foreach my $line (<$maps_and_symbols_file>) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ($line =~ /\b(0x[0-9a-f]+)\b/i) { + push(@pclist, HexExtend($1)); + $pcs->{$pclist[-1]} = 1; + } else { + $map .= $line; + } + } + + my $libs = ParseLibraries($main::prog, $map, $pcs); + my $symbols = ExtractSymbols($libs, $pcs); + + foreach my $pc (@pclist) { + # ->[0] is the shortname, ->[2] is the full name + print(($symbols->{$pc}->[0] || "??") . "\n"); + } +} + + +# For sorting functions by name +sub ByName { + return ShortFunctionName($a) cmp ShortFunctionName($b); +} + +# Print source-listing for all all routines that match $list_opts +sub PrintListing { + my $total = shift; + my $libs = shift; + my $flat = shift; + my $cumulative = shift; + my $list_opts = shift; + my $html = shift; + + my $output = \*STDOUT; + my $fname = ""; + + if ($html) { + # Arrange to write the output to a temporary file + $fname = TempName($main::next_tmpfile, "html"); + $main::next_tmpfile++; + if (!open(TEMP, ">$fname")) { + print STDERR "$fname: $!\n"; + return; + } + $output = \*TEMP; + print $output HtmlListingHeader(); + printf $output ("
%s
Total: %s %s
\n", + $main::prog, Unparse($total), Units()); + } + + my $listed = 0; + foreach my $lib (@{$libs}) { + my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts); + my $offset = AddressSub($lib->[1], $lib->[3]); + foreach my $routine (sort ByName keys(%{$symbol_table})) { + # Print if there are any samples in this routine + my $start_addr = $symbol_table->{$routine}->[0]; + my $end_addr = $symbol_table->{$routine}->[1]; + my $length = hex(AddressSub($end_addr, $start_addr)); + my $addr = AddressAdd($start_addr, $offset); + for (my $i = 0; $i < $length; $i++) { + if (defined($cumulative->{$addr})) { + $listed += PrintSource( + $lib->[0], $offset, + $routine, $flat, $cumulative, + $start_addr, $end_addr, + $html, + $output); + last; + } + $addr = AddressInc($addr); + } + } + } + + if ($html) { + if ($listed > 0) { + print $output HtmlListingFooter(); + close($output); + RunWeb($fname); + } else { + close($output); + unlink($fname); + } + } +} + +sub HtmlListingHeader { + return <<'EOF'; + + + +Pprof listing + + + + +EOF +} + +sub HtmlListingFooter { + return <<'EOF'; + + +EOF +} + +sub HtmlEscape { + my $text = shift; + $text =~ s/&/&/g; + $text =~ s//>/g; + return $text; +} + +# Returns the indentation of the line, if it has any non-whitespace +# characters. Otherwise, returns -1. +sub Indentation { + my $line = shift; + if (m/^(\s*)\S/) { + return length($1); + } else { + return -1; + } +} + +# If the symbol table contains inlining info, Disassemble() may tag an +# instruction with a location inside an inlined function. But for +# source listings, we prefer to use the location in the function we +# are listing. So use MapToSymbols() to fetch full location +# information for each instruction and then pick out the first +# location from a location list (location list contains callers before +# callees in case of inlining). +# +# After this routine has run, each entry in $instructions contains: +# [0] start address +# [1] filename for function we are listing +# [2] line number for function we are listing +# [3] disassembly +# [4] limit address +# [5] most specific filename (may be different from [1] due to inlining) +# [6] most specific line number (may be different from [2] due to inlining) +sub GetTopLevelLineNumbers { + my ($lib, $offset, $instructions) = @_; + my $pcs = []; + for (my $i = 0; $i <= $#{$instructions}; $i++) { + push(@{$pcs}, $instructions->[$i]->[0]); + } + my $symbols = {}; + MapToSymbols($lib, $offset, $pcs, $symbols); + for (my $i = 0; $i <= $#{$instructions}; $i++) { + my $e = $instructions->[$i]; + push(@{$e}, $e->[1]); + push(@{$e}, $e->[2]); + my $addr = $e->[0]; + my $sym = $symbols->{$addr}; + if (defined($sym)) { + if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) { + $e->[1] = $1; # File name + $e->[2] = $2; # Line number + } + } + } +} + +# Print source-listing for one routine +sub PrintSource { + my $prog = shift; + my $offset = shift; + my $routine = shift; + my $flat = shift; + my $cumulative = shift; + my $start_addr = shift; + my $end_addr = shift; + my $html = shift; + my $output = shift; + + # Disassemble all instructions (just to get line numbers) + my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); + GetTopLevelLineNumbers($prog, $offset, \@instructions); + + # Hack 1: assume that the first source file encountered in the + # disassembly contains the routine + my $filename = undef; + for (my $i = 0; $i <= $#instructions; $i++) { + if ($instructions[$i]->[2] >= 0) { + $filename = $instructions[$i]->[1]; + last; + } + } + if (!defined($filename)) { + print STDERR "no filename found in $routine\n"; + return 0; + } + + # Hack 2: assume that the largest line number from $filename is the + # end of the procedure. This is typically safe since if P1 contains + # an inlined call to P2, then P2 usually occurs earlier in the + # source file. If this does not work, we might have to compute a + # density profile or just print all regions we find. + my $lastline = 0; + for (my $i = 0; $i <= $#instructions; $i++) { + my $f = $instructions[$i]->[1]; + my $l = $instructions[$i]->[2]; + if (($f eq $filename) && ($l > $lastline)) { + $lastline = $l; + } + } + + # Hack 3: assume the first source location from "filename" is the start of + # the source code. + my $firstline = 1; + for (my $i = 0; $i <= $#instructions; $i++) { + if ($instructions[$i]->[1] eq $filename) { + $firstline = $instructions[$i]->[2]; + last; + } + } + + # Hack 4: Extend last line forward until its indentation is less than + # the indentation we saw on $firstline + my $oldlastline = $lastline; + { + if (!open(FILE, "<$filename")) { + print STDERR "$filename: $!\n"; + return 0; + } + my $l = 0; + my $first_indentation = -1; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + $l++; + my $indent = Indentation($_); + if ($l >= $firstline) { + if ($first_indentation < 0 && $indent >= 0) { + $first_indentation = $indent; + last if ($first_indentation == 0); + } + } + if ($l >= $lastline && $indent >= 0) { + if ($indent >= $first_indentation) { + $lastline = $l+1; + } else { + last; + } + } + } + close(FILE); + } + + # Assign all samples to the range $firstline,$lastline, + # Hack 4: If an instruction does not occur in the range, its samples + # are moved to the next instruction that occurs in the range. + my $samples1 = {}; # Map from line number to flat count + my $samples2 = {}; # Map from line number to cumulative count + my $running1 = 0; # Unassigned flat counts + my $running2 = 0; # Unassigned cumulative counts + my $total1 = 0; # Total flat counts + my $total2 = 0; # Total cumulative counts + my %disasm = (); # Map from line number to disassembly + my $running_disasm = ""; # Unassigned disassembly + my $skip_marker = "---\n"; + if ($html) { + $skip_marker = ""; + for (my $l = $firstline; $l <= $lastline; $l++) { + $disasm{$l} = ""; + } + } + my $last_dis_filename = ''; + my $last_dis_linenum = -1; + my $last_touched_line = -1; # To detect gaps in disassembly for a line + foreach my $e (@instructions) { + # Add up counts for all address that fall inside this instruction + my $c1 = 0; + my $c2 = 0; + for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { + $c1 += GetEntry($flat, $a); + $c2 += GetEntry($cumulative, $a); + } + + if ($html) { + my $dis = sprintf(" %6s %6s \t\t%8s: %s ", + HtmlPrintNumber($c1), + HtmlPrintNumber($c2), + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); + + # Append the most specific source line associated with this instruction + if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) }; + $dis = HtmlEscape($dis); + my $f = $e->[5]; + my $l = $e->[6]; + if ($f ne $last_dis_filename) { + $dis .= sprintf("%s:%d", + HtmlEscape(CleanFileName($f)), $l); + } elsif ($l ne $last_dis_linenum) { + # De-emphasize the unchanged file name portion + $dis .= sprintf("%s" . + ":%d", + HtmlEscape(CleanFileName($f)), $l); + } else { + # De-emphasize the entire location + $dis .= sprintf("%s:%d", + HtmlEscape(CleanFileName($f)), $l); + } + $last_dis_filename = $f; + $last_dis_linenum = $l; + $running_disasm .= $dis; + $running_disasm .= "\n"; + } + + $running1 += $c1; + $running2 += $c2; + $total1 += $c1; + $total2 += $c2; + my $file = $e->[1]; + my $line = $e->[2]; + if (($file eq $filename) && + ($line >= $firstline) && + ($line <= $lastline)) { + # Assign all accumulated samples to this line + AddEntry($samples1, $line, $running1); + AddEntry($samples2, $line, $running2); + $running1 = 0; + $running2 = 0; + if ($html) { + if ($line != $last_touched_line && $disasm{$line} ne '') { + $disasm{$line} .= "\n"; + } + $disasm{$line} .= $running_disasm; + $running_disasm = ''; + $last_touched_line = $line; + } + } + } + + # Assign any leftover samples to $lastline + AddEntry($samples1, $lastline, $running1); + AddEntry($samples2, $lastline, $running2); + if ($html) { + if ($lastline != $last_touched_line && $disasm{$lastline} ne '') { + $disasm{$lastline} .= "\n"; + } + $disasm{$lastline} .= $running_disasm; + } + + if ($html) { + printf $output ( + "

%s

%s\n
\n" .
+      "Total:%6s %6s (flat / cumulative %s)\n",
+      HtmlEscape(ShortFunctionName($routine)),
+      HtmlEscape(CleanFileName($filename)),
+      Unparse($total1),
+      Unparse($total2),
+      Units());
+  } else {
+    printf $output (
+      "ROUTINE ====================== %s in %s\n" .
+      "%6s %6s Total %s (flat / cumulative)\n",
+      ShortFunctionName($routine),
+      CleanFileName($filename),
+      Unparse($total1),
+      Unparse($total2),
+      Units());
+  }
+  if (!open(FILE, "<$filename")) {
+    print STDERR "$filename: $!\n";
+    return 0;
+  }
+  my $l = 0;
+  while () {
+    s/\r//g;         # turn windows-looking lines into unix-looking lines
+    $l++;
+    if ($l >= $firstline - 5 &&
+        (($l <= $oldlastline + 5) || ($l <= $lastline))) {
+      chop;
+      my $text = $_;
+      if ($l == $firstline) { print $output $skip_marker; }
+      my $n1 = GetEntry($samples1, $l);
+      my $n2 = GetEntry($samples2, $l);
+      if ($html) {
+        # Emit a span that has one of the following classes:
+        #    livesrc -- has samples
+        #    deadsrc -- has disassembly, but with no samples
+        #    nop     -- has no matching disasembly
+        # Also emit an optional span containing disassembly.
+        my $dis = $disasm{$l};
+        my $asm = "";
+        if (defined($dis) && $dis ne '') {
+          $asm = "" . $dis . "";
+        }
+        my $source_class = (($n1 + $n2 > 0) 
+                            ? "livesrc" 
+                            : (($asm ne "") ? "deadsrc" : "nop"));
+        printf $output (
+          "%5d " .
+          "%6s %6s %s%s\n",
+          $l, $source_class,
+          HtmlPrintNumber($n1),
+          HtmlPrintNumber($n2),
+          HtmlEscape($text),
+          $asm);
+      } else {
+        printf $output(
+          "%6s %6s %4d: %s\n",
+          UnparseAlt($n1),
+          UnparseAlt($n2),
+          $l,
+          $text);
+      }
+      if ($l == $lastline)  { print $output $skip_marker; }
+    };
+  }
+  close(FILE);
+  if ($html) {
+    print $output "
\n"; + } + return 1; +} + +# Return the source line for the specified file/linenumber. +# Returns undef if not found. +sub SourceLine { + my $file = shift; + my $line = shift; + + # Look in cache + if (!defined($main::source_cache{$file})) { + if (100 < scalar keys(%main::source_cache)) { + # Clear the cache when it gets too big + $main::source_cache = (); + } + + # Read all lines from the file + if (!open(FILE, "<$file")) { + print STDERR "$file: $!\n"; + $main::source_cache{$file} = []; # Cache the negative result + return undef; + } + my $lines = []; + push(@{$lines}, ""); # So we can use 1-based line numbers as indices + while () { + push(@{$lines}, $_); + } + close(FILE); + + # Save the lines in the cache + $main::source_cache{$file} = $lines; + } + + my $lines = $main::source_cache{$file}; + if (($line < 0) || ($line > $#{$lines})) { + return undef; + } else { + return $lines->[$line]; + } +} + +# Print disassembly for one routine with interspersed source if available +sub PrintDisassembledFunction { + my $prog = shift; + my $offset = shift; + my $routine = shift; + my $flat = shift; + my $cumulative = shift; + my $start_addr = shift; + my $end_addr = shift; + my $total = shift; + + # Disassemble all instructions + my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); + + # Make array of counts per instruction + my @flat_count = (); + my @cum_count = (); + my $flat_total = 0; + my $cum_total = 0; + foreach my $e (@instructions) { + # Add up counts for all address that fall inside this instruction + my $c1 = 0; + my $c2 = 0; + for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { + $c1 += GetEntry($flat, $a); + $c2 += GetEntry($cumulative, $a); + } + push(@flat_count, $c1); + push(@cum_count, $c2); + $flat_total += $c1; + $cum_total += $c2; + } + + # Print header with total counts + printf("ROUTINE ====================== %s\n" . + "%6s %6s %s (flat, cumulative) %.1f%% of total\n", + ShortFunctionName($routine), + Unparse($flat_total), + Unparse($cum_total), + Units(), + ($cum_total * 100.0) / $total); + + # Process instructions in order + my $current_file = ""; + for (my $i = 0; $i <= $#instructions; ) { + my $e = $instructions[$i]; + + # Print the new file name whenever we switch files + if ($e->[1] ne $current_file) { + $current_file = $e->[1]; + my $fname = $current_file; + $fname =~ s|^\./||; # Trim leading "./" + + # Shorten long file names + if (length($fname) >= 58) { + $fname = "..." . substr($fname, -55); + } + printf("-------------------- %s\n", $fname); + } + + # TODO: Compute range of lines to print together to deal with + # small reorderings. + my $first_line = $e->[2]; + my $last_line = $first_line; + my %flat_sum = (); + my %cum_sum = (); + for (my $l = $first_line; $l <= $last_line; $l++) { + $flat_sum{$l} = 0; + $cum_sum{$l} = 0; + } + + # Find run of instructions for this range of source lines + my $first_inst = $i; + while (($i <= $#instructions) && + ($instructions[$i]->[2] >= $first_line) && + ($instructions[$i]->[2] <= $last_line)) { + $e = $instructions[$i]; + $flat_sum{$e->[2]} += $flat_count[$i]; + $cum_sum{$e->[2]} += $cum_count[$i]; + $i++; + } + my $last_inst = $i - 1; + + # Print source lines + for (my $l = $first_line; $l <= $last_line; $l++) { + my $line = SourceLine($current_file, $l); + if (!defined($line)) { + $line = "?\n"; + next; + } else { + $line =~ s/^\s+//; + } + printf("%6s %6s %5d: %s", + UnparseAlt($flat_sum{$l}), + UnparseAlt($cum_sum{$l}), + $l, + $line); + } + + # Print disassembly + for (my $x = $first_inst; $x <= $last_inst; $x++) { + my $e = $instructions[$x]; + printf("%6s %6s %8s: %6s\n", + UnparseAlt($flat_count[$x]), + UnparseAlt($cum_count[$x]), + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); + } + } +} + +# Print DOT graph +sub PrintDot { + my $prog = shift; + my $symbols = shift; + my $raw = shift; + my $flat = shift; + my $cumulative = shift; + my $overall_total = shift; + + # Get total + my $local_total = TotalProfile($flat); + my $nodelimit = int($main::opt_nodefraction * $local_total); + my $edgelimit = int($main::opt_edgefraction * $local_total); + my $nodecount = $main::opt_nodecount; + + # Find nodes to include + my @list = (sort { abs(GetEntry($cumulative, $b)) <=> + abs(GetEntry($cumulative, $a)) + || $a cmp $b } + keys(%{$cumulative})); + my $last = $nodecount - 1; + if ($last > $#list) { + $last = $#list; + } + while (($last >= 0) && + (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) { + $last--; + } + if ($last < 0) { + print STDERR "No nodes to print\n"; + return 0; + } + + if ($nodelimit > 0 || $edgelimit > 0) { + printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n", + Unparse($nodelimit), Units(), + Unparse($edgelimit), Units()); + } + + # Open DOT output file + my $output; + my $escaped_dot = ShellEscape(@DOT); + my $escaped_ps2pdf = ShellEscape(@PS2PDF); + if ($main::opt_gv) { + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "ps")); + $output = "| $escaped_dot -Tps2 >$escaped_outfile"; + } elsif ($main::opt_evince) { + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "pdf")); + $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile"; + } elsif ($main::opt_ps) { + $output = "| $escaped_dot -Tps2"; + } elsif ($main::opt_pdf) { + $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - -"; + } elsif ($main::opt_web || $main::opt_svg) { + # We need to post-process the SVG, so write to a temporary file always. + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "svg")); + $output = "| $escaped_dot -Tsvg >$escaped_outfile"; + } elsif ($main::opt_gif) { + $output = "| $escaped_dot -Tgif"; + } else { + $output = ">&STDOUT"; + } + open(DOT, $output) || error("$output: $!\n"); + + # Title + printf DOT ("digraph \"%s; %s %s\" {\n", + $prog, + Unparse($overall_total), + Units()); + if ($main::opt_pdf) { + # The output is more printable if we set the page size for dot. + printf DOT ("size=\"8,11\"\n"); + } + printf DOT ("node [width=0.375,height=0.25];\n"); + + # Print legend + printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," . + "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n", + $prog, + sprintf("Total %s: %s", Units(), Unparse($overall_total)), + sprintf("Focusing on: %s", Unparse($local_total)), + sprintf("Dropped nodes with <= %s abs(%s)", + Unparse($nodelimit), Units()), + sprintf("Dropped edges with <= %s %s", + Unparse($edgelimit), Units()) + ); + + # Print nodes + my %node = (); + my $nextnode = 1; + foreach my $a (@list[0..$last]) { + # Pick font size + my $f = GetEntry($flat, $a); + my $c = GetEntry($cumulative, $a); + + my $fs = 8; + if ($local_total > 0) { + $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total))); + } + + $node{$a} = $nextnode++; + my $sym = $a; + $sym =~ s/\s+/\\n/g; + $sym =~ s/::/\\n/g; + + # Extra cumulative info to print for non-leaves + my $extra = ""; + if ($f != $c) { + $extra = sprintf("\\rof %s (%s)", + Unparse($c), + Percent($c, $local_total)); + } + my $style = ""; + if ($main::opt_heapcheck) { + if ($f > 0) { + # make leak-causing nodes more visible (add a background) + $style = ",style=filled,fillcolor=gray" + } elsif ($f < 0) { + # make anti-leak-causing nodes (which almost never occur) + # stand out as well (triple border) + $style = ",peripheries=3" + } + } + + printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" . + "\",shape=box,fontsize=%.1f%s];\n", + $node{$a}, + $sym, + Unparse($f), + Percent($f, $local_total), + $extra, + $fs, + $style, + ); + } + + # Get edges and counts per edge + my %edge = (); + my $n; + my $fullname_to_shortname_map = {}; + FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); + foreach my $k (keys(%{$raw})) { + # TODO: omit low %age edges + $n = $raw->{$k}; + my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); + for (my $i = 1; $i <= $#translated; $i++) { + my $src = $translated[$i]; + my $dst = $translated[$i-1]; + #next if ($src eq $dst); # Avoid self-edges? + if (exists($node{$src}) && exists($node{$dst})) { + my $edge_label = "$src\001$dst"; + if (!exists($edge{$edge_label})) { + $edge{$edge_label} = 0; + } + $edge{$edge_label} += $n; + } + } + } + + # Print edges (process in order of decreasing counts) + my %indegree = (); # Number of incoming edges added per node so far + my %outdegree = (); # Number of outgoing edges added per node so far + foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) { + my @x = split(/\001/, $e); + $n = $edge{$e}; + + # Initialize degree of kept incoming and outgoing edges if necessary + my $src = $x[0]; + my $dst = $x[1]; + if (!exists($outdegree{$src})) { $outdegree{$src} = 0; } + if (!exists($indegree{$dst})) { $indegree{$dst} = 0; } + + my $keep; + if ($indegree{$dst} == 0) { + # Keep edge if needed for reachability + $keep = 1; + } elsif (abs($n) <= $edgelimit) { + # Drop if we are below --edgefraction + $keep = 0; + } elsif ($outdegree{$src} >= $main::opt_maxdegree || + $indegree{$dst} >= $main::opt_maxdegree) { + # Keep limited number of in/out edges per node + $keep = 0; + } else { + $keep = 1; + } + + if ($keep) { + $outdegree{$src}++; + $indegree{$dst}++; + + # Compute line width based on edge count + my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0); + if ($fraction > 1) { $fraction = 1; } + my $w = $fraction * 2; + if ($w < 1 && ($main::opt_web || $main::opt_svg)) { + # SVG output treats line widths < 1 poorly. + $w = 1; + } + + # Dot sometimes segfaults if given edge weights that are too large, so + # we cap the weights at a large value + my $edgeweight = abs($n) ** 0.7; + if ($edgeweight > 100000) { $edgeweight = 100000; } + $edgeweight = int($edgeweight); + + my $style = sprintf("setlinewidth(%f)", $w); + if ($x[1] =~ m/\(inline\)/) { + $style .= ",dashed"; + } + + # Use a slightly squashed function of the edge count as the weight + printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n", + $node{$x[0]}, + $node{$x[1]}, + Unparse($n), + $edgeweight, + $style); + } + } + + print DOT ("}\n"); + close(DOT); + + if ($main::opt_web || $main::opt_svg) { + # Rewrite SVG to be more usable inside web browser. + RewriteSvg(TempName($main::next_tmpfile, "svg")); + } + + return 1; +} + +sub RewriteSvg { + my $svgfile = shift; + + open(SVG, $svgfile) || die "open temp svg: $!"; + my @svg = ; + close(SVG); + unlink $svgfile; + my $svg = join('', @svg); + + # Dot's SVG output is + # + # + # + # ... + # + # + # + # Change it to + # + # + # $svg_javascript + # + # + # ... + # + # + # + + # Fix width, height; drop viewBox. + $svg =~ s/(?s) above first + my $svg_javascript = SvgJavascript(); + my $viewport = "\n"; + $svg =~ s/ above . + $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/; + $svg =~ s/$svgfile") || die "open $svgfile: $!"; + print SVG $svg; + close(SVG); + } +} + +sub SvgJavascript { + return <<'EOF'; + +EOF +} + +# Provides a map from fullname to shortname for cases where the +# shortname is ambiguous. The symlist has both the fullname and +# shortname for all symbols, which is usually fine, but sometimes -- +# such as overloaded functions -- two different fullnames can map to +# the same shortname. In that case, we use the address of the +# function to disambiguate the two. This function fills in a map that +# maps fullnames to modified shortnames in such cases. If a fullname +# is not present in the map, the 'normal' shortname provided by the +# symlist is the appropriate one to use. +sub FillFullnameToShortnameMap { + my $symbols = shift; + my $fullname_to_shortname_map = shift; + my $shortnames_seen_once = {}; + my $shortnames_seen_more_than_once = {}; + + foreach my $symlist (values(%{$symbols})) { + # TODO(csilvers): deal with inlined symbols too. + my $shortname = $symlist->[0]; + my $fullname = $symlist->[2]; + if ($fullname !~ /<[0-9a-fA-F]+>$/) { # fullname doesn't end in an address + next; # the only collisions we care about are when addresses differ + } + if (defined($shortnames_seen_once->{$shortname}) && + $shortnames_seen_once->{$shortname} ne $fullname) { + $shortnames_seen_more_than_once->{$shortname} = 1; + } else { + $shortnames_seen_once->{$shortname} = $fullname; + } + } + + foreach my $symlist (values(%{$symbols})) { + my $shortname = $symlist->[0]; + my $fullname = $symlist->[2]; + # TODO(csilvers): take in a list of addresses we care about, and only + # store in the map if $symlist->[1] is in that list. Saves space. + next if defined($fullname_to_shortname_map->{$fullname}); + if (defined($shortnames_seen_more_than_once->{$shortname})) { + if ($fullname =~ /<0*([^>]*)>$/) { # fullname has address at end of it + $fullname_to_shortname_map->{$fullname} = "$shortname\@$1"; + } + } + } +} + +# Return a small number that identifies the argument. +# Multiple calls with the same argument will return the same number. +# Calls with different arguments will return different numbers. +sub ShortIdFor { + my $key = shift; + my $id = $main::uniqueid{$key}; + if (!defined($id)) { + $id = keys(%main::uniqueid) + 1; + $main::uniqueid{$key} = $id; + } + return $id; +} + +# Translate a stack of addresses into a stack of symbols +sub TranslateStack { + my $symbols = shift; + my $fullname_to_shortname_map = shift; + my $k = shift; + + my @addrs = split(/\n/, $k); + my @result = (); + for (my $i = 0; $i <= $#addrs; $i++) { + my $a = $addrs[$i]; + + # Skip large addresses since they sometimes show up as fake entries on RH9 + if (length($a) > 8 && $a gt "7fffffffffffffff") { + next; + } + + if ($main::opt_disasm || $main::opt_list) { + # We want just the address for the key + push(@result, $a); + next; + } + + my $symlist = $symbols->{$a}; + if (!defined($symlist)) { + $symlist = [$a, "", $a]; + } + + # We can have a sequence of symbols for a particular entry + # (more than one symbol in the case of inlining). Callers + # come before callees in symlist, so walk backwards since + # the translated stack should contain callees before callers. + for (my $j = $#{$symlist}; $j >= 2; $j -= 3) { + my $func = $symlist->[$j-2]; + my $fileline = $symlist->[$j-1]; + my $fullfunc = $symlist->[$j]; + if (defined($fullname_to_shortname_map->{$fullfunc})) { + $func = $fullname_to_shortname_map->{$fullfunc}; + } + if ($j > 2) { + $func = "$func (inline)"; + } + + # Do not merge nodes corresponding to Callback::Run since that + # causes confusing cycles in dot display. Instead, we synthesize + # a unique name for this frame per caller. + if ($func =~ m/Callback.*::Run$/) { + my $caller = ($i > 0) ? $addrs[$i-1] : 0; + $func = "Run#" . ShortIdFor($caller); + } + + if ($main::opt_addresses) { + push(@result, "$a $func $fileline"); + } elsif ($main::opt_lines) { + if ($func eq '??' && $fileline eq '??:0') { + push(@result, "$a"); + } elsif (!$main::opt_show_addresses) { + push(@result, "$func $fileline"); + } else { + push(@result, "$func $fileline ($a)"); + } + } elsif ($main::opt_functions) { + if ($func eq '??') { + push(@result, "$a"); + } elsif (!$main::opt_show_addresses) { + push(@result, $func); + } else { + push(@result, "$func ($a)"); + } + } elsif ($main::opt_files) { + if ($fileline eq '??:0' || $fileline eq '') { + push(@result, "$a"); + } else { + my $f = $fileline; + $f =~ s/:\d+$//; + push(@result, $f); + } + } else { + push(@result, $a); + last; # Do not print inlined info + } + } + } + + # print join(",", @addrs), " => ", join(",", @result), "\n"; + return @result; +} + +# Generate percent string for a number and a total +sub Percent { + my $num = shift; + my $tot = shift; + if ($tot != 0) { + return sprintf("%.1f%%", $num * 100.0 / $tot); + } else { + return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf"); + } +} + +# Generate pretty-printed form of number +sub Unparse { + my $num = shift; + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + if ($main::opt_inuse_objects || $main::opt_alloc_objects) { + return sprintf("%d", $num); + } else { + if ($main::opt_show_bytes) { + return sprintf("%d", $num); + } else { + return sprintf("%.1f", $num / 1048576.0); + } + } + } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { + return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds + } else { + return sprintf("%d", $num); + } +} + +# Alternate pretty-printed form: 0 maps to "." +sub UnparseAlt { + my $num = shift; + if ($num == 0) { + return "."; + } else { + return Unparse($num); + } +} + +# Alternate pretty-printed form: 0 maps to "" +sub HtmlPrintNumber { + my $num = shift; + if ($num == 0) { + return ""; + } else { + return Unparse($num); + } +} + +# Return output units +sub Units { + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + if ($main::opt_inuse_objects || $main::opt_alloc_objects) { + return "objects"; + } else { + if ($main::opt_show_bytes) { + return "B"; + } else { + return "MB"; + } + } + } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { + return "seconds"; + } else { + return "samples"; + } +} + +##### Profile manipulation code ##### + +# Generate flattened profile: +# If count is charged to stack [a,b,c,d], in generated profile, +# it will be charged to [a] +sub FlatProfile { + my $profile = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + if ($#addrs >= 0) { + AddEntry($result, $addrs[0], $count); + } + } + return $result; +} + +# Generate cumulative profile: +# If count is charged to stack [a,b,c,d], in generated profile, +# it will be charged to [a], [b], [c], [d] +sub CumulativeProfile { + my $profile = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + foreach my $a (@addrs) { + AddEntry($result, $a, $count); + } + } + return $result; +} + +# If the second-youngest PC on the stack is always the same, returns +# that pc. Otherwise, returns undef. +sub IsSecondPcAlwaysTheSame { + my $profile = shift; + + my $second_pc = undef; + foreach my $k (keys(%{$profile})) { + my @addrs = split(/\n/, $k); + if ($#addrs < 1) { + return undef; + } + if (not defined $second_pc) { + $second_pc = $addrs[1]; + } else { + if ($second_pc ne $addrs[1]) { + return undef; + } + } + } + return $second_pc; +} + +sub ExtractSymbolLocationInlineStack { + my $symbols = shift; + my $address = shift; + my $stack = shift; + # 'addr2line' outputs "??:0" for unknown locations; we do the + # same to be consistent. + if (exists $symbols->{$address}) { + my @localinlinestack = @{$symbols->{$address}}; + for (my $i = $#localinlinestack; $i > 0; $i-=3) { + my $file = $localinlinestack[$i-1]; + my $fn = $localinlinestack[$i-2]; + if ($file eq "?" || $file eq ":0") { + $file = "??:0"; + } + my $suffix = "[inline]"; + if ($i == 2) { + $suffix = ""; + } + push (@$stack, $file.":".$fn.$suffix); + } + } + else { + push (@$stack, "??:0:unknown"); + } +} + +sub ExtractSymbolNameInlineStack { + my $symbols = shift; + my $address = shift; + + my @stack = (); + + if (exists $symbols->{$address}) { + my @localinlinestack = @{$symbols->{$address}}; + for (my $i = $#localinlinestack; $i > 0; $i-=3) { + my $file = $localinlinestack[$i-1]; + my $fn = $localinlinestack[$i-0]; + + if ($file eq "?" || $file eq ":0") { + $file = "??:0"; + } + if ($fn eq '??') { + # If we can't get the symbol name, at least use the file information. + $fn = $file; + } + my $suffix = "[inline]"; + if ($i == 2) { + $suffix = ""; + } + push (@stack, $fn.$suffix); + } + } + else { + # If we can't get a symbol name, at least fill in the address. + push (@stack, $address); + } + + return @stack; +} + +sub ExtractSymbolLocation { + my $symbols = shift; + my $address = shift; + # 'addr2line' outputs "??:0" for unknown locations; we do the + # same to be consistent. + my $location = "??:0:unknown"; + if (exists $symbols->{$address}) { + my $file = $symbols->{$address}->[1]; + if ($file eq "?" || $file eq ":0") { + $file = "??:0" + } + $location = $file . ":" . $symbols->{$address}->[0]; + } + return $location; +} + +# Extracts a graph of calls. +sub ExtractCalls { + my $symbols = shift; + my $profile = shift; + my $calls = {}; + while( my ($stack_trace, $count) = each %$profile ) { + my @address = split(/\n/, $stack_trace); + my @stack = (); + ExtractSymbolLocationInlineStack($symbols, $address[0], \@stack); + for (my $i = 1; $i <= $#address; $i++) { + ExtractSymbolLocationInlineStack($symbols, $address[$i], \@stack); + } + AddEntry($calls, $stack[0], $count); + for (my $i = 1; $i < $#address; $i++) { + AddEntry($calls, "$stack[$i] -> $stack[$i-1]", $count); + } + } + return $calls; +} + +sub PrintStacksForText { + my $symbols = shift; + my $profile = shift; + + while (my ($stack_trace, $count) = each %$profile) { + my @address = split(/\n/, $stack_trace); + for (my $i = 0; $i <= $#address; $i++) { + $address[$i] = sprintf("(%s) %s", $address[$i], ExtractSymbolLocation($symbols, $address[$i])); + } + printf("%-8d %s\n\n", $count, join("\n ", @address)); + } +} + +sub PrintCollapsedStacks { + my $symbols = shift; + my $profile = shift; + + while (my ($stack_trace, $count) = each %$profile) { + my @address = split(/\n/, $stack_trace); + my @names = reverse ( map { ExtractSymbolNameInlineStack($symbols, $_) } @address ); + printf("%s %d\n", join(";", @names), $count); + } +} + +sub RemoveUninterestingFrames { + my $symbols = shift; + my $profile = shift; + + # List of function names to skip + my %skip = (); + my $skip_regexp = 'NOMATCH'; + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + foreach my $name ('calloc', + 'cfree', + 'malloc', + 'free', + 'memalign', + 'posix_memalign', + 'pvalloc', + 'valloc', + 'realloc', + 'tc_calloc', + 'tc_cfree', + 'tc_malloc', + 'tc_free', + 'tc_memalign', + 'tc_posix_memalign', + 'tc_pvalloc', + 'tc_valloc', + 'tc_realloc', + 'tc_new', + 'tc_delete', + 'tc_newarray', + 'tc_deletearray', + 'tc_new_nothrow', + 'tc_newarray_nothrow', + 'do_malloc', + '::do_malloc', # new name -- got moved to an unnamed ns + '::do_malloc_or_cpp_alloc', + 'DoSampledAllocation', + 'simple_alloc::allocate', + '__malloc_alloc_template::allocate', + '__builtin_delete', + '__builtin_new', + '__builtin_vec_delete', + '__builtin_vec_new', + 'operator new', + 'operator new[]', + # The entry to our memory-allocation routines on OS X + 'malloc_zone_malloc', + 'malloc_zone_calloc', + 'malloc_zone_valloc', + 'malloc_zone_realloc', + 'malloc_zone_memalign', + 'malloc_zone_free', + # These mark the beginning/end of our custom sections + '__start_google_malloc', + '__stop_google_malloc', + '__start_malloc_hook', + '__stop_malloc_hook') { + $skip{$name} = 1; + $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything + } + # TODO: Remove TCMalloc once everything has been + # moved into the tcmalloc:: namespace and we have flushed + # old code out of the system. + $skip_regexp = "TCMalloc|^tcmalloc::"; + } elsif ($main::profile_type eq 'contention') { + foreach my $vname ('base::RecordLockProfileData', + 'base::SubmitMutexProfileData', + 'base::SubmitSpinLockProfileData', + 'Mutex::Unlock', + 'Mutex::UnlockSlow', + 'Mutex::ReaderUnlock', + 'MutexLock::~MutexLock', + 'SpinLock::Unlock', + 'SpinLock::SlowUnlock', + 'SpinLockHolder::~SpinLockHolder') { + $skip{$vname} = 1; + } + } elsif ($main::profile_type eq 'cpu' && !$main::opt_no_auto_signal_frames) { + # Drop signal handlers used for CPU profile collection + # TODO(dpeng): this should not be necessary; it's taken + # care of by the general 2nd-pc mechanism below. + foreach my $name ('ProfileData::Add', # historical + 'ProfileData::prof_handler', # historical + 'CpuProfiler::prof_handler', + '__FRAME_END__', + '__pthread_sighandler', + '__restore') { + $skip{$name} = 1; + } + } else { + # Nothing skipped for unknown types + } + + if ($main::profile_type eq 'cpu') { + # If all the second-youngest program counters are the same, + # this STRONGLY suggests that it is an artifact of measurement, + # i.e., stack frames pushed by the CPU profiler signal handler. + # Hence, we delete them. + # (The topmost PC is read from the signal structure, not from + # the stack, so it does not get involved.) + while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) { + my $result = {}; + my $func = ''; + if (exists($symbols->{$second_pc})) { + $second_pc = $symbols->{$second_pc}->[0]; + } + if ($main::opt_no_auto_signal_frames) { + print STDERR "All second stack frames are same: `$second_pc'.\nMight be stack trace capturing bug.\n"; + last; + } + print STDERR "Removing $second_pc from all stack traces.\n"; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my $topaddr = POSIX::strtoul($addrs[0], 16); + splice @addrs, 1, 1; + if ($#addrs > 1) { + my $subtopaddr = POSIX::strtoul($addrs[1], 16); + if ($subtopaddr + 1 == $topaddr) { + splice @addrs, 1, 1; + } + } + my $reduced_path = join("\n", @addrs); + AddEntry($result, $reduced_path, $count); + } + $profile = $result; + } + } + + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my @path = (); + foreach my $a (@addrs) { + if (exists($symbols->{$a})) { + my $func = $symbols->{$a}->[0]; + if ($skip{$func} || ($func =~ m/$skip_regexp/)) { + next; + } + } + push(@path, $a); + } + my $reduced_path = join("\n", @path); + AddEntry($result, $reduced_path, $count); + } + return $result; +} + +# Reduce profile to granularity given by user +sub ReduceProfile { + my $symbols = shift; + my $profile = shift; + my $result = {}; + my $fullname_to_shortname_map = {}; + FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); + my @path = (); + my %seen = (); + $seen{''} = 1; # So that empty keys are skipped + foreach my $e (@translated) { + # To avoid double-counting due to recursion, skip a stack-trace + # entry if it has already been seen + if (!$seen{$e}) { + $seen{$e} = 1; + push(@path, $e); + } + } + my $reduced_path = join("\n", @path); + AddEntry($result, $reduced_path, $count); + } + return $result; +} + +# Does the specified symbol array match the regexp? +sub SymbolMatches { + my $sym = shift; + my $re = shift; + if (defined($sym)) { + for (my $i = 0; $i < $#{$sym}; $i += 3) { + if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) { + return 1; + } + } + } + return 0; +} + +# Focus only on paths involving specified regexps +sub FocusProfile { + my $symbols = shift; + my $profile = shift; + my $focus = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + foreach my $a (@addrs) { + # Reply if it matches either the address/shortname/fileline + if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) { + AddEntry($result, $k, $count); + last; + } + } + } + return $result; +} + +# Focus only on paths not involving specified regexps +sub IgnoreProfile { + my $symbols = shift; + my $profile = shift; + my $ignore = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my $matched = 0; + foreach my $a (@addrs) { + # Reply if it matches either the address/shortname/fileline + if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) { + $matched = 1; + last; + } + } + if (!$matched) { + AddEntry($result, $k, $count); + } + } + return $result; +} + +# Get total count in profile +sub TotalProfile { + my $profile = shift; + my $result = 0; + foreach my $k (keys(%{$profile})) { + $result += $profile->{$k}; + } + return $result; +} + +# Add A to B +sub AddProfile { + my $A = shift; + my $B = shift; + + my $R = {}; + # add all keys in A + foreach my $k (keys(%{$A})) { + my $v = $A->{$k}; + AddEntry($R, $k, $v); + } + # add all keys in B + foreach my $k (keys(%{$B})) { + my $v = $B->{$k}; + AddEntry($R, $k, $v); + } + return $R; +} + +# Merges symbol maps +sub MergeSymbols { + my $A = shift; + my $B = shift; + + my $R = {}; + foreach my $k (keys(%{$A})) { + $R->{$k} = $A->{$k}; + } + if (defined($B)) { + foreach my $k (keys(%{$B})) { + $R->{$k} = $B->{$k}; + } + } + return $R; +} + + +# Add A to B +sub AddPcs { + my $A = shift; + my $B = shift; + + my $R = {}; + # add all keys in A + foreach my $k (keys(%{$A})) { + $R->{$k} = 1 + } + # add all keys in B + foreach my $k (keys(%{$B})) { + $R->{$k} = 1 + } + return $R; +} + +# Subtract B from A +sub SubtractProfile { + my $A = shift; + my $B = shift; + + my $R = {}; + foreach my $k (keys(%{$A})) { + my $v = $A->{$k} - GetEntry($B, $k); + if ($v < 0 && $main::opt_drop_negative) { + $v = 0; + } + AddEntry($R, $k, $v); + } + if (!$main::opt_drop_negative) { + # Take care of when subtracted profile has more entries + foreach my $k (keys(%{$B})) { + if (!exists($A->{$k})) { + AddEntry($R, $k, 0 - $B->{$k}); + } + } + } + return $R; +} + +# Get entry from profile; zero if not present +sub GetEntry { + my $profile = shift; + my $k = shift; + if (exists($profile->{$k})) { + return $profile->{$k}; + } else { + return 0; + } +} + +# Add entry to specified profile +sub AddEntry { + my $profile = shift; + my $k = shift; + my $n = shift; + if (!exists($profile->{$k})) { + $profile->{$k} = 0; + } + $profile->{$k} += $n; +} + +# Add a stack of entries to specified profile, and add them to the $pcs +# list. +sub AddEntries { + my $profile = shift; + my $pcs = shift; + my $stack = shift; + my $count = shift; + my @k = (); + + foreach my $e (split(/\s+/, $stack)) { + my $pc = HexExtend($e); + $pcs->{$pc} = 1; + push @k, $pc; + } + AddEntry($profile, (join "\n", @k), $count); +} + +##### Code to profile a server dynamically ##### + +sub CheckSymbolPage { + my $url = SymbolPageURL(); + my $command = ShellEscape(@URL_FETCHER, $url); + open(SYMBOL, "$command |") or error($command); + my $line = ; + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + close(SYMBOL); + unless (defined($line)) { + error("$url doesn't exist\n"); + } + + if ($line =~ /^num_symbols:\s+(\d+)$/) { + if ($1 == 0) { + error("Stripped binary. No symbols available.\n"); + } + } else { + error("Failed to get the number of symbols from $url\n"); + } +} + +sub IsProfileURL { + my $profile_name = shift; + if (-f $profile_name) { + printf STDERR "Using local file $profile_name.\n"; + return 0; + } + return 1; +} + +sub ParseProfileURL { + my $profile_name = shift; + + if (!defined($profile_name) || $profile_name eq "") { + return (); + } + + # Split profile URL - matches all non-empty strings, so no test. + $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,; + + my $proto = $1 || "http://"; + my $hostport = $2; + my $prefix = $3; + my $profile = $4 || "/"; + + my $host = $hostport; + $host =~ s/:.*//; + + my $baseurl = "$proto$hostport$prefix"; + return ($host, $baseurl, $profile); +} + +# We fetch symbols from the first profile argument. +sub SymbolPageURL { + my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); + return "$baseURL$SYMBOL_PAGE"; +} + +sub FetchProgramName() { + my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); + my $url = "$baseURL$PROGRAM_NAME_PAGE"; + my $command_line = ShellEscape(@URL_FETCHER, $url); + open(CMDLINE, "$command_line |") or error($command_line); + my $cmdline = ; + $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines + close(CMDLINE); + error("Failed to get program name from $url\n") unless defined($cmdline); + $cmdline =~ s/\x00.+//; # Remove argv[1] and latters. + $cmdline =~ s!\n!!g; # Remove LFs. + return $cmdline; +} + +# Gee, curl's -L (--location) option isn't reliable at least +# with its 7.12.3 version. Curl will forget to post data if +# there is a redirection. This function is a workaround for +# curl. Redirection happens on borg hosts. +sub ResolveRedirectionForCurl { + my $url = shift; + my $command_line = ShellEscape(@URL_FETCHER, "--head", $url); + open(CMDLINE, "$command_line |") or error($command_line); + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (/^Location: (.*)/) { + $url = $1; + } + } + close(CMDLINE); + return $url; +} + +# Add a timeout flat to URL_FETCHER. Returns a new list. +sub AddFetchTimeout { + my $timeout = shift; + my @fetcher = @_; + if (defined($timeout)) { + if (join(" ", @fetcher) =~ m/\bcurl -s/) { + push(@fetcher, "--max-time", sprintf("%d", $timeout)); + } elsif (join(" ", @fetcher) =~ m/\brpcget\b/) { + push(@fetcher, sprintf("--deadline=%d", $timeout)); + } + } + return @fetcher; +} + +# Reads a symbol map from the file handle name given as $1, returning +# the resulting symbol map. Also processes variables relating to symbols. +# Currently, the only variable processed is 'binary=' which updates +# $main::prog to have the correct program name. +sub ReadSymbols { + my $in = shift; + my $map = {}; + while (<$in>) { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Removes all the leading zeroes from the symbols, see comment below. + if (m/^0x0*([0-9a-f]+)\s+(.+)/) { + $map->{$1} = $2; + } elsif (m/^---/) { + last; + } elsif (m/^([a-z][^=]*)=(.*)$/ ) { + my ($variable, $value) = ($1, $2); + for ($variable, $value) { + s/^\s+//; + s/\s+$//; + } + if ($variable eq "binary") { + if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) { + printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n", + $main::prog, $value); + } + $main::prog = $value; + } else { + printf STDERR ("Ignoring unknown variable in symbols list: " . + "'%s' = '%s'\n", $variable, $value); + } + } + } + return $map; +} + +# Fetches and processes symbols to prepare them for use in the profile output +# code. If the optional 'symbol_map' arg is not given, fetches symbols from +# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols +# are assumed to have already been fetched into 'symbol_map' and are simply +# extracted and processed. +sub FetchSymbols { + my $pcset = shift; + my $symbol_map = shift; + + my %seen = (); + my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq + + if (!defined($symbol_map)) { + my $post_data = join("+", sort((map {"0x" . "$_"} @pcs))); + + open(POSTFILE, ">$main::tmpfile_sym"); + print POSTFILE $post_data; + close(POSTFILE); + + my $url = SymbolPageURL(); + + my $command_line; + if (join(" ", @URL_FETCHER) =~ m/\bcurl -s/) { + $url = ResolveRedirectionForCurl($url); + $command_line = ShellEscape(@URL_FETCHER, "-d", "\@$main::tmpfile_sym", + $url); + } else { + $command_line = (ShellEscape(@URL_FETCHER, "--post", $url) + . " < " . ShellEscape($main::tmpfile_sym)); + } + # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols. + my $escaped_cppfilt = ShellEscape($obj_tool_map{"c++filt"}); + open(SYMBOL, "$command_line | $escaped_cppfilt |") or error($command_line); + $symbol_map = ReadSymbols(*SYMBOL{IO}); + close(SYMBOL); + } + + my $symbols = {}; + foreach my $pc (@pcs) { + my $fullname; + # For 64 bits binaries, symbols are extracted with 8 leading zeroes. + # Then /symbol reads the long symbols in as uint64, and outputs + # the result with a "0x%08llx" format which get rid of the zeroes. + # By removing all the leading zeroes in both $pc and the symbols from + # /symbol, the symbols match and are retrievable from the map. + my $shortpc = $pc; + $shortpc =~ s/^0*//; + # Each line may have a list of names, which includes the function + # and also other functions it has inlined. They are separated (in + # PrintSymbolizedProfile), by --, which is illegal in function names. + my $fullnames; + if (defined($symbol_map->{$shortpc})) { + $fullnames = $symbol_map->{$shortpc}; + } else { + $fullnames = "0x" . $pc; # Just use addresses + } + my $sym = []; + $symbols->{$pc} = $sym; + foreach my $fullname (split("--", $fullnames)) { + my $name = ShortFunctionName($fullname); + push(@{$sym}, $name, "?", $fullname); + } + } + return $symbols; +} + +sub BaseName { + my $file_name = shift; + $file_name =~ s!^.*/!!; # Remove directory name + return $file_name; +} + +sub MakeProfileBaseName { + my ($binary_name, $profile_name) = @_; + my ($host, $baseURL, $path) = ParseProfileURL($profile_name); + my $binary_shortname = BaseName($binary_name); + return sprintf("%s.%s.%s", + $binary_shortname, $main::op_time, $host); +} + +sub FetchDynamicProfile { + my $binary_name = shift; + my $profile_name = shift; + my $fetch_name_only = shift; + my $encourage_patience = shift; + + if (!IsProfileURL($profile_name)) { + return $profile_name; + } else { + my ($host, $baseURL, $path) = ParseProfileURL($profile_name); + if ($path eq "" || $path eq "/") { + # Missing type specifier defaults to cpu-profile + $path = $PROFILE_PAGE; + } + + my $profile_file = MakeProfileBaseName($binary_name, $profile_name); + + my $url = "$baseURL$path"; + my $fetch_timeout = undef; + if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) { + if ($path =~ m/[?]/) { + $url .= "&"; + } else { + $url .= "?"; + } + $url .= sprintf("seconds=%d", $main::opt_seconds); + $fetch_timeout = $main::opt_seconds * 1.01 + 60; + } else { + # For non-CPU profiles, we add a type-extension to + # the target profile file name. + my $suffix = $path; + $suffix =~ s,/,.,g; + $profile_file .= $suffix; + } + + my $profile_dir = $ENV{"PPROF_TMPDIR"} || ($ENV{HOME} . "/pprof"); + if (! -d $profile_dir) { + mkdir($profile_dir) + || die("Unable to create profile directory $profile_dir: $!\n"); + } + my $tmp_profile = "$profile_dir/.tmp.$profile_file"; + my $real_profile = "$profile_dir/$profile_file"; + + if ($fetch_name_only > 0) { + return $real_profile; + } + + my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER); + my $cmd = ShellEscape(@fetcher, $url) . " > " . ShellEscape($tmp_profile); + if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){ + print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n"; + if ($encourage_patience) { + print STDERR "Be patient...\n"; + } + } else { + print STDERR "Fetching $path profile from $url to\n ${real_profile}\n"; + } + + (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n"); + (system("mv", $tmp_profile, $real_profile) == 0) || error("Unable to rename profile\n"); + print STDERR "Wrote profile to $real_profile\n"; + $main::collected_profile = $real_profile; + return $main::collected_profile; + } +} + +# Collect profiles in parallel +sub FetchDynamicProfiles { + my $items = scalar(@main::pfile_args); + my $levels = log($items) / log(2); + + if ($items == 1) { + $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1); + } else { + # math rounding issues + if ((2 ** $levels) < $items) { + $levels++; + } + my $count = scalar(@main::pfile_args); + for (my $i = 0; $i < $count; $i++) { + $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0); + } + print STDERR "Fetching $count profiles, Be patient...\n"; + FetchDynamicProfilesRecurse($levels, 0, 0); + $main::collected_profile = join(" \\\n ", @main::profile_files); + } +} + +# Recursively fork a process to get enough processes +# collecting profiles +sub FetchDynamicProfilesRecurse { + my $maxlevel = shift; + my $level = shift; + my $position = shift; + + if (my $pid = fork()) { + $position = 0 | ($position << 1); + TryCollectProfile($maxlevel, $level, $position); + wait; + } else { + $position = 1 | ($position << 1); + TryCollectProfile($maxlevel, $level, $position); + cleanup(); + exit(0); + } +} + +# Collect a single profile +sub TryCollectProfile { + my $maxlevel = shift; + my $level = shift; + my $position = shift; + + if ($level >= ($maxlevel - 1)) { + if ($position < scalar(@main::pfile_args)) { + FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0); + } + } else { + FetchDynamicProfilesRecurse($maxlevel, $level+1, $position); + } +} + +##### Parsing code ##### + +# Provide a small streaming-read module to handle very large +# cpu-profile files. Stream in chunks along a sliding window. +# Provides an interface to get one 'slot', correctly handling +# endian-ness differences. A slot is one 32-bit or 64-bit word +# (depending on the input profile). We tell endianness and bit-size +# for the profile by looking at the first 8 bytes: in cpu profiles, +# the second slot is always 3 (we'll accept anything that's not 0). +BEGIN { + package CpuProfileStream; + + sub new { + my ($class, $file, $fname) = @_; + my $self = { file => $file, + base => 0, + stride => 512 * 1024, # must be a multiple of bitsize/8 + slots => [], + unpack_code => "", # N for big-endian, V for little + perl_is_64bit => 1, # matters if profile is 64-bit + }; + bless $self, $class; + # Let unittests adjust the stride + if ($main::opt_test_stride > 0) { + $self->{stride} = $main::opt_test_stride; + } + # Read the first two slots to figure out bitsize and endianness. + my $slots = $self->{slots}; + my $str; + read($self->{file}, $str, 8); + # Set the global $address_length based on what we see here. + # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars). + $address_length = ($str eq (chr(0)x8)) ? 16 : 8; + if ($address_length == 8) { + if (substr($str, 6, 2) eq chr(0)x2) { + $self->{unpack_code} = 'V'; # Little-endian. + } elsif (substr($str, 4, 2) eq chr(0)x2) { + $self->{unpack_code} = 'N'; # Big-endian + } else { + ::error("$fname: header size >= 2**16\n"); + } + @$slots = unpack($self->{unpack_code} . "*", $str); + } else { + # If we're a 64-bit profile, check if we're a 64-bit-capable + # perl. Otherwise, each slot will be represented as a float + # instead of an int64, losing precision and making all the + # 64-bit addresses wrong. We won't complain yet, but will + # later if we ever see a value that doesn't fit in 32 bits. + my $has_q = 0; + eval { $has_q = pack("Q", "1") ? 1 : 1; }; + if (!$has_q) { + $self->{perl_is_64bit} = 0; + } + read($self->{file}, $str, 8); + if (substr($str, 4, 4) eq chr(0)x4) { + # We'd love to use 'Q', but it's a) not universal, b) not endian-proof. + $self->{unpack_code} = 'V'; # Little-endian. + } elsif (substr($str, 0, 4) eq chr(0)x4) { + $self->{unpack_code} = 'N'; # Big-endian + } else { + ::error("$fname: header size >= 2**32\n"); + } + my @pair = unpack($self->{unpack_code} . "*", $str); + # Since we know one of the pair is 0, it's fine to just add them. + @$slots = (0, $pair[0] + $pair[1]); + } + return $self; + } + + # Load more data when we access slots->get(X) which is not yet in memory. + sub overflow { + my ($self) = @_; + my $slots = $self->{slots}; + $self->{base} += $#$slots + 1; # skip over data we're replacing + my $str; + read($self->{file}, $str, $self->{stride}); + if ($address_length == 8) { # the 32-bit case + # This is the easy case: unpack provides 32-bit unpacking primitives. + @$slots = unpack($self->{unpack_code} . "*", $str); + } else { + # We need to unpack 32 bits at a time and combine. + my @b32_values = unpack($self->{unpack_code} . "*", $str); + my @b64_values = (); + for (my $i = 0; $i < $#b32_values; $i += 2) { + # TODO(csilvers): if this is a 32-bit perl, the math below + # could end up in a too-large int, which perl will promote + # to a double, losing necessary precision. Deal with that. + # Right now, we just die. + my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]); + if ($self->{unpack_code} eq 'N') { # big-endian + ($lo, $hi) = ($hi, $lo); + } + my $value = $lo + $hi * (2**32); + if (!$self->{perl_is_64bit} && # check value is exactly represented + (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) { + ::error("Need a 64-bit perl to process this 64-bit profile.\n"); + } + push(@b64_values, $value); + } + @$slots = @b64_values; + } + } + + # Access the i-th long in the file (logically), or -1 at EOF. + sub get { + my ($self, $idx) = @_; + my $slots = $self->{slots}; + while ($#$slots >= 0) { + if ($idx < $self->{base}) { + # The only time we expect a reference to $slots[$i - something] + # after referencing $slots[$i] is reading the very first header. + # Since $stride > |header|, that shouldn't cause any lookback + # errors. And everything after the header is sequential. + print STDERR "Unexpected look-back reading CPU profile"; + return -1; # shrug, don't know what better to return + } elsif ($idx > $self->{base} + $#$slots) { + $self->overflow(); + } else { + return $slots->[$idx - $self->{base}]; + } + } + # If we get here, $slots is [], which means we've reached EOF + return -1; # unique since slots is supposed to hold unsigned numbers + } +} + +# Reads the top, 'header' section of a profile, and returns the last +# line of the header, commonly called a 'header line'. The header +# section of a profile consists of zero or more 'command' lines that +# are instructions to pprof, which pprof executes when reading the +# header. All 'command' lines start with a %. After the command +# lines is the 'header line', which is a profile-specific line that +# indicates what type of profile it is, and perhaps other global +# information about the profile. For instance, here's a header line +# for a heap profile: +# heap profile: 53: 38236 [ 5525: 1284029] @ heapprofile +# For historical reasons, the CPU profile does not contain a text- +# readable header line. If the profile looks like a CPU profile, +# this function returns "". If no header line could be found, this +# function returns undef. +# +# The following commands are recognized: +# %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:' +# +# The input file should be in binmode. +sub ReadProfileHeader { + local *PROFILE = shift; + my $firstchar = ""; + my $line = ""; + read(PROFILE, $firstchar, 1); + seek(PROFILE, -1, 1); # unread the firstchar + if ($firstchar !~ /[[:print:]]/) { # is not a text character + return ""; + } + while (defined($line = )) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ($line =~ /^%warn\s+(.*)/) { # 'warn' command + # Note this matches both '%warn blah\n' and '%warn\n'. + print STDERR "WARNING: $1\n"; # print the rest of the line + } elsif ($line =~ /^%/) { + print STDERR "Ignoring unknown command from profile header: $line"; + } else { + # End of commands, must be the header line. + return $line; + } + } + return undef; # got to EOF without seeing a header line +} + +sub IsSymbolizedProfileFile { + my $file_name = shift; + if (!(-e $file_name) || !(-r $file_name)) { + return 0; + } + # Check if the file contains a symbol-section marker. + open(TFILE, "<$file_name"); + binmode TFILE; + my $firstline = ReadProfileHeader(*TFILE); + close(TFILE); + if (!$firstline) { + return 0; + } + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + return $firstline =~ /^--- *$symbol_marker/; +} + +# Parse profile generated by common/profiler.cc and return a reference +# to a map: +# $result->{version} Version number of profile file +# $result->{period} Sampling period (in microseconds) +# $result->{profile} Profile object +# $result->{map} Memory map info from profile +# $result->{pcs} Hash of all PC values seen, key is hex address +sub ReadProfile { + my $prog = shift; + my $fname = shift; + my $result; # return value + + $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $contention_marker = $&; + $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $growth_marker = $&; + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $profile_marker = $&; + + # Look at first line to see if it is a heap or a CPU profile. + # CPU profile may start with no header at all, and just binary data + # (starting with \0\0\0\0) -- in that case, don't try to read the + # whole firstline, since it may be gigabytes(!) of data. + open(PROFILE, "<$fname") || error("$fname: $!\n"); + binmode PROFILE; # New perls do UTF-8 processing + my $header = ReadProfileHeader(*PROFILE); + if (!defined($header)) { # means "at EOF" + error("Profile is empty.\n"); + } + + my $symbols; + if ($header =~ m/^--- *$symbol_marker/o) { + # Verify that the user asked for a symbolized profile + if (!$main::use_symbolized_profile) { + # we have both a binary and symbolized profiles, abort + error("FATAL ERROR: Symbolized profile\n $fname\ncannot be used with " . + "a binary arg. Try again without passing\n $prog\n"); + } + # Read the symbol section of the symbolized profile file. + $symbols = ReadSymbols(*PROFILE{IO}); + # Read the next line to get the header for the remaining profile. + $header = ReadProfileHeader(*PROFILE) || ""; + } + + $main::profile_type = ''; + if ($header =~ m/^heap profile:.*$growth_marker/o) { + $main::profile_type = 'growth'; + $result = ReadHeapProfile($prog, *PROFILE, $header); + } elsif ($header =~ m/^heap profile:/) { + $main::profile_type = 'heap'; + $result = ReadHeapProfile($prog, *PROFILE, $header); + } elsif ($header =~ m/^--- *$contention_marker/o) { + $main::profile_type = 'contention'; + $result = ReadSynchProfile($prog, *PROFILE); + } elsif ($header =~ m/^--- *Stacks:/) { + print STDERR + "Old format contention profile: mistakenly reports " . + "condition variable signals as lock contentions.\n"; + $main::profile_type = 'contention'; + $result = ReadSynchProfile($prog, *PROFILE); + } elsif ($header =~ m/^--- *$profile_marker/) { + # the binary cpu profile data starts immediately after this line + $main::profile_type = 'cpu'; + $result = ReadCPUProfile($prog, $fname, *PROFILE); + } else { + if (defined($symbols)) { + # a symbolized profile contains a format we don't recognize, bail out + error("$fname: Cannot recognize profile section after symbols.\n"); + } + # no ascii header present -- must be a CPU profile + $main::profile_type = 'cpu'; + $result = ReadCPUProfile($prog, $fname, *PROFILE); + } + + close(PROFILE); + + # if we got symbols along with the profile, return those as well + if (defined($symbols)) { + $result->{symbols} = $symbols; + } + + return $result; +} + +# Subtract one from caller pc so we map back to call instr. +# However, don't do this if we're reading a symbolized profile +# file, in which case the subtract-one was done when the file +# was written. +# +# We apply the same logic to all readers, though ReadCPUProfile uses an +# independent implementation. +sub FixCallerAddresses { + my $stack = shift; + if ($main::use_symbolized_profile) { + return $stack; + } else { + $stack =~ /(\s)/; + my $delimiter = $1; + my @addrs = split(' ', $stack); + my @fixedaddrs; + $#fixedaddrs = $#addrs; + if ($#addrs >= 0) { + $fixedaddrs[0] = $addrs[0]; + } + for (my $i = 1; $i <= $#addrs; $i++) { + $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1"); + } + return join $delimiter, @fixedaddrs; + } +} + +# CPU profile reader +sub ReadCPUProfile { + my $prog = shift; + my $fname = shift; # just used for logging + local *PROFILE = shift; + my $version; + my $period; + my $i; + my $profile = {}; + my $pcs = {}; + + # Parse string into array of slots. + my $slots = CpuProfileStream->new(*PROFILE, $fname); + + # Read header. The current header version is a 5-element structure + # containing: + # 0: header count (always 0) + # 1: header "words" (after this one: 3) + # 2: format version (0) + # 3: sampling period (usec) + # 4: unused padding (always 0) + if ($slots->get(0) != 0 ) { + error("$fname: not a profile file, or old format profile file\n"); + } + $i = 2 + $slots->get(1); + $version = $slots->get(2); + $period = $slots->get(3); + # Do some sanity checking on these header values. + if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) { + error("$fname: not a profile file, or corrupted profile file\n"); + } + + # Parse profile + while ($slots->get($i) != -1) { + my $n = $slots->get($i++); + my $d = $slots->get($i++); + if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth? + my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8)); + print STDERR "At index $i (address $addr):\n"; + error("$fname: stack trace depth >= 2**32\n"); + } + if ($slots->get($i) == 0) { + # End of profile data marker + $i += $d; + last; + } + + # Make key out of the stack entries + my @k = (); + for (my $j = 0; $j < $d; $j++) { + my $pc = $slots->get($i+$j); + # Subtract one from caller pc so we map back to call instr. + # However, don't do this if we're reading a symbolized profile + # file, in which case the subtract-one was done when the file + # was written. + if ($j > 0 && !$main::use_symbolized_profile) { + $pc--; + } + $pc = sprintf("%0*x", $address_length, $pc); + $pcs->{$pc} = 1; + push @k, $pc; + } + + AddEntry($profile, (join "\n", @k), $n); + $i += $d; + } + + # Parse map + my $map = ''; + seek(PROFILE, $i * ($address_length / 2), 0); + read(PROFILE, $map, (stat PROFILE)[7]); + + my $r = {}; + $r->{version} = $version; + $r->{period} = $period; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + + return $r; +} + +sub ReadHeapProfile { + my $prog = shift; + local *PROFILE = shift; + my $header = shift; + + my $index = 1; + if ($main::opt_inuse_space) { + $index = 1; + } elsif ($main::opt_inuse_objects) { + $index = 0; + } elsif ($main::opt_alloc_space) { + $index = 3; + } elsif ($main::opt_alloc_objects) { + $index = 2; + } + + # Find the type of this profile. The header line looks like: + # heap profile: 1246: 8800744 [ 1246: 8800744] @ /266053 + # There are two pairs , the first inuse objects/space, and the + # second allocated objects/space. This is followed optionally by a profile + # type, and if that is present, optionally by a sampling frequency. + # For remote heap profiles (v1): + # The interpretation of the sampling frequency is that the profiler, for + # each sample, calculates a uniformly distributed random integer less than + # the given value, and records the next sample after that many bytes have + # been allocated. Therefore, the expected sample interval is half of the + # given frequency. By default, if not specified, the expected sample + # interval is 128KB. Only remote-heap-page profiles are adjusted for + # sample size. + # For remote heap profiles (v2): + # The sampling frequency is the rate of a Poisson process. This means that + # the probability of sampling an allocation of size X with sampling rate Y + # is 1 - exp(-X/Y) + # For version 2, a typical header line might look like this: + # heap profile: 1922: 127792360 [ 1922: 127792360] @ _v2/524288 + # the trailing number (524288) is the sampling rate. (Version 1 showed + # double the 'rate' here) + my $sampling_algorithm = 0; + my $sample_adjustment = 0; + chomp($header); + my $type = "unknown"; + if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") { + if (defined($6) && ($6 ne '')) { + $type = $6; + my $sample_period = $8; + # $type is "heapprofile" for profiles generated by the + # heap-profiler, and either "heap" or "heap_v2" for profiles + # generated by sampling directly within tcmalloc. It can also + # be "growth" for heap-growth profiles. The first is typically + # found for profiles generated locally, and the others for + # remote profiles. + if (($type eq "heapprofile") || ($type !~ /heap/) ) { + # No need to adjust for the sampling rate with heap-profiler-derived data + $sampling_algorithm = 0; + } elsif ($type =~ /_v2/) { + $sampling_algorithm = 2; # version 2 sampling + if (defined($sample_period) && ($sample_period ne '')) { + $sample_adjustment = int($sample_period); + } + } else { + $sampling_algorithm = 1; # version 1 sampling + if (defined($sample_period) && ($sample_period ne '')) { + $sample_adjustment = int($sample_period)/2; + } + } + } else { + # We detect whether or not this is a remote-heap profile by checking + # that the total-allocated stats ($n2,$s2) are exactly the + # same as the in-use stats ($n1,$s1). It is remotely conceivable + # that a non-remote-heap profile may pass this check, but it is hard + # to imagine how that could happen. + # In this case it's so old it's guaranteed to be remote-heap version 1. + my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); + if (($n1 == $n2) && ($s1 == $s2)) { + # This is likely to be a remote-heap based sample profile + $sampling_algorithm = 1; + } + } + } + + if ($sampling_algorithm > 0) { + # For remote-heap generated profiles, adjust the counts and sizes to + # account for the sample rate (we sample once every 128KB by default). + if ($sample_adjustment == 0) { + # Turn on profile adjustment. + $sample_adjustment = 128*1024; + print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n"; + } else { + printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n", + $sample_adjustment); + } + if ($sampling_algorithm > 1) { + # We don't bother printing anything for the original version (version 1) + printf STDERR "Heap version $sampling_algorithm\n"; + } + } + + my $profile = {}; + my $pcs = {}; + my $map = ""; + + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (/^MAPPED_LIBRARIES:/) { + # Read the /proc/self/maps data + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + $map .= $_; + } + last; + } + + if (/^--- Memory map:/) { + # Read /proc/self/maps data as formatted by DumpAddressMap() + my $buildvar = ""; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Parse "build=" specification if supplied + if (m/^\s*build=(.*)\n/) { + $buildvar = $1; + } + + # Expand "$build" variable if available + $_ =~ s/\$build\b/$buildvar/g; + + $map .= $_; + } + last; + } + + # Read entry of the form: + # : [: ] @ a1 a2 a3 ... an + s/^\s*//; + s/\s*$//; + if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) { + my $stack = $5; + my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); + + if ($sample_adjustment) { + if ($sampling_algorithm == 2) { + # Remote-heap version 2 + # The sampling frequency is the rate of a Poisson process. + # This means that the probability of sampling an allocation of + # size X with sampling rate Y is 1 - exp(-X/Y) + if ($n1 != 0) { + my $ratio = (($s1*1.0)/$n1)/($sample_adjustment); + my $scale_factor = 1/(1 - exp(-$ratio)); + $n1 *= $scale_factor; + $s1 *= $scale_factor; + } + if ($n2 != 0) { + my $ratio = (($s2*1.0)/$n2)/($sample_adjustment); + my $scale_factor = 1/(1 - exp(-$ratio)); + $n2 *= $scale_factor; + $s2 *= $scale_factor; + } + } else { + # Remote-heap version 1 + my $ratio; + $ratio = (($s1*1.0)/$n1)/($sample_adjustment); + if ($ratio < 1) { + $n1 /= $ratio; + $s1 /= $ratio; + } + $ratio = (($s2*1.0)/$n2)/($sample_adjustment); + if ($ratio < 1) { + $n2 /= $ratio; + $s2 /= $ratio; + } + } + } + + my @counts = ($n1, $s1, $n2, $s2); + $stack = FixCallerAddresses($stack); + push @stackTraces, "$n1 $s1 $n2 $s2 $stack"; + AddEntries($profile, $pcs, $stack, $counts[$index]); + } + } + + my $r = {}; + $r->{version} = "heap"; + $r->{period} = 1; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + return $r; +} + +sub ReadSynchProfile { + my $prog = shift; + local *PROFILE = shift; + my $header = shift; + + my $map = ''; + my $profile = {}; + my $pcs = {}; + my $sampling_period = 1; + my $cyclespernanosec = 2.8; # Default assumption for old binaries + my $seen_clockrate = 0; + my $line; + + my $index = 0; + if ($main::opt_total_delay) { + $index = 0; + } elsif ($main::opt_contentions) { + $index = 1; + } elsif ($main::opt_mean_delay) { + $index = 2; + } + + while ( $line = ) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) { + my ($cycles, $count, $stack) = ($1, $2, $3); + + # Convert cycles to nanoseconds + $cycles /= $cyclespernanosec; + + # Adjust for sampling done by application + $cycles *= $sampling_period; + $count *= $sampling_period; + + my @values = ($cycles, $count, $cycles / $count); + AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]); + + } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ || + $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) { + my ($cycles, $stack) = ($1, $2); + if ($cycles !~ /^\d+$/) { + next; + } + + # Convert cycles to nanoseconds + $cycles /= $cyclespernanosec; + + # Adjust for sampling done by application + $cycles *= $sampling_period; + + AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles); + + } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) { + my ($variable, $value) = ($1,$2); + for ($variable, $value) { + s/^\s+//; + s/\s+$//; + } + if ($variable eq "cycles/second") { + $cyclespernanosec = $value / 1e9; + $seen_clockrate = 1; + } elsif ($variable eq "sampling period") { + $sampling_period = $value; + } elsif ($variable eq "ms since reset") { + # Currently nothing is done with this value in pprof + # So we just silently ignore it for now + } elsif ($variable eq "discarded samples") { + # Currently nothing is done with this value in pprof + # So we just silently ignore it for now + } else { + printf STDERR ("Ignoring unnknown variable in /contention output: " . + "'%s' = '%s'\n",$variable,$value); + } + } else { + # Memory map entry + $map .= $line; + } + } + + if (!$seen_clockrate) { + printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n", + $cyclespernanosec); + } + + my $r = {}; + $r->{version} = 0; + $r->{period} = $sampling_period; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + return $r; +} + +# Given a hex value in the form "0x1abcd" or "1abcd", return either +# "0001abcd" or "000000000001abcd", depending on the current (global) +# address length. +sub HexExtend { + my $addr = shift; + + $addr =~ s/^(0x)?0*//; + my $zeros_needed = $address_length - length($addr); + if ($zeros_needed < 0) { + printf STDERR "Warning: address $addr is longer than address length $address_length\n"; + return $addr; + } + return ("0" x $zeros_needed) . $addr; +} + +##### Symbol extraction ##### + +# Aggressively search the lib_prefix values for the given library +# If all else fails, just return the name of the library unmodified. +# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so" +# it will search the following locations in this order, until it finds a file: +# /my/path/lib/dir/mylib.so +# /other/path/lib/dir/mylib.so +# /my/path/dir/mylib.so +# /other/path/dir/mylib.so +# /my/path/mylib.so +# /other/path/mylib.so +# /lib/dir/mylib.so (returned as last resort) +sub FindLibrary { + my $file = shift; + my $suffix = $file; + + # Search for the library as described above + do { + foreach my $prefix (@prefix_list) { + my $fullpath = $prefix . $suffix; + if (-e $fullpath) { + return $fullpath; + } + } + } while ($suffix =~ s|^/[^/]+/|/|); + return $file; +} + +# Return path to library with debugging symbols. +# For libc libraries, the copy in /usr/lib/debug contains debugging symbols +sub DebuggingLibrary { + my $file = shift; + if ($file =~ m|^/| && -f "/usr/lib/debug$file") { + return "/usr/lib/debug$file"; + } + if ($file =~ m|^/| && -f "/usr/lib/debug$file.debug") { + return "/usr/lib/debug$file.debug"; + } + return undef; +} + +# Parse text section header of a library using objdump +sub ParseTextSectionHeaderFromObjdump { + my $lib = shift; + + my $size = undef; + my $vma; + my $file_offset; + # Get objdump output from the library file to figure out how to + # map between mapped addresses and addresses in the library. + my $cmd = ShellEscape($obj_tool_map{"objdump"}, "-h", $lib); + open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Idx Name Size VMA LMA File off Algn + # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4 + # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file + # offset may still be 8. But AddressSub below will still handle that. + my @x = split; + if (($#x >= 6) && ($x[1] eq '.text')) { + $size = $x[2]; + $vma = $x[3]; + $file_offset = $x[5]; + last; + } + } + close(OBJDUMP); + + if (!defined($size)) { + return undef; + } + + my $r = {}; + $r->{size} = $size; + $r->{vma} = $vma; + $r->{file_offset} = $file_offset; + + return $r; +} + +# Parse text section header of a library using otool (on OS X) +sub ParseTextSectionHeaderFromOtool { + my $lib = shift; + + my $size = undef; + my $vma = undef; + my $file_offset = undef; + # Get otool output from the library file to figure out how to + # map between mapped addresses and addresses in the library. + my $command = ShellEscape($obj_tool_map{"otool"}, "-l", $lib); + open(OTOOL, "$command |") || error("$command: $!\n"); + my $cmd = ""; + my $sectname = ""; + my $segname = ""; + foreach my $line () { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + # Load command <#> + # cmd LC_SEGMENT + # [...] + # Section + # sectname __text + # segname __TEXT + # addr 0x000009f8 + # size 0x00018b9e + # offset 2552 + # align 2^2 (4) + # We will need to strip off the leading 0x from the hex addresses, + # and convert the offset into hex. + if ($line =~ /Load command/) { + $cmd = ""; + $sectname = ""; + $segname = ""; + } elsif ($line =~ /Section/) { + $sectname = ""; + $segname = ""; + } elsif ($line =~ /cmd (\w+)/) { + $cmd = $1; + } elsif ($line =~ /sectname (\w+)/) { + $sectname = $1; + } elsif ($line =~ /segname (\w+)/) { + $segname = $1; + } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") && + $sectname eq "__text" && + $segname eq "__TEXT")) { + next; + } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) { + $vma = $1; + } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) { + $size = $1; + } elsif ($line =~ /\boffset ([0-9]+)/) { + $file_offset = sprintf("%016x", $1); + } + if (defined($vma) && defined($size) && defined($file_offset)) { + last; + } + } + close(OTOOL); + + if (!defined($vma) || !defined($size) || !defined($file_offset)) { + return undef; + } + + my $r = {}; + $r->{size} = $size; + $r->{vma} = $vma; + $r->{file_offset} = $file_offset; + + return $r; +} + +sub ParseTextSectionHeader { + # obj_tool_map("otool") is only defined if we're in a Mach-O environment + if (defined($obj_tool_map{"otool"})) { + my $r = ParseTextSectionHeaderFromOtool(@_); + if (defined($r)){ + return $r; + } + } + # If otool doesn't work, or we don't have it, fall back to objdump + return ParseTextSectionHeaderFromObjdump(@_); +} + +# Split /proc/pid/maps dump into a list of libraries +sub ParseLibraries { + return if $main::use_symbol_page; # We don't need libraries info. + my $prog = Cwd::abs_path(shift); + my $map = shift; + my $pcs = shift; + + my $result = []; + my $h = "[a-f0-9]+"; + my $zero_offset = HexExtend("0"); + + my $buildvar = ""; + foreach my $l (split("\n", $map)) { + if ($l =~ m/^\s*build=(.*)$/) { + $buildvar = $1; + } + + my $start; + my $finish; + my $offset; + my $lib; + if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(.+\.(so|dll|dylib|bundle|node)((\.\d+)+\w*(\.\d+){0,3})?)$/i) { + # Full line from /proc/self/maps. Example: + # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = HexExtend($3); + $lib = $4; + $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths + } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) { + # Cooked line from DumpAddressMap. Example: + # 40000000-40015000: /lib/ld-2.3.2.so + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = $zero_offset; + $lib = $3; + } elsif (($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+)$/i) && ($4 eq $prog)) { + # PIEs and address space randomization do not play well with our + # default assumption that main executable is at lowest + # addresses. So we're detecting main executable in + # /proc/self/maps as well. + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = HexExtend($3); + $lib = $4; + $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths + } else { + next; + } + + # Expand "$build" variable if available + $lib =~ s/\$build\b/$buildvar/g; + + $lib = FindLibrary($lib); + + # Check for pre-relocated libraries, which use pre-relocated symbol tables + # and thus require adjusting the offset that we'll use to translate + # VM addresses into symbol table addresses. + # Only do this if we're not going to fetch the symbol table from a + # debugging copy of the library. + if (!DebuggingLibrary($lib)) { + my $text = ParseTextSectionHeader($lib); + if (defined($text)) { + my $vma_offset = AddressSub($text->{vma}, $text->{file_offset}); + $offset = AddressAdd($offset, $vma_offset); + } + } + + push(@{$result}, [$lib, $start, $finish, $offset]); + } + + # Append special entry for additional library (not relocated) + if ($main::opt_lib ne "") { + my $text = ParseTextSectionHeader($main::opt_lib); + if (defined($text)) { + my $start = $text->{vma}; + my $finish = AddressAdd($start, $text->{size}); + + push(@{$result}, [$main::opt_lib, $start, $finish, $start]); + } + } + + # Append special entry for the main program. This covers + # 0..max_pc_value_seen, so that we assume pc values not found in one + # of the library ranges will be treated as coming from the main + # program binary. + my $min_pc = HexExtend("0"); + my $max_pc = $min_pc; # find the maximal PC value in any sample + foreach my $pc (keys(%{$pcs})) { + if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); } + } + push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]); + + return $result; +} + +# Add two hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressAdd { + my $addr1 = shift; + my $addr2 = shift; + my $sum; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16); + return sprintf("%08x", $sum); + + } else { + # Do the addition in 7-nibble chunks to trivialize carry handling. + + if ($main::opt_debug and $main::opt_test) { + print STDERR "AddressAdd $addr1 + $addr2 = "; + } + + my $a1 = substr($addr1,-7); + $addr1 = substr($addr1,0,-7); + my $a2 = substr($addr2,-7); + $addr2 = substr($addr2,0,-7); + $sum = hex($a1) + hex($a2); + my $c = 0; + if ($sum > 0xfffffff) { + $c = 1; + $sum -= 0x10000000; + } + my $r = sprintf("%07x", $sum); + + $a1 = substr($addr1,-7); + $addr1 = substr($addr1,0,-7); + $a2 = substr($addr2,-7); + $addr2 = substr($addr2,0,-7); + $sum = hex($a1) + hex($a2) + $c; + $c = 0; + if ($sum > 0xfffffff) { + $c = 1; + $sum -= 0x10000000; + } + $r = sprintf("%07x", $sum) . $r; + + $sum = hex($addr1) + hex($addr2) + $c; + if ($sum > 0xff) { $sum -= 0x100; } + $r = sprintf("%02x", $sum) . $r; + + if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; } + + return $r; + } +} + + +# Subtract two hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressSub { + my $addr1 = shift; + my $addr2 = shift; + my $diff; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16); + return sprintf("%08x", $diff); + + } else { + # Do the addition in 7-nibble chunks to trivialize borrow handling. + # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; } + + my $a1 = hex(substr($addr1,-7)); + $addr1 = substr($addr1,0,-7); + my $a2 = hex(substr($addr2,-7)); + $addr2 = substr($addr2,0,-7); + my $b = 0; + if ($a2 > $a1) { + $b = 1; + $a1 += 0x10000000; + } + $diff = $a1 - $a2; + my $r = sprintf("%07x", $diff); + + $a1 = hex(substr($addr1,-7)); + $addr1 = substr($addr1,0,-7); + $a2 = hex(substr($addr2,-7)) + $b; + $addr2 = substr($addr2,0,-7); + $b = 0; + if ($a2 > $a1) { + $b = 1; + $a1 += 0x10000000; + } + $diff = $a1 - $a2; + $r = sprintf("%07x", $diff) . $r; + + $a1 = hex($addr1); + $a2 = hex($addr2) + $b; + if ($a2 > $a1) { $a1 += 0x100; } + $diff = $a1 - $a2; + $r = sprintf("%02x", $diff) . $r; + + # if ($main::opt_debug) { print STDERR "$r\n"; } + + return $r; + } +} + +# Increment a hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressInc { + my $addr = shift; + my $sum; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $sum = (hex($addr)+1) % (0x10000000 * 16); + return sprintf("%08x", $sum); + + } else { + # Do the addition in 7-nibble chunks to trivialize carry handling. + # We are always doing this to step through the addresses in a function, + # and will almost never overflow the first chunk, so we check for this + # case and exit early. + + # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; } + + my $a1 = substr($addr,-7); + $addr = substr($addr,0,-7); + $sum = hex($a1) + 1; + my $r = sprintf("%07x", $sum); + if ($sum <= 0xfffffff) { + $r = $addr . $r; + # if ($main::opt_debug) { print STDERR "$r\n"; } + return HexExtend($r); + } else { + $r = "0000000"; + } + + $a1 = substr($addr,-7); + $addr = substr($addr,0,-7); + $sum = hex($a1) + 1; + $r = sprintf("%07x", $sum) . $r; + if ($sum <= 0xfffffff) { + $r = $addr . $r; + # if ($main::opt_debug) { print STDERR "$r\n"; } + return HexExtend($r); + } else { + $r = "00000000000000"; + } + + $sum = hex($addr) + 1; + if ($sum > 0xff) { $sum -= 0x100; } + $r = sprintf("%02x", $sum) . $r; + + # if ($main::opt_debug) { print STDERR "$r\n"; } + return $r; + } +} + +# Extract symbols for all PC values found in profile +sub ExtractSymbols { + my $libs = shift; + my $pcset = shift; + + my $symbols = {}; + + # Map each PC value to the containing library. To make this faster, + # we sort libraries by their starting pc value (highest first), and + # advance through the libraries as we advance the pc. Sometimes the + # addresses of libraries may overlap with the addresses of the main + # binary, so to make sure the libraries 'win', we iterate over the + # libraries in reverse order (which assumes the binary doesn't start + # in the middle of a library, which seems a fair assumption). + my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings + foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) { + my $libname = $lib->[0]; + my $start = $lib->[1]; + my $finish = $lib->[2]; + my $offset = $lib->[3]; + + # Get list of pcs that belong in this library. + my $contained = []; + my ($start_pc_index, $finish_pc_index); + # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index]. + for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0; + $finish_pc_index--) { + last if $pcs[$finish_pc_index - 1] le $finish; + } + # Find smallest start_pc_index such that $start <= $pc[$start_pc_index]. + for ($start_pc_index = $finish_pc_index; $start_pc_index > 0; + $start_pc_index--) { + last if $pcs[$start_pc_index - 1] lt $start; + } + # This keeps PC values higher than $pc[$finish_pc_index] in @pcs, + # in case there are overlaps in libraries and the main binary. + @{$contained} = splice(@pcs, $start_pc_index, + $finish_pc_index - $start_pc_index); + # Map to symbols + MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols); + } + + return $symbols; +} + +# Map list of PC values to symbols for a given image +sub MapToSymbols { + my $image = shift; + my $offset = shift; + my $pclist = shift; + my $symbols = shift; + + my $debug = 0; + + # For libc (and other) libraries, the copy in /usr/lib/debug contains debugging symbols + my $debugging = DebuggingLibrary($image); + if ($debugging) { + $image = $debugging; + } + + # Ignore empty binaries + if ($#{$pclist} < 0) { return; } + + # Figure out the addr2line command to use + my $addr2line = $obj_tool_map{"addr2line"}; + my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image); + if (exists $obj_tool_map{"addr2line_pdb"}) { + $addr2line = $obj_tool_map{"addr2line_pdb"}; + $cmd = ShellEscape($addr2line, "--demangle", "-f", "-C", "-e", $image); + } + + # If "addr2line" isn't installed on the system at all, just use + # nm to get what info we can (function names, but not line numbers). + if (system(ShellEscape($addr2line, "--help") . " >$dev_null 2>&1") != 0) { + MapSymbolsWithNM($image, $offset, $pclist, $symbols); + return; + } + + # "addr2line -i" can produce a variable number of lines per input + # address, with no separator that allows us to tell when data for + # the next address starts. So we find the address for a special + # symbol (_fini) and interleave this address between all real + # addresses passed to addr2line. The name of this special symbol + # can then be used as a separator. + $sep_address = undef; # May be filled in by MapSymbolsWithNM() + my $nm_symbols = {}; + MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols); + if (defined($sep_address)) { + # Only add " -i" to addr2line if the binary supports it. + # addr2line --help returns 0, but not if it sees an unknown flag first. + if (system("$cmd -i --help >$dev_null 2>&1") == 0) { + $cmd .= " -i"; + } else { + $sep_address = undef; # no need for sep_address if we don't support -i + } + } + + # Make file with all PC values with intervening 'sep_address' so + # that we can reliably detect the end of inlined function list + open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n"); + if ($debug) { print("---- $image ---\n"); } + for (my $i = 0; $i <= $#{$pclist}; $i++) { + # addr2line always reads hex addresses, and does not need '0x' prefix. + if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); } + printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset)); + if (defined($sep_address)) { + printf ADDRESSES ("%s\n", $sep_address); + } + } + close(ADDRESSES); + if ($debug) { + print("----\n"); + system("cat", $main::tmpfile_sym); + print("---- $cmd ---\n"); + system("$cmd < " . ShellEscape($main::tmpfile_sym)); + print("----\n"); + } + + open(SYMBOLS, "$cmd <" . ShellEscape($main::tmpfile_sym) . " |") + || error("$cmd: $!\n"); + my $count = 0; # Index in pclist + while () { + # Read fullfunction and filelineinfo from next pair of lines + s/\r?\n$//g; + my $fullfunction = $_; + $_ = ; + s/\r?\n$//g; + my $filelinenum = $_; + + if (defined($sep_address) && $fullfunction eq $sep_symbol) { + # Terminating marker for data for this address + $count++; + next; + } + + $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths + + # Remove discriminator markers as this comes after the line number and + # confuses the rest of this script. + $filelinenum =~ s/ \(discriminator \d+\)$//; + # Convert unknown line numbers into line 0. + $filelinenum =~ s/:\?$/:0/; + + my $pcstr = $pclist->[$count]; + my $function = ShortFunctionName($fullfunction); + my $nms = $nm_symbols->{$pcstr}; + if (defined($nms)) { + if ($fullfunction eq '??') { + # nm found a symbol for us. + $function = $nms->[0]; + $fullfunction = $nms->[2]; + } else { + # MapSymbolsWithNM tags each routine with its starting address, + # useful in case the image has multiple occurrences of this + # routine. (It uses a syntax that resembles template paramters, + # that are automatically stripped out by ShortFunctionName().) + # addr2line does not provide the same information. So we check + # if nm disambiguated our symbol, and if so take the annotated + # (nm) version of the routine-name. TODO(csilvers): this won't + # catch overloaded, inlined symbols, which nm doesn't see. + # Better would be to do a check similar to nm's, in this fn. + if ($nms->[2] =~ m/^\Q$function\E/) { # sanity check it's the right fn + $function = $nms->[0]; + $fullfunction = $nms->[2]; + } + } + } + + # Prepend to accumulated symbols for pcstr + # (so that caller comes before callee) + my $sym = $symbols->{$pcstr}; + if (!defined($sym)) { + $sym = []; + $symbols->{$pcstr} = $sym; + } + unshift(@{$sym}, $function, $filelinenum, $fullfunction); + if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); } + if (!defined($sep_address)) { + # Inlining is off, so this entry ends immediately + $count++; + } + } + close(SYMBOLS); +} + +# Use nm to map the list of referenced PCs to symbols. Return true iff we +# are able to read procedure information via nm. +sub MapSymbolsWithNM { + my $image = shift; + my $offset = shift; + my $pclist = shift; + my $symbols = shift; + + # Get nm output sorted by increasing address + my $symbol_table = GetProcedureBoundaries($image, "."); + if (!%{$symbol_table}) { + return 0; + } + # Start addresses are already the right length (8 or 16 hex digits). + my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] } + keys(%{$symbol_table}); + + if ($#names < 0) { + # No symbols: just use addresses + foreach my $pc (@{$pclist}) { + my $pcstr = "0x" . $pc; + $symbols->{$pc} = [$pcstr, "?", $pcstr]; + } + return 0; + } + + # Sort addresses so we can do a join against nm output + my $index = 0; + my $fullname = $names[0]; + my $name = ShortFunctionName($fullname); + foreach my $pc (sort { $a cmp $b } @{$pclist}) { + # Adjust for mapped offset + my $mpc = AddressSub($pc, $offset); + while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){ + $index++; + $fullname = $names[$index]; + $name = ShortFunctionName($fullname); + } + if ($mpc lt $symbol_table->{$fullname}->[1]) { + $symbols->{$pc} = [$name, "?", $fullname]; + } else { + my $pcstr = "0x" . $pc; + $symbols->{$pc} = [$pcstr, "?", $pcstr]; + } + } + return 1; +} + +sub ShortFunctionName { + my $function = shift; + while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types + $function =~ s/<[0-9a-f]*>$//g; # Remove Address + if (!$main::opt_no_strip_temp) { + while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments + } + $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type + return $function; +} + +# Trim overly long symbols found in disassembler output +sub CleanDisassembly { + my $d = shift; + while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax) + while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments + return $d; +} + +# Clean file name for display +sub CleanFileName { + my ($f) = @_; + $f =~ s|^/proc/self/cwd/||; + $f =~ s|^\./||; + return $f; +} + +# Make address relative to section and clean up for display +sub UnparseAddress { + my ($offset, $address) = @_; + $address = AddressSub($address, $offset); + $address =~ s/^0x//; + $address =~ s/^0*//; + return $address; +} + +##### Miscellaneous ##### + +# Find the right versions of the above object tools to use. The +# argument is the program file being analyzed, and should be an ELF +# 32-bit or ELF 64-bit executable file. The location of the tools +# is determined by considering the following options in this order: +# 1) --tools option, if set +# 2) PPROF_TOOLS environment variable, if set +# 3) the environment +sub ConfigureObjTools { + my $prog_file = shift; + + # Check for the existence of $prog_file because /usr/bin/file does not + # predictably return error status in prod. + (-e $prog_file) || error("$prog_file does not exist.\n"); + + my $file_type = undef; + if (-e "/usr/bin/file") { + # Follow symlinks (at least for systems where "file" supports that). + my $escaped_prog_file = ShellEscape($prog_file); + $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null || + /usr/bin/file $escaped_prog_file`; + } elsif ($^O == "MSWin32") { + $file_type = "MS Windows"; + } else { + print STDERR "WARNING: Can't determine the file type of $prog_file"; + } + + if ($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; + } + + if ($file_type =~ /MS Windows/) { + # For windows, we provide a version of nm and addr2line as part of + # the opensource release, which is capable of parsing + # Windows-style PDB executables. It should live in the path, or + # in the same directory as pprof. + $obj_tool_map{"nm_pdb"} = "nm-pdb"; + $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb"; + } + + if ($file_type =~ /Mach-O/) { + # OS X uses otool to examine Mach-O files, rather than objdump. + $obj_tool_map{"otool"} = "otool"; + $obj_tool_map{"addr2line"} = "false"; # no addr2line + $obj_tool_map{"objdump"} = "false"; # no objdump + } + + # Go fill in %obj_tool_map with the pathnames to use: + foreach my $tool (keys %obj_tool_map) { + $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool}); + } +} + +# Returns the path of a caller-specified object tool. If --tools or +# PPROF_TOOLS are specified, then returns the full path to the tool +# with that prefix. Otherwise, returns the path unmodified (which +# means we will look for it on PATH). +sub ConfigureTool { + my $tool = shift; + my $path; + + # --tools (or $PPROF_TOOLS) is a comma separated list, where each + # item is either a) a pathname prefix, or b) a map of the form + # :. First we look for an entry of type (b) for our + # tool. If one is found, we use it. Otherwise, we consider all the + # pathname prefixes in turn, until one yields an existing file. If + # none does, we use a default path. + my $tools = $main::opt_tools || $ENV{"PPROF_TOOLS"} || ""; + if ($tools =~ m/(,|^)\Q$tool\E:([^,]*)/) { + $path = $2; + # TODO(csilvers): sanity-check that $path exists? Hard if it's relative. + } elsif ($tools ne '') { + foreach my $prefix (split(',', $tools)) { + next if ($prefix =~ /:/); # ignore "tool:fullpath" entries in the list + if (-x $prefix . $tool) { + $path = $prefix . $tool; + last; + } + } + if (!$path) { + error("No '$tool' found with prefix specified by " . + "--tools (or \$PPROF_TOOLS) '$tools'\n"); + } + } else { + # ... otherwise use the version that exists in the same directory as + # pprof. If there's nothing there, use $PATH. + $0 =~ m,[^/]*$,; # this is everything after the last slash + my $dirname = $`; # this is everything up to and including the last slash + if (-x "$dirname$tool") { + $path = "$dirname$tool"; + } else { + $path = $tool; + } + } + if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; } + return $path; +} + +sub ShellEscape { + my @escaped_words = (); + foreach my $word (@_) { + my $escaped_word = $word; + if ($word =~ m![^a-zA-Z0-9/.,_=-]!) { # check for anything not in whitelist + $escaped_word =~ s/'/'\\''/; + $escaped_word = "'$escaped_word'"; + } + push(@escaped_words, $escaped_word); + } + return join(" ", @escaped_words); +} + +sub cleanup { + unlink($main::tmpfile_sym); + unlink(keys %main::tempnames); + + # We leave any collected profiles in $HOME/pprof in case the user wants + # to look at them later. We print a message informing them of this. + if ((scalar(@main::profile_files) > 0) && + defined($main::collected_profile)) { + if (scalar(@main::profile_files) == 1) { + print STDERR "Dynamically gathered profile is in $main::collected_profile\n"; + } + print STDERR "If you want to investigate this profile further, you can do:\n"; + print STDERR "\n"; + print STDERR " $0 \\\n"; + print STDERR " $main::prog \\\n"; + print STDERR " $main::collected_profile\n"; + print STDERR "\n"; + } +} + +sub sighandler { + cleanup(); + exit(1); +} + +sub error { + my $msg = shift; + print STDERR $msg; + cleanup(); + exit(1); +} + + +# Run $nm_command and get all the resulting procedure boundaries whose +# names match "$regexp" and returns them in a hashtable mapping from +# procedure name to a two-element vector of [start address, end address] +sub GetProcedureBoundariesViaNm { + my $escaped_nm_command = shift; # shell-escaped + my $regexp = shift; + my $image = shift; + + my $symbol_table = {}; + open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n"); + my $last_start = "0"; + my $routine = ""; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (m/^\s*([0-9a-f]+) (.) (..*)/) { + my $start_val = $1; + my $type = $2; + my $this_routine = $3; + + # It's possible for two symbols to share the same address, if + # one is a zero-length variable (like __start_google_malloc) or + # one symbol is a weak alias to another (like __libc_malloc). + # In such cases, we want to ignore all values except for the + # actual symbol, which in nm-speak has type "T". The logic + # below does this, though it's a bit tricky: what happens when + # we have a series of lines with the same address, is the first + # one gets queued up to be processed. However, it won't + # *actually* be processed until later, when we read a line with + # a different address. That means that as long as we're reading + # lines with the same address, we have a chance to replace that + # item in the queue, which we do whenever we see a 'T' entry -- + # that is, a line with type 'T'. If we never see a 'T' entry, + # we'll just go ahead and process the first entry (which never + # got touched in the queue), and ignore the others. + if ($start_val eq $last_start && $type =~ /t/i) { + # We are the 'T' symbol at this address, replace previous symbol. + $routine = $this_routine; + next; + } elsif ($start_val eq $last_start) { + # We're not the 'T' symbol at this address, so ignore us. + next; + } + + if ($this_routine eq $sep_symbol) { + $sep_address = HexExtend($start_val); + } + + # Tag this routine with the starting address in case the image + # has multiple occurrences of this routine. We use a syntax + # that resembles template paramters that are automatically + # stripped out by ShortFunctionName() + $this_routine .= "<$start_val>"; + + if (defined($routine) && $routine =~ m/$regexp/) { + $symbol_table->{$routine} = [HexExtend($last_start), + HexExtend($start_val)]; + } + $last_start = $start_val; + $routine = $this_routine; + } elsif (m/^Loaded image name: (.+)/) { + # The win32 nm workalike emits information about the binary it is using. + if ($main::opt_debug) { print STDERR "Using Image $1\n"; } + } elsif (m/^PDB file name: (.+)/) { + # The win32 nm workalike emits information about the pdb it is using. + if ($main::opt_debug) { print STDERR "Using PDB $1\n"; } + } + } + close(NM); + # Handle the last line in the nm output. Unfortunately, we don't know + # how big this last symbol is, because we don't know how big the file + # is. For now, we just give it a size of 0. + # TODO(csilvers): do better here. + if (defined($routine) && $routine =~ m/$regexp/) { + $symbol_table->{$routine} = [HexExtend($last_start), + HexExtend($last_start)]; + } + + # Verify if addr2line can find the $sep_symbol. If not, we use objdump + # to find the address for the $sep_symbol on code section which addr2line + # can find. + if (defined($sep_address)){ + my $start_val = $sep_address; + my $addr2line = $obj_tool_map{"addr2line"}; + my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image, "-i"); + open(FINI, "echo $start_val | $cmd |") + || error("echo $start_val | $cmd: $!\n"); + $_ = ; + s/\r?\n$//g; + my $fini = $_; + close(FINI); + if ($fini ne $sep_symbol){ + my $objdump = $obj_tool_map{"objdump"}; + $cmd = ShellEscape($objdump, "-d", $image); + my $grep = ShellEscape("grep", $sep_symbol); + my $tail = ShellEscape("tail", "-n", "1"); + open(FINI, "$cmd | $grep | $tail |") + || error("$cmd | $grep | $tail: $!\n"); + s/\r//g; # turn windows-looking lines into unix-looking lines + my $data = ; + if (defined($data)){ + ($start_val, $fini) = split(/ $dev_null 2>&1"; + if (system(ShellEscape($nm, "--demangle", $image) . $to_devnull) == 0) { + # In this mode, we do "nm --demangle " + $demangle_flag = "--demangle"; + $cppfilt_flag = ""; + } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) { + # In this mode, we do "nm | c++filt" + $cppfilt_flag = " | " . ShellEscape($cppfilt); + }; + my $flatten_flag = ""; + if (system(ShellEscape($nm, "-f", $image) . $to_devnull) == 0) { + $flatten_flag = "-f"; + } + + # Finally, in the case $imagie isn't a debug library, we try again with + # -D to at least get *exported* symbols. If we can't use --demangle, + # we use c++filt instead, if it exists on this system. + my @nm_commands = (ShellEscape($nm, "-n", $flatten_flag, $demangle_flag, + $image) . " 2>$dev_null $cppfilt_flag", + ShellEscape($nm, "-D", "-n", $flatten_flag, $demangle_flag, + $image) . " 2>$dev_null $cppfilt_flag", + # 6nm is for Go binaries + ShellEscape("6nm", "$image") . " 2>$dev_null | sort", + ); + + # If the executable is an MS Windows PDB-format executable, we'll + # have set up obj_tool_map("nm_pdb"). In this case, we actually + # want to use both unix nm and windows-specific nm_pdb, since + # PDB-format executables can apparently include dwarf .o files. + if (exists $obj_tool_map{"nm_pdb"}) { + push(@nm_commands, + ShellEscape($obj_tool_map{"nm_pdb"}, "--demangle", $image) + . " 2>$dev_null"); + } + + foreach my $nm_command (@nm_commands) { + my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp, $image); + return $symbol_table if (%{$symbol_table}); + } + my $symbol_table = {}; + return $symbol_table; +} + + +# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings. +# To make them more readable, we add underscores at interesting places. +# This routine removes the underscores, producing the canonical representation +# used by pprof to represent addresses, particularly in the tested routines. +sub CanonicalHex { + my $arg = shift; + return join '', (split '_',$arg); +} + + +# Unit test for AddressAdd: +sub AddressAddUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressAdd ($row->[0], $row->[1]); + if ($sum ne $row->[2]) { + printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, + $row->[0], $row->[1], $row->[2]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1])); + my $expected = join '', (split '_',$row->[2]); + if ($sum ne CanonicalHex($row->[2])) { + printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, + $row->[0], $row->[1], $row->[2]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Unit test for AddressSub: +sub AddressSubUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressSub ($row->[0], $row->[1]); + if ($sum ne $row->[3]) { + printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, + $row->[0], $row->[1], $row->[3]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1])); + if ($sum ne CanonicalHex($row->[3])) { + printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, + $row->[0], $row->[1], $row->[3]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Unit test for AddressInc: +sub AddressIncUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressInc ($row->[0]); + if ($sum ne $row->[4]) { + printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, + $row->[0], $row->[4]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressInc (CanonicalHex($row->[0])); + if ($sum ne CanonicalHex($row->[4])) { + printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, + $row->[0], $row->[4]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Driver for unit tests. +# Currently just the address add/subtract/increment routines for 64-bit. +sub RunUnitTests { + my $error_count = 0; + + # This is a list of tuples [a, b, a+b, a-b, a+1] + my $unit_test_data_8 = [ + [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)], + [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)], + [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)], + [qw(00000001 ffffffff 00000000 00000002 00000002)], + [qw(00000001 fffffff0 fffffff1 00000011 00000002)], + ]; + my $unit_test_data_16 = [ + # The implementation handles data in 7-nibble chunks, so those are the + # interesting boundaries. + [qw(aaaaaaaa 50505050 + 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)], + [qw(50505050 aaaaaaaa + 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)], + [qw(ffffffff aaaaaaaa + 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)], + [qw(00000001 ffffffff + 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)], + [qw(00000001 fffffff0 + 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)], + + [qw(00_a00000a_aaaaaaa 50505050 + 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)], + [qw(0f_fff0005_0505050 aaaaaaaa + 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)], + [qw(00_000000f_fffffff 01_800000a_aaaaaaa + 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)], + [qw(00_0000000_0000001 ff_fffffff_fffffff + 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)], + [qw(00_0000000_0000001 ff_fffffff_ffffff0 + ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)], + ]; + + $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16); + $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16); + $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16); + if ($error_count > 0) { + print STDERR $error_count, " errors: FAILED\n"; + } else { + print STDERR "PASS\n"; + } + exit ($error_count); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/addressmap-inl.h b/trunk/3rdparty/gperftools-2-fit/src/addressmap-inl.h new file mode 100644 index 000000000..524aff687 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/addressmap-inl.h @@ -0,0 +1,422 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// A fast map from addresses to values. Assumes that addresses are +// clustered. The main use is intended to be for heap-profiling. +// May be too memory-hungry for other uses. +// +// We use a user-defined allocator/de-allocator so that we can use +// this data structure during heap-profiling. +// +// IMPLEMENTATION DETAIL: +// +// Some default definitions/parameters: +// * Block -- aligned 128-byte region of the address space +// * Cluster -- aligned 1-MB region of the address space +// * Block-ID -- block-number within a cluster +// * Cluster-ID -- Starting address of cluster divided by cluster size +// +// We use a three-level map to represent the state: +// 1. A hash-table maps from a cluster-ID to the data for that cluster. +// 2. For each non-empty cluster we keep an array indexed by +// block-ID tht points to the first entry in the linked-list +// for the block. +// 3. At the bottom, we keep a singly-linked list of all +// entries in a block (for non-empty blocks). +// +// hash table +// +-------------+ +// | id->cluster |---> ... +// | ... | +// | id->cluster |---> Cluster +// +-------------+ +-------+ Data for one block +// | nil | +------------------------------------+ +// | ----+---|->[addr/value]-->[addr/value]-->... | +// | nil | +------------------------------------+ +// | ----+--> ... +// | nil | +// | ... | +// +-------+ +// +// Note that we require zero-bytes of overhead for completely empty +// clusters. The minimum space requirement for a cluster is the size +// of the hash-table entry plus a pointer value for each block in +// the cluster. Empty blocks impose no extra space requirement. +// +// The cost of a lookup is: +// a. A hash-table lookup to find the cluster +// b. An array access in the cluster structure +// c. A traversal over the linked-list for a block + +#ifndef BASE_ADDRESSMAP_INL_H_ +#define BASE_ADDRESSMAP_INL_H_ + +#include "config.h" +#include +#include +#if defined HAVE_STDINT_H +#include // to get uint16_t (ISO naming madness) +#elif defined HAVE_INTTYPES_H +#include // another place uint16_t might be defined +#else +#include // our last best hope +#endif + +// This class is thread-unsafe -- that is, instances of this class can +// not be accessed concurrently by multiple threads -- because the +// callback function for Iterate() may mutate contained values. If the +// callback functions you pass do not mutate their Value* argument, +// AddressMap can be treated as thread-compatible -- that is, it's +// safe for multiple threads to call "const" methods on this class, +// but not safe for one thread to call const methods on this class +// while another thread is calling non-const methods on the class. +template +class AddressMap { + public: + typedef void* (*Allocator)(size_t size); + typedef void (*DeAllocator)(void* ptr); + typedef const void* Key; + + // Create an AddressMap that uses the specified allocator/deallocator. + // The allocator/deallocator should behave like malloc/free. + // For instance, the allocator does not need to return initialized memory. + AddressMap(Allocator alloc, DeAllocator dealloc); + ~AddressMap(); + + // If the map contains an entry for "key", return it. Else return NULL. + inline const Value* Find(Key key) const; + inline Value* FindMutable(Key key); + + // Insert into the map. Any old value associated + // with key is forgotten. + void Insert(Key key, Value value); + + // Remove any entry for key in the map. If an entry was found + // and removed, stores the associated value in "*removed_value" + // and returns true. Else returns false. + bool FindAndRemove(Key key, Value* removed_value); + + // Similar to Find but we assume that keys are addresses of non-overlapping + // memory ranges whose sizes are given by size_func. + // If the map contains a range into which "key" points + // (at its start or inside of it, but not at the end), + // return the address of the associated value + // and store its key in "*res_key". + // Else return NULL. + // max_size specifies largest range size possibly in existence now. + typedef size_t (*ValueSizeFunc)(const Value& v); + const Value* FindInside(ValueSizeFunc size_func, size_t max_size, + Key key, Key* res_key); + + // Iterate over the address map calling 'callback' + // for all stored key-value pairs and passing 'arg' to it. + // We don't use full Closure/Callback machinery not to add + // unnecessary dependencies to this class with low-level uses. + template + inline void Iterate(void (*callback)(Key, Value*, Type), Type arg) const; + + private: + typedef uintptr_t Number; + + // The implementation assumes that addresses inserted into the map + // will be clustered. We take advantage of this fact by splitting + // up the address-space into blocks and using a linked-list entry + // for each block. + + // Size of each block. There is one linked-list for each block, so + // do not make the block-size too big. Oterwise, a lot of time + // will be spent traversing linked lists. + static const int kBlockBits = 7; + static const int kBlockSize = 1 << kBlockBits; + + // Entry kept in per-block linked-list + struct Entry { + Entry* next; + Key key; + Value value; + }; + + // We further group a sequence of consecutive blocks into a cluster. + // The data for a cluster is represented as a dense array of + // linked-lists, one list per contained block. + static const int kClusterBits = 13; + static const Number kClusterSize = 1 << (kBlockBits + kClusterBits); + static const int kClusterBlocks = 1 << kClusterBits; + + // We use a simple chaining hash-table to represent the clusters. + struct Cluster { + Cluster* next; // Next cluster in hash table chain + Number id; // Cluster ID + Entry* blocks[kClusterBlocks]; // Per-block linked-lists + }; + + // Number of hash-table entries. With the block-size/cluster-size + // defined above, each cluster covers 1 MB, so an 4K entry + // hash-table will give an average hash-chain length of 1 for 4GB of + // in-use memory. + static const int kHashBits = 12; + static const int kHashSize = 1 << 12; + + // Number of entry objects allocated at a time + static const int ALLOC_COUNT = 64; + + Cluster** hashtable_; // The hash-table + Entry* free_; // Free list of unused Entry objects + + // Multiplicative hash function: + // The value "kHashMultiplier" is the bottom 32 bits of + // int((sqrt(5)-1)/2 * 2^32) + // This is a good multiplier as suggested in CLR, Knuth. The hash + // value is taken to be the top "k" bits of the bottom 32 bits + // of the muliplied value. + static const uint32_t kHashMultiplier = 2654435769u; + static int HashInt(Number x) { + // Multiply by a constant and take the top bits of the result. + const uint32_t m = static_cast(x) * kHashMultiplier; + return static_cast(m >> (32 - kHashBits)); + } + + // Find cluster object for specified address. If not found + // and "create" is true, create the object. If not found + // and "create" is false, return NULL. + // + // This method is bitwise-const if create is false. + Cluster* FindCluster(Number address, bool create) { + // Look in hashtable + const Number cluster_id = address >> (kBlockBits + kClusterBits); + const int h = HashInt(cluster_id); + for (Cluster* c = hashtable_[h]; c != NULL; c = c->next) { + if (c->id == cluster_id) { + return c; + } + } + + // Create cluster if necessary + if (create) { + Cluster* c = New(1); + c->id = cluster_id; + c->next = hashtable_[h]; + hashtable_[h] = c; + return c; + } + return NULL; + } + + // Return the block ID for an address within its cluster + static int BlockID(Number address) { + return (address >> kBlockBits) & (kClusterBlocks - 1); + } + + //-------------------------------------------------------------- + // Memory management -- we keep all objects we allocate linked + // together in a singly linked list so we can get rid of them + // when we are all done. Furthermore, we allow the client to + // pass in custom memory allocator/deallocator routines. + //-------------------------------------------------------------- + struct Object { + Object* next; + // The real data starts here + }; + + Allocator alloc_; // The allocator + DeAllocator dealloc_; // The deallocator + Object* allocated_; // List of allocated objects + + // Allocates a zeroed array of T with length "num". Also inserts + // the allocated block into a linked list so it can be deallocated + // when we are all done. + template T* New(int num) { + void* ptr = (*alloc_)(sizeof(Object) + num*sizeof(T)); + memset(ptr, 0, sizeof(Object) + num*sizeof(T)); + Object* obj = reinterpret_cast(ptr); + obj->next = allocated_; + allocated_ = obj; + return reinterpret_cast(reinterpret_cast(ptr) + 1); + } +}; + +// More implementation details follow: + +template +AddressMap::AddressMap(Allocator alloc, DeAllocator dealloc) + : free_(NULL), + alloc_(alloc), + dealloc_(dealloc), + allocated_(NULL) { + hashtable_ = New(kHashSize); +} + +template +AddressMap::~AddressMap() { + // De-allocate all of the objects we allocated + for (Object* obj = allocated_; obj != NULL; /**/) { + Object* next = obj->next; + (*dealloc_)(obj); + obj = next; + } +} + +template +inline const Value* AddressMap::Find(Key key) const { + return const_cast(this)->FindMutable(key); +} + +template +inline Value* AddressMap::FindMutable(Key key) { + const Number num = reinterpret_cast(key); + const Cluster* const c = FindCluster(num, false/*do not create*/); + if (c != NULL) { + for (Entry* e = c->blocks[BlockID(num)]; e != NULL; e = e->next) { + if (e->key == key) { + return &e->value; + } + } + } + return NULL; +} + +template +void AddressMap::Insert(Key key, Value value) { + const Number num = reinterpret_cast(key); + Cluster* const c = FindCluster(num, true/*create*/); + + // Look in linked-list for this block + const int block = BlockID(num); + for (Entry* e = c->blocks[block]; e != NULL; e = e->next) { + if (e->key == key) { + e->value = value; + return; + } + } + + // Create entry + if (free_ == NULL) { + // Allocate a new batch of entries and add to free-list + Entry* array = New(ALLOC_COUNT); + for (int i = 0; i < ALLOC_COUNT-1; i++) { + array[i].next = &array[i+1]; + } + array[ALLOC_COUNT-1].next = free_; + free_ = &array[0]; + } + Entry* e = free_; + free_ = e->next; + e->key = key; + e->value = value; + e->next = c->blocks[block]; + c->blocks[block] = e; +} + +template +bool AddressMap::FindAndRemove(Key key, Value* removed_value) { + const Number num = reinterpret_cast(key); + Cluster* const c = FindCluster(num, false/*do not create*/); + if (c != NULL) { + for (Entry** p = &c->blocks[BlockID(num)]; *p != NULL; p = &(*p)->next) { + Entry* e = *p; + if (e->key == key) { + *removed_value = e->value; + *p = e->next; // Remove e from linked-list + e->next = free_; // Add e to free-list + free_ = e; + return true; + } + } + } + return false; +} + +template +const Value* AddressMap::FindInside(ValueSizeFunc size_func, + size_t max_size, + Key key, + Key* res_key) { + const Number key_num = reinterpret_cast(key); + Number num = key_num; // we'll move this to move back through the clusters + while (1) { + const Cluster* c = FindCluster(num, false/*do not create*/); + if (c != NULL) { + while (1) { + const int block = BlockID(num); + bool had_smaller_key = false; + for (const Entry* e = c->blocks[block]; e != NULL; e = e->next) { + const Number e_num = reinterpret_cast(e->key); + if (e_num <= key_num) { + if (e_num == key_num || // to handle 0-sized ranges + key_num < e_num + (*size_func)(e->value)) { + *res_key = e->key; + return &e->value; + } + had_smaller_key = true; + } + } + if (had_smaller_key) return NULL; // got a range before 'key' + // and it did not contain 'key' + if (block == 0) break; + // try address-wise previous block + num |= kBlockSize - 1; // start at the last addr of prev block + num -= kBlockSize; + if (key_num - num > max_size) return NULL; + } + } + if (num < kClusterSize) return NULL; // first cluster + // go to address-wise previous cluster to try + num |= kClusterSize - 1; // start at the last block of previous cluster + num -= kClusterSize; + if (key_num - num > max_size) return NULL; + // Having max_size to limit the search is crucial: else + // we have to traverse a lot of empty clusters (or blocks). + // We can avoid needing max_size if we put clusters into + // a search tree, but performance suffers considerably + // if we use this approach by using stl::set. + } +} + +template +template +inline void AddressMap::Iterate(void (*callback)(Key, Value*, Type), + Type arg) const { + // We could optimize this by traversing only non-empty clusters and/or blocks + // but it does not speed up heap-checker noticeably. + for (int h = 0; h < kHashSize; ++h) { + for (const Cluster* c = hashtable_[h]; c != NULL; c = c->next) { + for (int b = 0; b < kClusterBlocks; ++b) { + for (Entry* e = c->blocks[b]; e != NULL; e = e->next) { + callback(e->key, &e->value, arg); + } + } + } + } +} + +#endif // BASE_ADDRESSMAP_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/arm_instruction_set_select.h b/trunk/3rdparty/gperftools-2-fit/src/base/arm_instruction_set_select.h new file mode 100644 index 000000000..77ff670f3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/arm_instruction_set_select.h @@ -0,0 +1,85 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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: Alexander Levitskiy +// +// Generalizes the plethora of ARM flavors available to an easier to manage set +// Defs reference is at https://wiki.edubuntu.org/ARM/Thumb2PortingHowto + +#ifndef ARM_INSTRUCTION_SET_SELECT_H_ +#define ARM_INSTRUCTION_SET_SELECT_H_ + +#if defined(__ARM_ARCH_8A__) +# define ARMV8 1 +#endif + +#if defined(ARMV8) || \ + defined(__ARM_ARCH_7__) || \ + defined(__ARM_ARCH_7R__) || \ + defined(__ARM_ARCH_7A__) +# define ARMV7 1 +#endif + +#if defined(ARMV7) || \ + defined(__ARM_ARCH_6__) || \ + defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__) || \ + defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6T2__) || \ + defined(__ARM_ARCH_6ZK__) +# define ARMV6 1 +#endif + +#if defined(ARMV6) || \ + defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5E__) || \ + defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) +# define ARMV5 1 +#endif + +#if defined(ARMV5) || \ + defined(__ARM_ARCH_4__) || \ + defined(__ARM_ARCH_4T__) +# define ARMV4 1 +#endif + +#if defined(ARMV4) || \ + defined(__ARM_ARCH_3__) || \ + defined(__ARM_ARCH_3M__) +# define ARMV3 1 +#endif + +#if defined(ARMV3) || \ + defined(__ARM_ARCH_2__) +# define ARMV2 1 +#endif + +#endif // ARM_INSTRUCTION_SET_SELECT_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-generic.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-generic.h new file mode 100644 index 000000000..cfa614370 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-generic.h @@ -0,0 +1,209 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2003, 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: Lei Zhang, Sasha Levitskiy +// +// This file is an internal atomic implementation, use base/atomicops.h instead. +// +// LinuxKernelCmpxchg is from Google Gears. + +#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_ +#define BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_ + +#include +#include +#include "base/basictypes.h" + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +typedef int64_t Atomic64; + +// 0xffff0fc0 is the hard coded address of a function provided by +// the kernel which implements an atomic compare-exchange. On older +// ARM architecture revisions (pre-v6) this may be implemented using +// a syscall. This address is stable, and in active use (hard coded) +// by at least glibc-2.7 and the Android C library. +// pLinuxKernelCmpxchg has both acquire and release barrier sematincs. +typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr); +LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg ATTRIBUTE_WEAK = + (LinuxKernelCmpxchgFunc) 0xffff0fc0; + +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier ATTRIBUTE_WEAK = + (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; + + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = *ptr; + do { + if (!pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + // pLinuxKernelCmpxchg already has acquire and release barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + // pLinuxKernelCmpxchg already has acquire and release barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + pLinuxKernelMemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + + +// 64-bit versions are not implemented yet. + +inline void NotImplementedFatalError(const char *function_name) { + fprintf(stderr, "64-bit %s() not implemented on this platform\n", + function_name); + abort(); +} + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + NotImplementedFatalError("NoBarrier_CompareAndSwap"); + return 0; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + NotImplementedFatalError("NoBarrier_AtomicExchange"); + return 0; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + // pLinuxKernelCmpxchg already has acquire and release barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + // pLinuxKernelCmpxchg already has acquire and release barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + NotImplementedFatalError("NoBarrier_Store"); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + NotImplementedFatalError("Release_Store"); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + NotImplementedFatalError("NoBarrier_Load"); + return 0; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + NotImplementedFatalError("Atomic64 Acquire_Load"); + return 0; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + NotImplementedFatalError("Atomic64 Acquire_CompareAndSwap"); + return 0; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + NotImplementedFatalError("Atomic64 Release_CompareAndSwap"); + return 0; +} + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-v6plus.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-v6plus.h new file mode 100644 index 000000000..af2920a5b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-arm-v6plus.h @@ -0,0 +1,310 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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: Sasha Levitskiy +// based on atomicops-internals by Sanjay Ghemawat +// +// This file is an internal atomic implementation, use base/atomicops.h instead. +// +// This code implements ARM atomics for architectures V6 and newer. + +#ifndef BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_ +#define BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_ + +#include +#include +#include "base/basictypes.h" // For COMPILE_ASSERT + +// The LDREXD and STREXD instructions in ARM all v7 variants or above. In v6, +// only some variants support it. For simplicity, we only use exclusive +// 64-bit load/store in V7 or above. +#if defined(ARMV7) +# define BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD +#endif + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +typedef int64_t Atomic64; + +// 32-bit low-level ops + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 oldval, res; + do { + __asm__ __volatile__( + "ldrex %1, [%3]\n" + "mov %0, #0\n" + "teq %1, %4\n" + // The following IT (if-then) instruction is needed for the subsequent + // conditional instruction STREXEQ when compiling in THUMB mode. + // In ARM mode, the compiler/assembler will not generate any code for it. + "it eq\n" + "strexeq %0, %5, [%3]\n" + : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr) + : "r" (ptr), "Ir" (old_value), "r" (new_value) + : "cc"); + } while (res); + return oldval; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 tmp, old; + __asm__ __volatile__( + "1:\n" + "ldrex %1, [%2]\n" + "strex %0, %3, [%2]\n" + "teq %0, #0\n" + "bne 1b" + : "=&r" (tmp), "=&r" (old) + : "r" (ptr), "r" (new_value) + : "cc", "memory"); + return old; +} + +inline void MemoryBarrier() { +#if !defined(ARMV7) + uint32_t dest = 0; + __asm__ __volatile__("mcr p15,0,%0,c7,c10,5" :"=&r"(dest) : : "memory"); +#else + __asm__ __volatile__("dmb" : : : "memory"); +#endif +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + MemoryBarrier(); + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +// 64-bit versions are only available if LDREXD and STREXD instructions +// are available. +#ifdef BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD + +#define BASE_HAS_ATOMIC64 1 + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 oldval, res; + do { + __asm__ __volatile__( + "ldrexd %1, [%3]\n" + "mov %0, #0\n" + "teq %Q1, %Q4\n" + // The following IT (if-then) instructions are needed for the subsequent + // conditional instructions when compiling in THUMB mode. + // In ARM mode, the compiler/assembler will not generate any code for it. + "it eq\n" + "teqeq %R1, %R4\n" + "it eq\n" + "strexdeq %0, %5, [%3]\n" + : "=&r" (res), "=&r" (oldval), "+Q" (*ptr) + : "r" (ptr), "Ir" (old_value), "r" (new_value) + : "cc"); + } while (res); + return oldval; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + int store_failed; + Atomic64 old; + __asm__ __volatile__( + "1:\n" + "ldrexd %1, [%2]\n" + "strexd %0, %3, [%2]\n" + "teq %0, #0\n" + "bne 1b" + : "=&r" (store_failed), "=&r" (old) + : "r" (ptr), "r" (new_value) + : "cc", "memory"); + return old; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + int store_failed; + Atomic64 dummy; + __asm__ __volatile__( + "1:\n" + // Dummy load to lock cache line. + "ldrexd %1, [%3]\n" + "strexd %0, %2, [%3]\n" + "teq %0, #0\n" + "bne 1b" + : "=&r" (store_failed), "=&r"(dummy) + : "r"(value), "r" (ptr) + : "cc", "memory"); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + Atomic64 res; + __asm__ __volatile__( + "ldrexd %0, [%1]\n" + "clrex\n" + : "=r" (res) + : "r"(ptr), "Q"(*ptr)); + return res; +} + +#else // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD + +inline void NotImplementedFatalError(const char *function_name) { + fprintf(stderr, "64-bit %s() not implemented on this platform\n", + function_name); + abort(); +} + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + NotImplementedFatalError("NoBarrier_CompareAndSwap"); + return 0; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + NotImplementedFatalError("NoBarrier_AtomicExchange"); + return 0; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + NotImplementedFatalError("Acquire_AtomicExchange"); + return 0; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + NotImplementedFatalError("Release_AtomicExchange"); + return 0; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + NotImplementedFatalError("NoBarrier_Store"); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + NotImplementedFatalError("NoBarrier_Load"); + return 0; +} + +#endif // BASE_ATOMICOPS_HAS_LDREXD_AND_STREXD + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + NoBarrier_Store(ptr, value); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = NoBarrier_Load(ptr); + MemoryBarrier(); + return value; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 value = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + MemoryBarrier(); + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +} // namespace subtle ends +} // namespace base ends + +#endif // BASE_ATOMICOPS_INTERNALS_ARM_V6PLUS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-gcc.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-gcc.h new file mode 100644 index 000000000..4f81ce32a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-gcc.h @@ -0,0 +1,183 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, Linaro +// 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: Riku Voipio, riku.voipio@linaro.org +// +// atomic primitives implemented with gcc atomic intrinsics: +// http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html +// + +#ifndef BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ +#define BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ + +#include +#include +#include "base/basictypes.h" + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +typedef int64_t Atomic64; + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELAXED); +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_ACQUIRE); +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELEASE); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); + return prev_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +// 64-bit versions + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELAXED); +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_ACQUIRE); +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(const_cast(ptr), new_value, __ATOMIC_RELEASE); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value = old_value; + __atomic_compare_exchange_n(ptr, &prev_value, new_value, + 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED); + return prev_value; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_GCC_GENERIC_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-linuxppc.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-linuxppc.h new file mode 100644 index 000000000..5c4d03c33 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-linuxppc.h @@ -0,0 +1,405 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2008, 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. + * + * --- + */ + +// Implementation of atomic operations for ppc-linux. This file should not +// be included directly. Clients should instead include +// "base/atomicops.h". + +#ifndef BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_ +#define BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_ + +typedef int32_t Atomic32; + +#ifdef __PPC64__ +#define BASE_HAS_ATOMIC64 1 +#endif + +namespace base { +namespace subtle { + +static inline void _sync(void) { + __asm__ __volatile__("sync": : : "memory"); +} + +static inline void _lwsync(void) { + // gcc defines __NO_LWSYNC__ when appropriate; see + // http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01238.html +#ifdef __NO_LWSYNC__ + __asm__ __volatile__("msync": : : "memory"); +#else + __asm__ __volatile__("lwsync": : : "memory"); +#endif +} + +static inline void _isync(void) { + __asm__ __volatile__("isync": : : "memory"); +} + +static inline Atomic32 OSAtomicAdd32(Atomic32 amount, Atomic32 *value) { + Atomic32 t; + __asm__ __volatile__( +"1: lwarx %0,0,%3\n\ + add %0,%2,%0\n\ + stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "+m" (*value) + : "r" (amount), "r" (value) + : "cc"); + return t; +} + +static inline Atomic32 OSAtomicAdd32Barrier(Atomic32 amount, Atomic32 *value) { + Atomic32 t; + _lwsync(); + t = OSAtomicAdd32(amount, value); + // This is based on the code snippet in the architecture manual (Vol + // 2, Appendix B). It's a little tricky: correctness depends on the + // fact that the code right before this (in OSAtomicAdd32) has a + // conditional branch with a data dependency on the update. + // Otherwise, we'd have to use sync. + _isync(); + return t; +} + +static inline bool OSAtomicCompareAndSwap32(Atomic32 old_value, + Atomic32 new_value, + Atomic32 *value) { + Atomic32 prev; + __asm__ __volatile__( +"1: lwarx %0,0,%2\n\ + cmpw 0,%0,%3\n\ + bne- 2f\n\ + stwcx. %4,0,%2\n\ + bne- 1b\n\ +2:" + : "=&r" (prev), "+m" (*value) + : "r" (value), "r" (old_value), "r" (new_value) + : "cc"); + return prev == old_value; +} + +static inline Atomic32 OSAtomicCompareAndSwap32Acquire(Atomic32 old_value, + Atomic32 new_value, + Atomic32 *value) { + Atomic32 t; + t = OSAtomicCompareAndSwap32(old_value, new_value, value); + // This is based on the code snippet in the architecture manual (Vol + // 2, Appendix B). It's a little tricky: correctness depends on the + // fact that the code right before this (in + // OSAtomicCompareAndSwap32) has a conditional branch with a data + // dependency on the update. Otherwise, we'd have to use sync. + _isync(); + return t; +} + +static inline Atomic32 OSAtomicCompareAndSwap32Release(Atomic32 old_value, + Atomic32 new_value, + Atomic32 *value) { + _lwsync(); + return OSAtomicCompareAndSwap32(old_value, new_value, value); +} + +typedef int64_t Atomic64; + +inline void MemoryBarrier() { + // This can't be _lwsync(); we need to order the immediately + // preceding stores against any load that may follow, but lwsync + // doesn't guarantee that. + _sync(); +} + +// 32-bit Versions. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32Acquire(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32Release(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Acquire(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Release(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +#ifdef __PPC64__ + +// 64-bit Versions. + +static inline Atomic64 OSAtomicAdd64(Atomic64 amount, Atomic64 *value) { + Atomic64 t; + __asm__ __volatile__( +"1: ldarx %0,0,%3\n\ + add %0,%2,%0\n\ + stdcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (t), "+m" (*value) + : "r" (amount), "r" (value) + : "cc"); + return t; +} + +static inline Atomic64 OSAtomicAdd64Barrier(Atomic64 amount, Atomic64 *value) { + Atomic64 t; + _lwsync(); + t = OSAtomicAdd64(amount, value); + // This is based on the code snippet in the architecture manual (Vol + // 2, Appendix B). It's a little tricky: correctness depends on the + // fact that the code right before this (in OSAtomicAdd64) has a + // conditional branch with a data dependency on the update. + // Otherwise, we'd have to use sync. + _isync(); + return t; +} + +static inline bool OSAtomicCompareAndSwap64(Atomic64 old_value, + Atomic64 new_value, + Atomic64 *value) { + Atomic64 prev; + __asm__ __volatile__( +"1: ldarx %0,0,%2\n\ + cmpd 0,%0,%3\n\ + bne- 2f\n\ + stdcx. %4,0,%2\n\ + bne- 1b\n\ +2:" + : "=&r" (prev), "+m" (*value) + : "r" (value), "r" (old_value), "r" (new_value) + : "cc"); + return prev == old_value; +} + +static inline Atomic64 OSAtomicCompareAndSwap64Acquire(Atomic64 old_value, + Atomic64 new_value, + Atomic64 *value) { + Atomic64 t; + t = OSAtomicCompareAndSwap64(old_value, new_value, value); + // This is based on the code snippet in the architecture manual (Vol + // 2, Appendix B). It's a little tricky: correctness depends on the + // fact that the code right before this (in + // OSAtomicCompareAndSwap64) has a conditional branch with a data + // dependency on the update. Otherwise, we'd have to use sync. + _isync(); + return t; +} + +static inline Atomic64 OSAtomicCompareAndSwap64Release(Atomic64 old_value, + Atomic64 new_value, + Atomic64 *value) { + _lwsync(); + return OSAtomicCompareAndSwap64(old_value, new_value, value); +} + + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64Acquire(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64Release(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Acquire(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Release(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +#endif + +inline void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { + _lwsync(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32 *ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { + Atomic32 value = *ptr; + _lwsync(); + return value; +} + +#ifdef __PPC64__ + +// 64-bit Versions. + +inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { + _lwsync(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64 *ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { + Atomic64 value = *ptr; + _lwsync(); + return value; +} + +#endif + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-macosx.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-macosx.h new file mode 100644 index 000000000..9a0c00a89 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-macosx.h @@ -0,0 +1,341 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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. + */ + +// Implementation of atomic operations for Mac OS X. This file should not +// be included directly. Clients should instead include +// "base/atomicops.h". + +#ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H_ +#define BASE_ATOMICOPS_INTERNALS_MACOSX_H_ + +typedef int32_t Atomic32; + +// MacOS uses long for intptr_t, AtomicWord and Atomic32 are always different +// on the Mac, even when they are the same size. Similarly, on __ppc64__, +// AtomicWord and Atomic64 are always different. Thus, we need explicit +// casting. +#ifdef __LP64__ +#define AtomicWordCastType base::subtle::Atomic64 +#else +#define AtomicWordCastType Atomic32 +#endif + +#if defined(__LP64__) || defined(__i386__) +#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic* +#endif + +#include + +namespace base { +namespace subtle { + +#if !defined(__LP64__) && defined(__ppc__) + +// The Mac 64-bit OSAtomic implementations are not available for 32-bit PowerPC, +// while the underlying assembly instructions are available only some +// implementations of PowerPC. + +// The following inline functions will fail with the error message at compile +// time ONLY IF they are called. So it is safe to use this header if user +// code only calls AtomicWord and Atomic32 operations. +// +// NOTE(vchen): Implementation notes to implement the atomic ops below may +// be found in "PowerPC Virtual Environment Architecture, Book II, +// Version 2.02", January 28, 2005, Appendix B, page 46. Unfortunately, +// extra care must be taken to ensure data are properly 8-byte aligned, and +// that data are returned correctly according to Mac OS X ABI specs. + +inline int64_t OSAtomicCompareAndSwap64( + int64_t oldValue, int64_t newValue, int64_t *theValue) { + __asm__ __volatile__( + "_OSAtomicCompareAndSwap64_not_supported_for_32_bit_ppc\n\t"); + return 0; +} + +inline int64_t OSAtomicAdd64(int64_t theAmount, int64_t *theValue) { + __asm__ __volatile__( + "_OSAtomicAdd64_not_supported_for_32_bit_ppc\n\t"); + return 0; +} + +inline int64_t OSAtomicCompareAndSwap64Barrier( + int64_t oldValue, int64_t newValue, int64_t *theValue) { + int64_t prev = OSAtomicCompareAndSwap64(oldValue, newValue, theValue); + OSMemoryBarrier(); + return prev; +} + +inline int64_t OSAtomicAdd64Barrier( + int64_t theAmount, int64_t *theValue) { + int64_t new_val = OSAtomicAdd64(theAmount, theValue); + OSMemoryBarrier(); + return new_val; +} +#endif + +typedef int64_t Atomic64; + +inline void MemoryBarrier() { + OSMemoryBarrier(); +} + +// 32-bit Versions. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32Barrier(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32 *ptr, + Atomic32 new_value) { + return Acquire_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, + Atomic32 old_value, + Atomic32 new_value) { + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +// 64-bit version + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64Barrier(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64 *ptr, + Atomic64 new_value) { + return Acquire_AtomicExchange(ptr, new_value); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Barrier(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr, + Atomic64 old_value, + Atomic64 new_value) { + // The lib kern interface does not distinguish between + // Acquire and Release memory barriers; they are equivalent. + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +#ifdef __LP64__ + +// 64-bit implementation on 64-bit platform + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +#else + +// 64-bit implementation on 32-bit platform + +#if defined(__ppc__) + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + __asm__ __volatile__( + "_NoBarrier_Store_not_supported_for_32_bit_ppc\n\t"); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + __asm__ __volatile__( + "_NoBarrier_Load_not_supported_for_32_bit_ppc\n\t"); + return 0; +} + +#elif defined(__i386__) + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic + "movq %%mm0, %0\n\t" // moves (ptr could be read-only) + "emms\n\t" // Reset FP registers + : "=m" (*ptr) + : "m" (value) + : // mark the FP stack and mmx registers as clobbered + "st", "st(1)", "st(2)", "st(3)", "st(4)", + "st(5)", "st(6)", "st(7)", "mm0", "mm1", + "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"); + +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + Atomic64 value; + __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic + "movq %%mm0, %0\n\t" // moves (ptr could be read-only) + "emms\n\t" // Reset FP registers + : "=m" (value) + : "m" (*ptr) + : // mark the FP stack and mmx registers as clobbered + "st", "st(1)", "st(2)", "st(3)", "st(4)", + "st(5)", "st(6)", "st(7)", "mm0", "mm1", + "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"); + + return value; +} +#endif + + +inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { + MemoryBarrier(); + NoBarrier_Store(ptr, value); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { + Atomic64 value = NoBarrier_Load(ptr); + MemoryBarrier(); + return value; +} + +#endif // __LP64__ + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-mips.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-mips.h new file mode 100644 index 000000000..58e0f1420 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-mips.h @@ -0,0 +1,299 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2013, 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: Jovan Zelincevic +// based on atomicops-internals by Sanjay Ghemawat + +// This file is an internal atomic implementation, use base/atomicops.h instead. +// +// This code implements MIPS atomics. + +#ifndef BASE_ATOMICOPS_INTERNALS_MIPS_H_ +#define BASE_ATOMICOPS_INTERNALS_MIPS_H_ + +#if (_MIPS_ISA == _MIPS_ISA_MIPS64) +#define BASE_HAS_ATOMIC64 1 +#endif + +typedef int32_t Atomic32; + +namespace base { +namespace subtle { + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + Atomic32 prev, tmp; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "ll %0, %5 \n" // prev = *ptr + "bne %0, %3, 2f \n" // if (prev != old_value) goto 2 + " move %2, %4 \n" // tmp = new_value + "sc %2, %1 \n" // *ptr = tmp (with atomic check) + "beqz %2, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + "2: \n" + + ".set pop \n" + : "=&r" (prev), "=m" (*ptr), + "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), + "m" (*ptr) + : "memory" + ); + return prev; +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + Atomic32 temp, old; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "ll %1, %2 \n" // old = *ptr + "move %0, %3 \n" // temp = new_value + "sc %0, %2 \n" // *ptr = temp (with atomic check) + "beqz %0, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + + ".set pop \n" + : "=&r" (temp), "=&r" (old), + "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory" + ); + return old; +} + +inline void MemoryBarrier() +{ + __asm__ volatile("sync" : : : "memory"); +} + +// "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return res; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) +{ + MemoryBarrier(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return res; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) +{ + *ptr = value; +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + Atomic32 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) +{ + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) +{ + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) +{ + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) +{ + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +#if (_MIPS_ISA == _MIPS_ISA_MIPS64) || (_MIPS_SIM == _MIPS_SIM_ABI64) + +typedef int64_t Atomic64; + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + Atomic64 prev, tmp; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "lld %0, %5 \n" // prev = *ptr + "bne %0, %3, 2f \n" // if (prev != old_value) goto 2 + " move %2, %4 \n" // tmp = new_value + "scd %2, %1 \n" // *ptr = tmp (with atomic check) + "beqz %2, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + "2: \n" + + ".set pop \n" + : "=&r" (prev), "=m" (*ptr), + "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), + "m" (*ptr) + : "memory" + ); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + Atomic64 temp, old; + __asm__ volatile( + ".set push \n" + ".set noreorder \n" + + "1: \n" + "lld %1, %2 \n" // old = *ptr + "move %0, %3 \n" // temp = new_value + "scd %0, %2 \n" // *ptr = temp (with atomic check) + "beqz %0, 1b \n" // start again on atomic error + " nop \n" // delay slot nop + + ".set pop \n" + : "=&r" (temp), "=&r" (old), + "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory" + ); + return old; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + Atomic64 old_value = NoBarrier_AtomicExchange(ptr, new_value); + MemoryBarrier(); + return old_value; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return res; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) +{ + MemoryBarrier(); + Atomic64 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return res; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) +{ + *ptr = value; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) +{ + MemoryBarrier(); + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) +{ + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) +{ + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) +{ + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +#endif + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_MIPS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-windows.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-windows.h new file mode 100644 index 000000000..f7c2907e8 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-windows.h @@ -0,0 +1,428 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +// Implementation of atomic operations using Windows API +// functions. This file should not be included directly. Clients +// should instead include "base/atomicops.h". + +#ifndef BASE_ATOMICOPS_INTERNALS_WINDOWS_H_ +#define BASE_ATOMICOPS_INTERNALS_WINDOWS_H_ + +#include +#include +#include "base/basictypes.h" // For COMPILE_ASSERT + +typedef int32 Atomic32; + +#if defined(_WIN64) +#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic* +#endif + +namespace base { +namespace subtle { + +typedef int64 Atomic64; + +// 32-bit low-level operations on any platform + +extern "C" { +// We use windows intrinsics when we can (they seem to be supported +// well on MSVC 8.0 and above). Unfortunately, in some +// environments, and have conflicting +// declarations of some other intrinsics, breaking compilation: +// http://connect.microsoft.com/VisualStudio/feedback/details/262047 +// Therefore, we simply declare the relevant intrinsics ourself. + +// MinGW has a bug in the header files where it doesn't indicate the +// first argument is volatile -- they're not up to date. See +// http://readlist.com/lists/lists.sourceforge.net/mingw-users/0/3861.html +// We have to const_cast away the volatile to avoid compiler warnings. +// TODO(csilvers): remove this once MinGW has updated MinGW/include/winbase.h +#if defined(__MINGW32__) +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { + return ::InterlockedCompareExchange(const_cast(ptr), newval, oldval); +} +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { + return ::InterlockedExchange(const_cast(ptr), newval); +} +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { + return ::InterlockedExchangeAdd(const_cast(ptr), increment); +} + +#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0 +// Unfortunately, in some environments, and +// have conflicting declarations of some intrinsics, breaking +// compilation. So we declare the intrinsics we need ourselves. See +// http://connect.microsoft.com/VisualStudio/feedback/details/262047 +LONG _InterlockedCompareExchange(volatile LONG* ptr, LONG newval, LONG oldval); +#pragma intrinsic(_InterlockedCompareExchange) +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { + return _InterlockedCompareExchange(ptr, newval, oldval); +} + +LONG _InterlockedExchange(volatile LONG* ptr, LONG newval); +#pragma intrinsic(_InterlockedExchange) +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { + return _InterlockedExchange(ptr, newval); +} + +LONG _InterlockedExchangeAdd(volatile LONG* ptr, LONG increment); +#pragma intrinsic(_InterlockedExchangeAdd) +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { + return _InterlockedExchangeAdd(ptr, increment); +} + +#else +inline LONG FastInterlockedCompareExchange(volatile LONG* ptr, + LONG newval, LONG oldval) { + return ::InterlockedCompareExchange(ptr, newval, oldval); +} +inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) { + return ::InterlockedExchange(ptr, newval); +} +inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) { + return ::InterlockedExchangeAdd(ptr, increment); +} + +#endif // ifdef __MINGW32__ +} // extern "C" + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + LONG result = FastInterlockedCompareExchange( + reinterpret_cast(ptr), + static_cast(new_value), + static_cast(old_value)); + return static_cast(result); +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + LONG result = FastInterlockedExchange( + reinterpret_cast(ptr), + static_cast(new_value)); + return static_cast(result); +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + // FastInterlockedExchange has both acquire and release memory barriers. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + // FastInterlockedExchange has both acquire and release memory barriers. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +} // namespace base::subtle +} // namespace base + + +// In msvc8/vs2005, winnt.h already contains a definition for +// MemoryBarrier in the global namespace. Add it there for earlier +// versions and forward to it from within the namespace. +#if !(defined(_MSC_VER) && _MSC_VER >= 1400) +inline void MemoryBarrier() { + Atomic32 value = 0; + base::subtle::NoBarrier_AtomicExchange(&value, 0); + // actually acts as a barrier in thisd implementation +} +#endif + +namespace base { +namespace subtle { + +inline void MemoryBarrier() { + ::MemoryBarrier(); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + // See comments in Atomic64 version of Release_Store() below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + return value; +} + +// 64-bit operations + +#if defined(_WIN64) || defined(__MINGW64__) + +// 64-bit low-level operations on 64-bit platform. + +COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); + +// These are the intrinsics needed for 64-bit operations. Similar to the +// 32-bit case above. + +extern "C" { +#if defined(__MINGW64__) +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { + return ::InterlockedCompareExchangePointer(const_cast(ptr), + newval, oldval); +} +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { + return ::InterlockedExchangePointer(const_cast(ptr), newval); +} +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { + return ::InterlockedExchangeAdd64(const_cast(ptr), increment); +} + +#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0 +// Like above, we need to declare the intrinsics ourselves. +PVOID _InterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval); +#pragma intrinsic(_InterlockedCompareExchangePointer) +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { + return _InterlockedCompareExchangePointer(const_cast(ptr), + newval, oldval); +} + +PVOID _InterlockedExchangePointer(volatile PVOID* ptr, PVOID newval); +#pragma intrinsic(_InterlockedExchangePointer) +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { + return _InterlockedExchangePointer(const_cast(ptr), newval); +} + +LONGLONG _InterlockedExchangeAdd64(volatile LONGLONG* ptr, LONGLONG increment); +#pragma intrinsic(_InterlockedExchangeAdd64) +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { + return _InterlockedExchangeAdd64(const_cast(ptr), increment); +} + +#else +inline PVOID FastInterlockedCompareExchangePointer(volatile PVOID* ptr, + PVOID newval, PVOID oldval) { + return ::InterlockedCompareExchangePointer(ptr, newval, oldval); +} +inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) { + return ::InterlockedExchangePointer(ptr, newval); +} +inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr, + LONGLONG increment) { + return ::InterlockedExchangeAdd64(ptr, increment); +} + +#endif // ifdef __MINGW64__ +} // extern "C" + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + PVOID result = FastInterlockedCompareExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value), reinterpret_cast(old_value)); + return reinterpret_cast(result); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + PVOID result = FastInterlockedExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value)); + return reinterpret_cast(result); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + return value; +} + +#else // defined(_WIN64) || defined(__MINGW64__) + +// 64-bit low-level operations on 32-bit platform + +// TODO(vchen): The GNU assembly below must be converted to MSVC inline +// assembly. Then the file should be renamed to ...-x86-msvc.h, probably. + +inline void NotImplementedFatalError(const char *function_name) { + fprintf(stderr, "64-bit %s() not implemented on this platform\n", + function_name); + abort(); +} + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { +#if 0 // Not implemented + Atomic64 prev; + __asm__ __volatile__("movl (%3), %%ebx\n\t" // Move 64-bit new_value into + "movl 4(%3), %%ecx\n\t" // ecx:ebx + "lock; cmpxchg8b %1\n\t" // If edx:eax (old_value) same + : "=A" (prev) // as contents of ptr: + : "m" (*ptr), // ecx:ebx => ptr + "0" (old_value), // else: + "r" (&new_value) // old *ptr => edx:eax + : "memory", "%ebx", "%ecx"); + return prev; +#else + NotImplementedFatalError("NoBarrier_CompareAndSwap"); + return 0; +#endif +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { +#if 0 // Not implemented + __asm__ __volatile__( + "movl (%2), %%ebx\n\t" // Move 64-bit new_value into + "movl 4(%2), %%ecx\n\t" // ecx:ebx + "0:\n\t" + "movl %1, %%eax\n\t" // Read contents of ptr into + "movl 4%1, %%edx\n\t" // edx:eax + "lock; cmpxchg8b %1\n\t" // Attempt cmpxchg; if *ptr + "jnz 0b\n\t" // is no longer edx:eax, loop + : "=A" (new_value) + : "m" (*ptr), + "r" (&new_value) + : "memory", "%ebx", "%ecx"); + return new_value; // Now it's the previous value. +#else + NotImplementedFatalError("NoBarrier_AtomicExchange"); + return 0; +#endif +} + +inline void NoBarrier_Store(volatile Atomic64* ptrValue, Atomic64 value) +{ + __asm { + movq mm0, value; // Use mmx reg for 64-bit atomic moves + mov eax, ptrValue; + movq [eax], mm0; + emms; // Empty mmx state to enable FP registers + } +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + NoBarrier_Store(ptr, value); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptrValue) +{ + Atomic64 value; + __asm { + mov eax, ptrValue; + movq mm0, [eax]; // Use mmx reg for 64-bit atomic moves + movq value, mm0; + emms; // Empty mmx state to enable FP registers + } + return value; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = NoBarrier_Load(ptr); + return value; +} + +#endif // defined(_WIN64) || defined(__MINGW64__) + + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + // FastInterlockedExchange has both acquire and release memory barriers. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + // FastInterlockedExchange has both acquire and release memory barriers. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_WINDOWS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.cc b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.cc new file mode 100644 index 000000000..20073c2d5 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.cc @@ -0,0 +1,112 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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. + * + * --- + * This module gets enough CPU information to optimize the + * atomicops module on x86. + */ + +#include "base/atomicops.h" +#include "base/basictypes.h" +#include "base/googleinit.h" +#include "base/logging.h" +#include + +// This file only makes sense with atomicops-internals-x86.h -- it +// depends on structs that are defined in that file. If atomicops.h +// doesn't sub-include that file, then we aren't needed, and shouldn't +// try to do anything. +#ifdef BASE_ATOMICOPS_INTERNALS_X86_H_ + +// Inline cpuid instruction. In PIC compilations, %ebx contains the address +// of the global offset table. To avoid breaking such executables, this code +// must preserve that register's value across cpuid instructions. +#if defined(__i386__) +#define cpuid(a, b, c, d, inp) \ + asm ("mov %%ebx, %%edi\n" \ + "cpuid\n" \ + "xchg %%edi, %%ebx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#elif defined (__x86_64__) +#define cpuid(a, b, c, d, inp) \ + asm ("mov %%rbx, %%rdi\n" \ + "cpuid\n" \ + "xchg %%rdi, %%rbx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#endif + +#if defined(cpuid) // initialize the struct only on x86 + +// Set the flags so that code will run correctly and conservatively +// until InitGoogle() is called. +struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { + false, // no SSE2 + false // no cmpxchg16b +}; + +// Initialize the AtomicOps_Internalx86CPUFeatures struct. +static void AtomicOps_Internalx86CPUFeaturesInit() { + uint32 eax; + uint32 ebx; + uint32 ecx; + uint32 edx; + + // Get vendor string (issue CPUID with eax = 0) + cpuid(eax, ebx, ecx, edx, 0); + char vendor[13]; + memcpy(vendor, &ebx, 4); + memcpy(vendor + 4, &edx, 4); + memcpy(vendor + 8, &ecx, 4); + vendor[12] = 0; + + // get feature flags in ecx/edx, and family/model in eax + cpuid(eax, ebx, ecx, edx, 1); + + int family = (eax >> 8) & 0xf; // family and model fields + int model = (eax >> 4) & 0xf; + if (family == 0xf) { // use extended family and model fields + family += (eax >> 20) & 0xff; + model += ((eax >> 16) & 0xf) << 4; + } + + // edx bit 26 is SSE2 which we use to tell use whether we can use mfence + AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); + + // ecx bit 13 indicates whether the cmpxchg16b instruction is supported + AtomicOps_Internalx86CPUFeatures.has_cmpxchg16b = ((ecx >> 13) & 1); +} + +REGISTER_MODULE_INITIALIZER(atomicops_x86, { + AtomicOps_Internalx86CPUFeaturesInit(); +}); + +#endif + +#endif /* ifdef BASE_ATOMICOPS_INTERNALS_X86_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.h new file mode 100644 index 000000000..94c7aac77 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops-internals-x86.h @@ -0,0 +1,353 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +// Implementation of atomic operations for x86. This file should not +// be included directly. Clients should instead include +// "base/atomicops.h". + +#ifndef BASE_ATOMICOPS_INTERNALS_X86_H_ +#define BASE_ATOMICOPS_INTERNALS_X86_H_ +#include "base/basictypes.h" + +typedef int32_t Atomic32; +#define BASE_HAS_ATOMIC64 1 // Use only in tests and base/atomic* + + +// NOTE(vchen): x86 does not need to define AtomicWordCastType, because it +// already matches Atomic32 or Atomic64, depending on the platform. + + +// This struct is not part of the public API of this module; clients may not +// use it. +// Features of this x86. Values may not be correct before main() is run, +// but are set conservatively. +struct AtomicOps_x86CPUFeatureStruct { + bool has_sse2; // Processor has SSE2. + bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction. +}; + +ATTRIBUTE_VISIBILITY_HIDDEN +extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures; + + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + + +namespace base { +namespace subtle { + +typedef int64_t Atomic64; + +// 32-bit low-level operations on any platform. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev; + __asm__ __volatile__("lock; cmpxchgl %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_val = NoBarrier_AtomicExchange(ptr, new_value); + return old_val; +} + +inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + // xchgl already has release memory barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return x; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +#if defined(__x86_64__) + +// 64-bit implementations of memory barrier can be simpler, because it +// "mfence" is guaranteed to exist. +inline void MemoryBarrier() { + __asm__ __volatile__("mfence" : : : "memory"); +} + +#else + +inline void MemoryBarrier() { + if (AtomicOps_Internalx86CPUFeatures.has_sse2) { + __asm__ __volatile__("mfence" : : : "memory"); + } else { // mfence is faster but not present on PIII + Atomic32 x = 0; + Acquire_AtomicExchange(&x, 0); + } +} + +#endif + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ATOMICOPS_COMPILER_BARRIER(); + *ptr = value; // An x86 store acts as a release barrier. + // See comments in Atomic64 version of Release_Store(), below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. + // See comments in Atomic64 version of Release_Store(), below. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +#if defined(__x86_64__) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + __asm__ __volatile__("lock; cmpxchgq %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 old_val = NoBarrier_AtomicExchange(ptr, new_value); + return old_val; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + // xchgq already has release memory barrier semantics. + return NoBarrier_AtomicExchange(ptr, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ATOMICOPS_COMPILER_BARRIER(); + + *ptr = value; // An x86 store acts as a release barrier + // for current AMD/Intel chips as of Jan 2008. + // See also Acquire_Load(), below. + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm + // + // x86 stores/loads fail to act as barriers for a few instructions (clflush + // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are + // not generated by the compiler, and are rare. Users of these instructions + // need to know about cache behaviour in any case since all of these involve + // either flushing cache lines or non-temporal cache hints. +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, + // for current AMD/Intel chips as of Jan 2008. + // See also Release_Store(), above. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +#else // defined(__x86_64__) + +// 64-bit low-level operations on 32-bit platform. + +#if !((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +// For compilers older than gcc 4.1, we use inline asm. +// +// Potential pitfalls: +// +// 1. %ebx points to Global offset table (GOT) with -fPIC. +// We need to preserve this register. +// 2. When explicit registers are used in inline asm, the +// compiler may not be aware of it and might try to reuse +// the same register for another argument which has constraints +// that allow it ("r" for example). + +inline Atomic64 __sync_val_compare_and_swap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + __asm__ __volatile__("push %%ebx\n\t" + "movl (%3), %%ebx\n\t" // Move 64-bit new_value into + "movl 4(%3), %%ecx\n\t" // ecx:ebx + "lock; cmpxchg8b (%1)\n\t"// If edx:eax (old_value) same + "pop %%ebx\n\t" + : "=A" (prev) // as contents of ptr: + : "D" (ptr), // ecx:ebx => ptr + "0" (old_value), // else: + "S" (&new_value) // old *ptr => edx:eax + : "memory", "%ecx"); + return prev; +} +#endif // Compiler < gcc-4.1 + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_val, + Atomic64 new_val) { + return __sync_val_compare_and_swap(ptr, old_val, new_val); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_val) { + Atomic64 old_val; + + do { + old_val = *ptr; + } while (__sync_val_compare_and_swap(ptr, old_val, new_val) != old_val); + + return old_val; +} + +inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_val) { + Atomic64 old_val = NoBarrier_AtomicExchange(ptr, new_val); + return old_val; +} + +inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_val) { + return NoBarrier_AtomicExchange(ptr, new_val); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic + "movq %%mm0, %0\n\t" // moves (ptr could be read-only) + "emms\n\t" // Empty mmx state/Reset FP regs + : "=m" (*ptr) + : "m" (value) + : // mark the FP stack and mmx registers as clobbered + "st", "st(1)", "st(2)", "st(3)", "st(4)", + "st(5)", "st(6)", "st(7)", "mm0", "mm1", + "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ATOMICOPS_COMPILER_BARRIER(); + NoBarrier_Store(ptr, value); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + Atomic64 value; + __asm__ __volatile__("movq %1, %%mm0\n\t" // Use mmx reg for 64-bit atomic + "movq %%mm0, %0\n\t" // moves (ptr could be read-only) + "emms\n\t" // Empty mmx state/Reset FP regs + : "=m" (value) + : "m" (*ptr) + : // mark the FP stack and mmx registers as clobbered + "st", "st(1)", "st(2)", "st(3)", "st(4)", + "st(5)", "st(6)", "st(7)", "mm0", "mm1", + "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"); + return value; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = NoBarrier_Load(ptr); + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +#endif // defined(__x86_64__) + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + return x; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +} // namespace base::subtle +} // namespace base + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // BASE_ATOMICOPS_INTERNALS_X86_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/atomicops.h b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops.h new file mode 100644 index 000000000..f1daf3bce --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/atomicops.h @@ -0,0 +1,363 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +// For atomic operations on statistics counters, see atomic_stats_counter.h. +// For atomic operations on sequence numbers, see atomic_sequence_num.h. +// For atomic operations on reference counts, see atomic_refcount.h. + +// Some fast atomic operations -- typically with machine-dependent +// implementations. This file may need editing as Google code is +// ported to different architectures. + +// The routines exported by this module are subtle. If you use them, even if +// you get the code right, it will depend on careful reasoning about atomicity +// and memory ordering; it will be less readable, and harder to maintain. If +// you plan to use these routines, you should have a good reason, such as solid +// evidence that performance would otherwise suffer, or there being no +// alternative. You should assume only properties explicitly guaranteed by the +// specifications in this file. You are almost certainly _not_ writing code +// just for the x86; if you assume x86 semantics, x86 hardware bugs and +// implementations on other archtectures will cause your code to break. If you +// do not know what you are doing, avoid these routines, and use a Mutex. +// +// These following lower-level operations are typically useful only to people +// implementing higher-level synchronization operations like spinlocks, +// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or +// a store with appropriate memory-ordering instructions. "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +// +// It is incorrect to make direct assignments to/from an atomic variable. +// You should use one of the Load or Store routines. The NoBarrier +// versions are provided when no barriers are needed: +// NoBarrier_Store() +// NoBarrier_Load() +// Although there are currently no compiler enforcement, you are encouraged +// to use these. Moreover, if you choose to use base::subtle::Atomic64 type, +// you MUST use one of the Load or Store routines to get correct behavior +// on 32-bit platforms. +// +// The intent is eventually to put all of these routines in namespace +// base::subtle + +#ifndef THREAD_ATOMICOPS_H_ +#define THREAD_ATOMICOPS_H_ + +#include +#ifdef HAVE_STDINT_H +#include +#endif + +// ------------------------------------------------------------------------ +// Include the platform specific implementations of the types +// and operations listed below. Implementations are to provide Atomic32 +// and Atomic64 operations. If there is a mismatch between intptr_t and +// the Atomic32 or Atomic64 types for a platform, the platform-specific header +// should define the macro, AtomicWordCastType in a clause similar to the +// following: +// #if ...pointers are 64 bits... +// # define AtomicWordCastType base::subtle::Atomic64 +// #else +// # define AtomicWordCastType Atomic32 +// #endif +// TODO(csilvers): figure out ARCH_PIII/ARCH_K8 (perhaps via ./configure?) +// ------------------------------------------------------------------------ + +#include "base/arm_instruction_set_select.h" +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#define CLANG_VERSION (__clang_major__ * 10000 \ + + __clang_minor__ * 100 \ + + __clang_patchlevel__) + +#if defined(TCMALLOC_PREFER_GCC_ATOMICS) && defined(__GNUC__) && GCC_VERSION >= 40700 +#include "base/atomicops-internals-gcc.h" +#elif defined(TCMALLOC_PREFER_GCC_ATOMICS) && defined(__clang__) && CLANG_VERSION >= 30400 +#include "base/atomicops-internals-gcc.h" +#elif defined(__MACH__) && defined(__APPLE__) +#include "base/atomicops-internals-macosx.h" +#elif defined(__GNUC__) && defined(ARMV6) +#include "base/atomicops-internals-arm-v6plus.h" +#elif defined(ARMV3) +#include "base/atomicops-internals-arm-generic.h" +#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__)) +#include "base/atomicops-internals-x86.h" +#elif defined(_WIN32) +#include "base/atomicops-internals-windows.h" +#elif defined(__linux__) && defined(__PPC__) +#include "base/atomicops-internals-linuxppc.h" +#elif defined(__GNUC__) && defined(__mips__) +#include "base/atomicops-internals-mips.h" +#elif defined(__GNUC__) && GCC_VERSION >= 40700 +#include "base/atomicops-internals-gcc.h" +#elif defined(__clang__) && CLANG_VERSION >= 30400 +#include "base/atomicops-internals-gcc.h" +#else +#error You need to implement atomic operations for this architecture +#endif + +// Signed type that can hold a pointer and supports the atomic ops below, as +// well as atomic loads and stores. Instances must be naturally-aligned. +typedef intptr_t AtomicWord; + +#ifdef AtomicWordCastType +// ------------------------------------------------------------------------ +// This section is needed only when explicit type casting is required to +// cast AtomicWord to one of the basic atomic types (Atomic64 or Atomic32). +// It also serves to document the AtomicWord interface. +// ------------------------------------------------------------------------ + +namespace base { +namespace subtle { + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast(ptr), + old_value, new_value); +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord Acquire_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return Acquire_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord Release_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return Release_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Acquire_CompareAndSwap( + reinterpret_cast(ptr), + old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Release_CompareAndSwap( + reinterpret_cast(ptr), + old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store( + reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Release_Store( + reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return base::subtle::Acquire_Load( + reinterpret_cast(ptr)); +} + +} // namespace base::subtle +} // namespace base +#endif // AtomicWordCastType + +// ------------------------------------------------------------------------ +// Commented out type definitions and method declarations for documentation +// of the interface provided by this module. +// ------------------------------------------------------------------------ + +#if 0 + +// Signed 32-bit type that supports the atomic ops below, as well as atomic +// loads and stores. Instances must be naturally aligned. This type differs +// from AtomicWord in 64-bit binaries where AtomicWord is 64-bits. +typedef int32_t Atomic32; + +// Corresponding operations on Atomic32 +namespace base { +namespace subtle { + +// Signed 64-bit type that supports the atomic ops below, as well as atomic +// loads and stores. Instances must be naturally aligned. This type differs +// from AtomicWord in 32-bit binaries where AtomicWord is 32-bits. +typedef int64_t Atomic64; + +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); +Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); +Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); +Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); +void Release_Store(volatile Atomic32* ptr, Atomic32 value); +Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); +Atomic32 Acquire_Load(volatile const Atomic32* ptr); + +// Corresponding operations on Atomic64 +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); +Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); +Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); + +Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); +void Release_Store(volatile Atomic64* ptr, Atomic64 value); +Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); +Atomic64 Acquire_Load(volatile const Atomic64* ptr); +} // namespace base::subtle +} // namespace base + +void MemoryBarrier(); + +#endif // 0 + + +// ------------------------------------------------------------------------ +// The following are to be deprecated when all uses have been changed to +// use the base::subtle namespace. +// ------------------------------------------------------------------------ + +#ifdef AtomicWordCastType +// AtomicWord versions to be deprecated +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Release_Store(ptr, value); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return base::subtle::Acquire_Load(ptr); +} +#endif // AtomicWordCastType + +// 32-bit Acquire/Release operations to be deprecated. + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value); +} +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value); +} +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + return base::subtle::Release_Store(ptr, value); +} +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + return base::subtle::Acquire_Load(ptr); +} + +#ifdef BASE_HAS_ATOMIC64 + +// 64-bit Acquire/Release operations to be deprecated. + +inline base::subtle::Atomic64 Acquire_CompareAndSwap( + volatile base::subtle::Atomic64* ptr, + base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) { + return base::subtle::Acquire_CompareAndSwap(ptr, old_value, new_value); +} +inline base::subtle::Atomic64 Release_CompareAndSwap( + volatile base::subtle::Atomic64* ptr, + base::subtle::Atomic64 old_value, base::subtle::Atomic64 new_value) { + return base::subtle::Release_CompareAndSwap(ptr, old_value, new_value); +} +inline void Release_Store( + volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) { + return base::subtle::Release_Store(ptr, value); +} +inline base::subtle::Atomic64 Acquire_Load( + volatile const base::subtle::Atomic64* ptr) { + return base::subtle::Acquire_Load(ptr); +} + +#endif // BASE_HAS_ATOMIC64 + +#endif // THREAD_ATOMICOPS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/basictypes.h b/trunk/3rdparty/gperftools-2-fit/src/base/basictypes.h new file mode 100644 index 000000000..ea87a6db0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/basictypes.h @@ -0,0 +1,440 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +#ifndef _BASICTYPES_H_ +#define _BASICTYPES_H_ + +#include +#include // for memcpy() +#ifdef HAVE_INTTYPES_H +#include // gets us PRId64, etc +#endif + +// To use this in an autoconf setting, make sure you run the following +// autoconf macros: +// AC_HEADER_STDC /* for stdint_h and inttypes_h */ +// AC_CHECK_TYPES([__int64]) /* defined in some windows platforms */ + +#ifdef HAVE_INTTYPES_H +#include // uint16_t might be here; PRId64 too. +#endif +#ifdef HAVE_STDINT_H +#include // to get uint16_t (ISO naming madness) +#endif +#include // our last best hope for uint16_t + +// Standard typedefs +// All Google code is compiled with -funsigned-char to make "char" +// unsigned. Google code therefore doesn't need a "uchar" type. +// TODO(csilvers): how do we make sure unsigned-char works on non-gcc systems? +typedef signed char schar; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +// NOTE: unsigned types are DANGEROUS in loops and other arithmetical +// places. Use the signed types unless your variable represents a bit +// pattern (eg a hash value) or you really need the extra bit. Do NOT +// use 'unsigned' to express "this value should always be positive"; +// use assertions for this. + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +const uint16 kuint16max = ( (uint16) 0xFFFF); +const uint32 kuint32max = ( (uint32) 0xFFFFFFFF); +const uint64 kuint64max = ( (((uint64) kuint32max) << 32) | kuint32max ); + +const int8 kint8max = ( ( int8) 0x7F); +const int16 kint16max = ( ( int16) 0x7FFF); +const int32 kint32max = ( ( int32) 0x7FFFFFFF); +const int64 kint64max = ( ((( int64) kint32max) << 32) | kuint32max ); + +const int8 kint8min = ( ( int8) 0x80); +const int16 kint16min = ( ( int16) 0x8000); +const int32 kint32min = ( ( int32) 0x80000000); +const int64 kint64min = ( (((uint64) kint32min) << 32) | 0 ); + +// Define the "portable" printf and scanf macros, if they're not +// already there (via the inttypes.h we #included above, hopefully). +// Mostly it's old systems that don't support inttypes.h, so we assume +// they're 32 bit. +#ifndef PRIx64 +#define PRIx64 "llx" +#endif +#ifndef SCNx64 +#define SCNx64 "llx" +#endif +#ifndef PRId64 +#define PRId64 "lld" +#endif +#ifndef SCNd64 +#define SCNd64 "lld" +#endif +#ifndef PRIu64 +#define PRIu64 "llu" +#endif +#ifndef PRIxPTR +#define PRIxPTR "lx" +#endif + +// Also allow for printing of a pthread_t. +#define GPRIuPTHREAD "lu" +#define GPRIxPTHREAD "lx" +#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__) || defined(__FreeBSD__) +#define PRINTABLE_PTHREAD(pthreadt) reinterpret_cast(pthreadt) +#else +#define PRINTABLE_PTHREAD(pthreadt) pthreadt +#endif + +#if defined(__GNUC__) +#define PREDICT_TRUE(x) __builtin_expect(!!(x), 1) +#define PREDICT_FALSE(x) __builtin_expect(!!(x), 0) +#else +#define PREDICT_TRUE(x) (x) +#define PREDICT_FALSE(x) (x) +#endif + +// A macro to disallow the evil copy constructor and operator= functions +// This should be used in the private: declarations for a class +#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// An alternate name that leaves out the moral judgment... :-) +#define DISALLOW_COPY_AND_ASSIGN(TypeName) DISALLOW_EVIL_CONSTRUCTORS(TypeName) + +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(sizeof(num_content_type_names) == sizeof(int), +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. +// +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +template +struct CompileAssert { +}; + +#ifdef HAVE___ATTRIBUTE__ +# define ATTRIBUTE_UNUSED __attribute__((unused)) +#else +# define ATTRIBUTE_UNUSED +#endif + +#if defined(HAVE___ATTRIBUTE__) && defined(HAVE_TLS) +#define ATTR_INITIAL_EXEC __attribute__ ((tls_model ("initial-exec"))) +#else +#define ATTR_INITIAL_EXEC +#endif + +#define COMPILE_ASSERT(expr, msg) \ + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ATTRIBUTE_UNUSED + +#define arraysize(a) (sizeof(a) / sizeof(*(a))) + +#define OFFSETOF_MEMBER(strct, field) \ + (reinterpret_cast(&reinterpret_cast(16)->field) - \ + reinterpret_cast(16)) + +// bit_cast implements the equivalent of +// "*reinterpret_cast(&source)". +// +// The reinterpret_cast method would produce undefined behavior +// according to ISO C++ specification section 3.10 -15 -. +// bit_cast<> calls memcpy() which is blessed by the standard, +// especially by the example in section 3.9. +// +// Fortunately memcpy() is very fast. In optimized mode, with a +// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline +// code with the minimal amount of data movement. On a 32-bit system, +// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) +// compiles to two loads and two stores. + +template +inline Dest bit_cast(const Source& source) { + COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), bitcasting_unequal_sizes); + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} + +// bit_store implements the equivalent of +// "dest = *reinterpret_cast(&source)". +// +// This prevents undefined behavior when the dest pointer is unaligned. +template +inline void bit_store(Dest *dest, const Source *source) { + COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), bitcasting_unequal_sizes); + memcpy(dest, source, sizeof(Dest)); +} + +#ifdef HAVE___ATTRIBUTE__ +# define ATTRIBUTE_WEAK __attribute__((weak)) +# define ATTRIBUTE_NOINLINE __attribute__((noinline)) +#else +# define ATTRIBUTE_WEAK +# define ATTRIBUTE_NOINLINE +#endif + +#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__) +# define ATTRIBUTE_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#else +# define ATTRIBUTE_VISIBILITY_HIDDEN +#endif + +// 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))) __attribute__((noinline)) + + // 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(__start_##name)) +# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(__stop_##name)) +# define HAVE_ATTRIBUTE_SECTION_START 1 + +#elif defined(HAVE___ATTRIBUTE__) && defined(__MACH__) +# define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__TEXT, " #name))) + +#include +#include +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); +#ifdef MH_MAGIC_64 + if (hdr->magic == MH_MAGIC_64) { + uint64_t len; + *pstart = getsectdatafromheader_64((mach_header_64*)hdr, + "__TEXT", 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; + } + } +#endif + if (hdr->magic == MH_MAGIC) { + uint32_t len; + *pstart = getsectdatafromheader(hdr, "__TEXT", 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("__TEXT", 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(__start_##name)) +# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(__stop_##name)) +# define HAVE_ATTRIBUTE_SECTION_START 1 + +#else // not HAVE___ATTRIBUTE__ && __ELF__, nor HAVE___ATTRIBUTE__ && __MACH__ +# define ATTRIBUTE_SECTION(name) +# 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(0)) +# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) + +#endif // HAVE___ATTRIBUTE__ and __ELF__ or __MACH__ + +#if defined(HAVE___ATTRIBUTE__) +# if (defined(__i386__) || defined(__x86_64__)) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) +# elif (defined(__PPC__) || defined(__PPC64__)) +# define CACHELINE_ALIGNED __attribute__((aligned(16))) +# elif (defined(__arm__)) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) + // some ARMs have shorter cache lines (ARM1176JZF-S is 32 bytes for example) but obviously 64-byte aligned implies 32-byte aligned +# elif (defined(__mips__)) +# define CACHELINE_ALIGNED __attribute__((aligned(128))) +# elif (defined(__aarch64__)) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) + // implementation specific, Cortex-A53 and 57 should have 64 bytes +# elif (defined(__s390__)) +# define CACHELINE_ALIGNED __attribute__((aligned(256))) +# elif (defined(__riscv) && __riscv_xlen == 64) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) +# elif (defined(__e2k__)) +# define CACHELINE_ALIGNED __attribute__((aligned(64))) +# else +# error Could not determine cache line length - unknown architecture +# endif +#else +# define CACHELINE_ALIGNED +#endif // defined(HAVE___ATTRIBUTE__) + +#if defined(HAVE___ATTRIBUTE__ALIGNED_FN) +# define CACHELINE_ALIGNED_FN CACHELINE_ALIGNED +#else +# define CACHELINE_ALIGNED_FN +#endif + +// Structure for discovering alignment +union MemoryAligner { + void* p; + double d; + size_t s; +} CACHELINE_ALIGNED; + +#if defined(HAVE___ATTRIBUTE__) && defined(__ELF__) +#define ATTRIBUTE_HIDDEN __attribute__((visibility("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +#if defined(__GNUC__) +#define ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define ATTRIBUTE_ALWAYS_INLINE __forceinline +#else +#define ATTRIBUTE_ALWAYS_INLINE +#endif + +// The following enum should be used only as a constructor argument to indicate +// that the variable has static storage class, and that the constructor should +// do nothing to its state. It indicates to the reader that it is legal to +// declare a static nistance of the class, provided the constructor is given +// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a +// static variable that has a constructor or a destructor because invocation +// order is undefined. However, IF the type can be initialized by filling with +// zeroes (which the loader does for static variables), AND the destructor also +// does nothing to the storage, then a constructor declared as +// explicit MyClass(base::LinkerInitialized x) {} +// and invoked as +// static MyClass my_variable_name(base::LINKER_INITIALIZED); +namespace base { +enum LinkerInitialized { LINKER_INITIALIZED }; +} + +#endif // _BASICTYPES_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/commandlineflags.h b/trunk/3rdparty/gperftools-2-fit/src/base/commandlineflags.h new file mode 100644 index 000000000..038a94a93 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/commandlineflags.h @@ -0,0 +1,175 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// This file is a compatibility layer that defines Google's version of +// command line flags that are used for configuration. +// +// We put flags into their own namespace. It is purposefully +// named in an opaque way that people should have trouble typing +// directly. The idea is that DEFINE puts the flag in the weird +// namespace, and DECLARE imports the flag from there into the +// current namespace. The net result is to force people to use +// DECLARE to get access to a flag, rather than saying +// extern bool FLAGS_logtostderr; +// or some such instead. We want this so we can put extra +// functionality (like sanity-checking) in DECLARE if we want, +// and make sure it is picked up everywhere. +// +// We also put the type of the variable in the namespace, so that +// people can't DECLARE_int32 something that they DEFINE_bool'd +// elsewhere. +#ifndef BASE_COMMANDLINEFLAGS_H_ +#define BASE_COMMANDLINEFLAGS_H_ + +#include +#include +#include // for memchr +#include // for getenv +#include "base/basictypes.h" + +#define DECLARE_VARIABLE(type, name) \ + namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \ + extern PERFTOOLS_DLL_DECL type FLAGS_##name; \ + } \ + using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name + +#define DEFINE_VARIABLE(type, name, value, meaning) \ + namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \ + PERFTOOLS_DLL_DECL type FLAGS_##name(value); \ + char FLAGS_no##name; \ + } \ + using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name + +// bool specialization +#define DECLARE_bool(name) \ + DECLARE_VARIABLE(bool, name) +#define DEFINE_bool(name, value, meaning) \ + DEFINE_VARIABLE(bool, name, value, meaning) + +// int32 specialization +#define DECLARE_int32(name) \ + DECLARE_VARIABLE(int32, name) +#define DEFINE_int32(name, value, meaning) \ + DEFINE_VARIABLE(int32, name, value, meaning) + +// int64 specialization +#define DECLARE_int64(name) \ + DECLARE_VARIABLE(int64, name) +#define DEFINE_int64(name, value, meaning) \ + DEFINE_VARIABLE(int64, name, value, meaning) + +#define DECLARE_uint64(name) \ + DECLARE_VARIABLE(uint64, name) +#define DEFINE_uint64(name, value, meaning) \ + DEFINE_VARIABLE(uint64, name, value, meaning) + +// double specialization +#define DECLARE_double(name) \ + DECLARE_VARIABLE(double, name) +#define DEFINE_double(name, value, meaning) \ + DEFINE_VARIABLE(double, name, value, meaning) + +// Special case for string, because we have to specify the namespace +// std::string, which doesn't play nicely with our FLAG__namespace hackery. +#define DECLARE_string(name) \ + namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \ + extern std::string FLAGS_##name; \ + } \ + using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name +#define DEFINE_string(name, value, meaning) \ + namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \ + std::string FLAGS_##name(value); \ + char FLAGS_no##name; \ + } \ + using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name + +// implemented in sysinfo.cc +namespace tcmalloc { + namespace commandlineflags { + + inline bool StringToBool(const char *value, bool def) { + if (!value) { + return def; + } + switch (value[0]) { + case 't': + case 'T': + case 'y': + case 'Y': + case '1': + case '\0': + return true; + } + return false; + } + + inline int StringToInt(const char *value, int def) { + if (!value) { + return def; + } + return strtol(value, NULL, 10); + } + + inline long long StringToLongLong(const char *value, long long def) { + if (!value) { + return def; + } + return strtoll(value, NULL, 10); + } + + inline double StringToDouble(const char *value, double def) { + if (!value) { + return def; + } + return strtod(value, NULL); + } + } +} + +// These macros (could be functions, but I don't want to bother with a .cc +// file), make it easier to initialize flags from the environment. + +#define EnvToString(envname, dflt) \ + (!getenv(envname) ? (dflt) : getenv(envname)) + +#define EnvToBool(envname, dflt) \ + tcmalloc::commandlineflags::StringToBool(getenv(envname), dflt) + +#define EnvToInt(envname, dflt) \ + tcmalloc::commandlineflags::StringToInt(getenv(envname), dflt) + +#define EnvToInt64(envname, dflt) \ + tcmalloc::commandlineflags::StringToLongLong(getenv(envname), dflt) + +#define EnvToDouble(envname, dflt) \ + tcmalloc::commandlineflags::StringToDouble(getenv(envname), dflt) + +#endif // BASE_COMMANDLINEFLAGS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.c b/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.c new file mode 100644 index 000000000..9b966a7cc --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.c @@ -0,0 +1,64 @@ +// -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2008-2009, 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: Kostya Serebryany + */ + +#ifdef __cplusplus +# error "This file should be built as pure C to avoid name mangling" +#endif + +#include "config.h" +#include +#include + +#include "base/dynamic_annotations.h" +#include "getenv_safe.h" // for TCMallocGetenvSafe + +static int GetRunningOnValgrind(void) { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) return 1; +#endif + const char *running_on_valgrind_str = TCMallocGetenvSafe("RUNNING_ON_VALGRIND"); + if (running_on_valgrind_str) { + return strcmp(running_on_valgrind_str, "0") != 0; + } + return 0; +} + +/* See the comments in dynamic_annotations.h */ +int RunningOnValgrind(void) { + static volatile int running_on_valgrind = -1; + int local_running_on_valgrind = running_on_valgrind; + if (local_running_on_valgrind == -1) + running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind(); + return local_running_on_valgrind; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.h b/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.h new file mode 100644 index 000000000..af9445271 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/dynamic_annotations.h @@ -0,0 +1,86 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2008, 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: Kostya Serebryany + */ + +/* This file defines dynamic annotations for use with dynamic analysis + tool such as valgrind, PIN, etc. + + Dynamic annotation is a source code annotation that affects + the generated code (that is, the annotation is not a comment). + Each such annotation is attached to a particular + instruction and/or to a particular object (address) in the program. + + The annotations that should be used by users are macros in all upper-case + (e.g., ANNOTATE_NEW_MEMORY). + + Actual implementation of these macros may differ depending on the + dynamic analysis tool being used. + + See http://code.google.com/p/data-race-test/ for more information. + + This file supports the following dynamic analysis tools: + - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero). + Macros are defined empty. + - ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1). + Macros are defined as calls to non-inlinable empty functions + that are intercepted by Valgrind. */ + +#ifndef BASE_DYNAMIC_ANNOTATIONS_H_ +#define BASE_DYNAMIC_ANNOTATIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return non-zero value if running under valgrind. + + If "valgrind.h" is included into dynamic_annotations.c, + the regular valgrind mechanism will be used. + See http://valgrind.org/docs/manual/manual-core-adv.html about + RUNNING_ON_VALGRIND and other valgrind "client requests". + The file "valgrind.h" may be obtained by doing + svn co svn://svn.valgrind.org/valgrind/trunk/include + + If for some reason you can't use "valgrind.h" or want to fake valgrind, + there are two ways to make this function return non-zero: + - Use environment variable: export RUNNING_ON_VALGRIND=1 + - Make your tool intercept the function RunningOnValgrind() and + change its return value. + */ +int RunningOnValgrind(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.cc b/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.cc new file mode 100644 index 000000000..d2ca1a5e1 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.cc @@ -0,0 +1,434 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Paul Pluzhnikov +// +// Allow dynamic symbol lookup in an in-memory Elf image. +// + +#include "base/elf_mem_image.h" + +#ifdef HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h + +#include // for size_t, ptrdiff_t +#include "base/logging.h" + +// From binutils/include/elf/common.h (this doesn't appear to be documented +// anywhere else). +// +// /* This flag appears in a Versym structure. It means that the symbol +// is hidden, and is only visible with an explicit version number. +// This is a GNU extension. */ +// #define VERSYM_HIDDEN 0x8000 +// +// /* This is the mask for the rest of the Versym information. */ +// #define VERSYM_VERSION 0x7fff + +#define VERSYM_VERSION 0x7fff + +namespace base { + +namespace { +template class ElfClass { + public: + static const int kElfClass = -1; + static int ElfBind(const ElfW(Sym) *) { + CHECK(false); // << "Unexpected word size"; + return 0; + } + static int ElfType(const ElfW(Sym) *) { + CHECK(false); // << "Unexpected word size"; + return 0; + } +}; + +template <> class ElfClass<32> { + public: + static const int kElfClass = ELFCLASS32; + static int ElfBind(const ElfW(Sym) *symbol) { + return ELF32_ST_BIND(symbol->st_info); + } + static int ElfType(const ElfW(Sym) *symbol) { + return ELF32_ST_TYPE(symbol->st_info); + } +}; + +template <> class ElfClass<64> { + public: + static const int kElfClass = ELFCLASS64; + static int ElfBind(const ElfW(Sym) *symbol) { + return ELF64_ST_BIND(symbol->st_info); + } + static int ElfType(const ElfW(Sym) *symbol) { + return ELF64_ST_TYPE(symbol->st_info); + } +}; + +typedef ElfClass<__WORDSIZE> CurrentElfClass; + +// Extract an element from one of the ELF tables, cast it to desired type. +// This is just a simple arithmetic and a glorified cast. +// Callers are responsible for bounds checking. +template +const T* GetTableElement(const ElfW(Ehdr) *ehdr, + ElfW(Off) table_offset, + ElfW(Word) element_size, + size_t index) { + return reinterpret_cast(reinterpret_cast(ehdr) + + table_offset + + index * element_size); +} +} // namespace + +const void *const ElfMemImage::kInvalidBase = + reinterpret_cast(~0L); + +ElfMemImage::ElfMemImage(const void *base) { + CHECK(base != kInvalidBase); + Init(base); +} + +int ElfMemImage::GetNumSymbols() const { + if (!hash_) { + return 0; + } + // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash + return hash_[1]; +} + +const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { + CHECK_LT(index, GetNumSymbols()); + return dynsym_ + index; +} + +const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { + CHECK_LT(index, GetNumSymbols()); + return versym_ + index; +} + +const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const { + CHECK_LT(index, ehdr_->e_phnum); + return GetTableElement(ehdr_, + ehdr_->e_phoff, + ehdr_->e_phentsize, + index); +} + +const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const { + CHECK_LT(offset, strsize_); + return dynstr_ + offset; +} + +const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { + if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { + // Symbol corresponds to "special" (e.g. SHN_ABS) section. + return reinterpret_cast(sym->st_value); + } + CHECK_LT(link_base_, sym->st_value); + return GetTableElement(ehdr_, 0, 1, sym->st_value) - link_base_; +} + +const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const { + CHECK_LE(index, verdefnum_); + const ElfW(Verdef) *version_definition = verdef_; + while (version_definition->vd_ndx < index && version_definition->vd_next) { + const char *const version_definition_as_char = + reinterpret_cast(version_definition); + version_definition = + reinterpret_cast(version_definition_as_char + + version_definition->vd_next); + } + return version_definition->vd_ndx == index ? version_definition : NULL; +} + +const ElfW(Verdaux) *ElfMemImage::GetVerdefAux( + const ElfW(Verdef) *verdef) const { + return reinterpret_cast(verdef+1); +} + +const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const { + CHECK_LT(offset, strsize_); + return dynstr_ + offset; +} + +void ElfMemImage::Init(const void *base) { + ehdr_ = NULL; + dynsym_ = NULL; + dynstr_ = NULL; + versym_ = NULL; + verdef_ = NULL; + hash_ = NULL; + strsize_ = 0; + verdefnum_ = 0; + link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. + if (!base) { + return; + } + const intptr_t base_as_uintptr_t = reinterpret_cast(base); + // Fake VDSO has low bit set. + const bool fake_vdso = ((base_as_uintptr_t & 1) != 0); + base = reinterpret_cast(base_as_uintptr_t & ~1); + const char *const base_as_char = reinterpret_cast(base); + if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || + base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { + RAW_DCHECK(false, "no ELF magic"); // at %p", base); + return; + } + int elf_class = base_as_char[EI_CLASS]; + if (elf_class != CurrentElfClass::kElfClass) { + DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); + return; + } + switch (base_as_char[EI_DATA]) { + case ELFDATA2LSB: { + if (__LITTLE_ENDIAN != __BYTE_ORDER) { + DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; + return; + } + break; + } + case ELFDATA2MSB: { + if (__BIG_ENDIAN != __BYTE_ORDER) { + DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; + return; + } + break; + } + default: { + RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA]; + return; + } + } + + ehdr_ = reinterpret_cast(base); + const ElfW(Phdr) *dynamic_program_header = NULL; + for (int i = 0; i < ehdr_->e_phnum; ++i) { + const ElfW(Phdr) *const program_header = GetPhdr(i); + switch (program_header->p_type) { + case PT_LOAD: + if (link_base_ == ~0L) { + link_base_ = program_header->p_vaddr; + } + break; + case PT_DYNAMIC: + dynamic_program_header = program_header; + break; + } + } + if (link_base_ == ~0L || !dynamic_program_header) { + RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO"); + RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); + // Mark this image as not present. Can not recur infinitely. + Init(0); + return; + } + ptrdiff_t relocation = + base_as_char - reinterpret_cast(link_base_); + ElfW(Dyn) *dynamic_entry = + reinterpret_cast(dynamic_program_header->p_vaddr + + relocation); + for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { + ElfW(Xword) value = dynamic_entry->d_un.d_val; + if (fake_vdso) { + // A complication: in the real VDSO, dynamic entries are not relocated + // (it wasn't loaded by a dynamic loader). But when testing with a + // "fake" dlopen()ed vdso library, the loader relocates some (but + // not all!) of them before we get here. + if (dynamic_entry->d_tag == DT_VERDEF) { + // The only dynamic entry (of the ones we care about) libc-2.3.6 + // loader doesn't relocate. + value += relocation; + } + } else { + // Real VDSO. Everything needs to be relocated. + value += relocation; + } + switch (dynamic_entry->d_tag) { + case DT_HASH: + hash_ = reinterpret_cast(value); + break; + case DT_SYMTAB: + dynsym_ = reinterpret_cast(value); + break; + case DT_STRTAB: + dynstr_ = reinterpret_cast(value); + break; + case DT_VERSYM: + versym_ = reinterpret_cast(value); + break; + case DT_VERDEF: + verdef_ = reinterpret_cast(value); + break; + case DT_VERDEFNUM: + verdefnum_ = dynamic_entry->d_un.d_val; + break; + case DT_STRSZ: + strsize_ = dynamic_entry->d_un.d_val; + break; + default: + // Unrecognized entries explicitly ignored. + break; + } + } + if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || + !verdef_ || !verdefnum_ || !strsize_) { + RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)"); + RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)"); + RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)"); + RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)"); + RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)"); + RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)"); + RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)"); + // Mark this image as not present. Can not recur infinitely. + Init(0); + return; + } +} + +bool ElfMemImage::LookupSymbol(const char *name, + const char *version, + int type, + SymbolInfo *info) const { + for (SymbolIterator it = begin(); it != end(); ++it) { + if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 && + CurrentElfClass::ElfType(it->symbol) == type) { + if (info) { + *info = *it; + } + return true; + } + } + return false; +} + +bool ElfMemImage::LookupSymbolByAddress(const void *address, + SymbolInfo *info_out) const { + for (SymbolIterator it = begin(); it != end(); ++it) { + const char *const symbol_start = + reinterpret_cast(it->address); + const char *const symbol_end = symbol_start + it->symbol->st_size; + if (symbol_start <= address && address < symbol_end) { + if (info_out) { + // Client wants to know details for that symbol (the usual case). + if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) { + // Strong symbol; just return it. + *info_out = *it; + return true; + } else { + // Weak or local. Record it, but keep looking for a strong one. + *info_out = *it; + } + } else { + // Client only cares if there is an overlapping symbol. + return true; + } + } + } + return false; +} + +ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) + : index_(index), image_(image) { +} + +const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { + return &info_; +} + +const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const { + return info_; +} + +bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const { + return this->image_ == rhs.image_ && this->index_ == rhs.index_; +} + +bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const { + return !(*this == rhs); +} + +ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() { + this->Update(1); + return *this; +} + +ElfMemImage::SymbolIterator ElfMemImage::begin() const { + SymbolIterator it(this, 0); + it.Update(0); + return it; +} + +ElfMemImage::SymbolIterator ElfMemImage::end() const { + return SymbolIterator(this, GetNumSymbols()); +} + +void ElfMemImage::SymbolIterator::Update(int increment) { + const ElfMemImage *image = reinterpret_cast(image_); + CHECK(image->IsPresent() || increment == 0); + if (!image->IsPresent()) { + return; + } + index_ += increment; + if (index_ >= image->GetNumSymbols()) { + index_ = image->GetNumSymbols(); + return; + } + const ElfW(Sym) *symbol = image->GetDynsym(index_); + const ElfW(Versym) *version_symbol = image->GetVersym(index_); + CHECK(symbol && version_symbol); + const char *const symbol_name = image->GetDynstr(symbol->st_name); + const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION; + const ElfW(Verdef) *version_definition = NULL; + const char *version_name = ""; + if (symbol->st_shndx == SHN_UNDEF) { + // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and + // version_index could well be greater than verdefnum_, so calling + // GetVerdef(version_index) may trigger assertion. + } else { + version_definition = image->GetVerdef(version_index); + } + if (version_definition) { + // I am expecting 1 or 2 auxiliary entries: 1 for the version itself, + // optional 2nd if the version has a parent. + CHECK_LE(1, version_definition->vd_cnt); + CHECK_LE(version_definition->vd_cnt, 2); + const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition); + version_name = image->GetVerstr(version_aux->vda_name); + } + info_.name = symbol_name; + info_.version = version_name; + info_.address = image->GetSymAddr(symbol); + info_.symbol = symbol; +} + +} // namespace base + +#endif // HAVE_ELF_MEM_IMAGE diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.h b/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.h new file mode 100644 index 000000000..5fb00fffb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/elf_mem_image.h @@ -0,0 +1,135 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Paul Pluzhnikov +// +// Allow dynamic symbol lookup for in-memory Elf images. + +#ifndef BASE_ELF_MEM_IMAGE_H_ +#define BASE_ELF_MEM_IMAGE_H_ + +#include +#ifdef HAVE_FEATURES_H +#include // for __GLIBC__ +#endif + +// Maybe one day we can rewrite this file not to require the elf +// symbol extensions in glibc, but for right now we need them. +#if defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) + +#define HAVE_ELF_MEM_IMAGE 1 + +#include +#include // for ElfW + +namespace base { + +// An in-memory ELF image (may not exist on disk). +class ElfMemImage { + public: + // Sentinel: there could never be an elf image at this address. + static const void *const kInvalidBase; + + // Information about a single vdso symbol. + // All pointers are into .dynsym, .dynstr, or .text of the VDSO. + // Do not free() them or modify through them. + struct SymbolInfo { + const char *name; // E.g. "__vdso_getcpu" + const char *version; // E.g. "LINUX_2.6", could be "" + // for unversioned symbol. + const void *address; // Relocated symbol address. + const ElfW(Sym) *symbol; // Symbol in the dynamic symbol table. + }; + + // Supports iteration over all dynamic symbols. + class SymbolIterator { + public: + friend class ElfMemImage; + const SymbolInfo *operator->() const; + const SymbolInfo &operator*() const; + SymbolIterator& operator++(); + bool operator!=(const SymbolIterator &rhs) const; + bool operator==(const SymbolIterator &rhs) const; + private: + SymbolIterator(const void *const image, int index); + void Update(int incr); + SymbolInfo info_; + int index_; + const void *const image_; + }; + + + explicit ElfMemImage(const void *base); + void Init(const void *base); + bool IsPresent() const { return ehdr_ != NULL; } + const ElfW(Phdr)* GetPhdr(int index) const; + const ElfW(Sym)* GetDynsym(int index) const; + const ElfW(Versym)* GetVersym(int index) const; + const ElfW(Verdef)* GetVerdef(int index) const; + const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const; + const char* GetDynstr(ElfW(Word) offset) const; + const void* GetSymAddr(const ElfW(Sym) *sym) const; + const char* GetVerstr(ElfW(Word) offset) const; + int GetNumSymbols() const; + + SymbolIterator begin() const; + SymbolIterator end() const; + + // Look up versioned dynamic symbol in the image. + // Returns false if image is not present, or doesn't contain given + // symbol/version/type combination. + // If info_out != NULL, additional details are filled in. + bool LookupSymbol(const char *name, const char *version, + int symbol_type, SymbolInfo *info_out) const; + + // Find info about symbol (if any) which overlaps given address. + // Returns true if symbol was found; false if image isn't present + // or doesn't have a symbol overlapping given address. + // If info_out != NULL, additional details are filled in. + bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; + + private: + const ElfW(Ehdr) *ehdr_; + const ElfW(Sym) *dynsym_; + const ElfW(Versym) *versym_; + const ElfW(Verdef) *verdef_; + const ElfW(Word) *hash_; + const char *dynstr_; + size_t strsize_; + size_t verdefnum_; + ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD). +}; + +} // namespace base + +#endif // __ELF__ and __GLIBC__ and !__native_client__ + +#endif // BASE_ELF_MEM_IMAGE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/elfcore.h b/trunk/3rdparty/gperftools-2-fit/src/base/elfcore.h new file mode 100644 index 000000000..11c09b4ff --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/elfcore.h @@ -0,0 +1,135 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2005-2008, 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: Markus Gutschke, Carl Crous + */ + +#ifndef _ELFCORE_H +#define _ELFCORE_H +#ifdef __cplusplus +extern "C" { +#endif + +/* We currently only support x86-32, x86-64, ARM, MIPS, PPC on Linux. + * Porting to other related platforms should not be difficult. + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__mips__) || defined(__PPC__)) && defined(__linux) + +#include "config.h" + +#include +#include +#include + + +/* Define the DUMPER symbol to make sure that there is exactly one + * core dumper built into the library. + */ +#define DUMPER "ELF" + +/* By the time that we get a chance to read CPU registers in the + * calling thread, they are already in a not particularly useful + * state. Besides, there will be multiple frames on the stack that are + * just making the core file confusing. To fix this problem, we take a + * snapshot of the frame pointer, stack pointer, and instruction + * pointer at an earlier time, and then insert these values into the + * core file. + */ + +#if defined(__i386__) || defined(__x86_64__) + typedef struct i386_regs { /* Normal (non-FPU) CPU registers */ + #ifdef __x86_64__ + #define BP rbp + #define SP rsp + #define IP rip + uint64_t r15,r14,r13,r12,rbp,rbx,r11,r10; + uint64_t r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax; + uint64_t rip,cs,eflags; + uint64_t rsp,ss; + uint64_t fs_base, gs_base; + uint64_t ds,es,fs,gs; + #else + #define BP ebp + #define SP esp + #define IP eip + uint32_t ebx, ecx, edx, esi, edi, ebp, eax; + uint16_t ds, __ds, es, __es; + uint16_t fs, __fs, gs, __gs; + uint32_t orig_eax, eip; + uint16_t cs, __cs; + uint32_t eflags, esp; + uint16_t ss, __ss; + #endif + } i386_regs; +#elif defined(__arm__) + typedef struct arm_regs { /* General purpose registers */ + #define BP uregs[11] /* Frame pointer */ + #define SP uregs[13] /* Stack pointer */ + #define IP uregs[15] /* Program counter */ + #define LR uregs[14] /* Link register */ + long uregs[18]; + } arm_regs; +#elif defined(__mips__) + typedef struct mips_regs { + unsigned long pad[6]; /* Unused padding to match kernel structures */ + unsigned long uregs[32]; /* General purpose registers. */ + unsigned long hi; /* Used for multiplication and division. */ + unsigned long lo; + unsigned long cp0_epc; /* Program counter. */ + unsigned long cp0_badvaddr; + unsigned long cp0_status; + unsigned long cp0_cause; + unsigned long unused; + } mips_regs; +#elif defined (__PPC__) + typedef struct ppc_regs { + #define SP uregs[1] /* Stack pointer */ + #define IP rip /* Program counter */ + #define LR lr /* Link register */ + unsigned long uregs[32]; /* General Purpose Registers - r0-r31. */ + double fpr[32]; /* Floating-Point Registers - f0-f31. */ + unsigned long rip; /* Program counter. */ + unsigned long msr; + unsigned long ccr; + unsigned long lr; + unsigned long ctr; + unsigned long xeq; + unsigned long mq; + } ppc_regs; +#endif + +#endif // __linux and various arches + +#ifdef __cplusplus +} +#endif +#endif /* _ELFCORE_H */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/googleinit.h b/trunk/3rdparty/gperftools-2-fit/src/base/googleinit.h new file mode 100644 index 000000000..a29042772 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/googleinit.h @@ -0,0 +1,74 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Jacob Hoffman-Andrews + +#ifndef _GOOGLEINIT_H +#define _GOOGLEINIT_H + +#include "base/logging.h" + +class GoogleInitializer { + public: + typedef void (*VoidFunction)(void); + GoogleInitializer(const char* name, VoidFunction ctor, VoidFunction dtor) + : name_(name), destructor_(dtor) { + RAW_VLOG(10, " constructing: %s\n", name_); + if (ctor) + ctor(); + } + ~GoogleInitializer() { + RAW_VLOG(10, " destroying: %s\n", name_); + if (destructor_) + destructor_(); + } + + private: + const char* const name_; + const VoidFunction destructor_; +}; + +#define REGISTER_MODULE_INITIALIZER(name, body) \ + namespace { \ + static void google_init_module_##name () { body; } \ + GoogleInitializer google_initializer_module_##name(#name, \ + google_init_module_##name, NULL); \ + } + +#define REGISTER_MODULE_DESTRUCTOR(name, body) \ + namespace { \ + static void google_destruct_module_##name () { body; } \ + GoogleInitializer google_destructor_module_##name(#name, \ + NULL, google_destruct_module_##name); \ + } + + +#endif /* _GOOGLEINIT_H */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/linux_syscall_support.h b/trunk/3rdparty/gperftools-2-fit/src/base/linux_syscall_support.h new file mode 100644 index 000000000..d6899b892 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/linux_syscall_support.h @@ -0,0 +1,3017 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2005-2008, 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: Markus Gutschke + */ + +/* This file includes Linux-specific support functions common to the + * coredumper and the thread lister; primarily, this is a collection + * of direct system calls, and a couple of symbols missing from + * standard header files. + * There are a few options that the including file can set to control + * the behavior of this file: + * + * SYS_CPLUSPLUS: + * The entire header file will normally be wrapped in 'extern "C" { }", + * making it suitable for compilation as both C and C++ source. If you + * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit + * the wrapping. N.B. doing so will suppress inclusion of all prerequisite + * system header files, too. It is the caller's responsibility to provide + * the necessary definitions. + * + * SYS_ERRNO: + * All system calls will update "errno" unless overriden by setting the + * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be + * an l-value. + * + * SYS_INLINE: + * New symbols will be defined "static inline", unless overridden by + * the SYS_INLINE macro. + * + * SYS_LINUX_SYSCALL_SUPPORT_H + * This macro is used to avoid multiple inclusions of this header file. + * If you need to include this file more than once, make sure to + * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion. + * + * SYS_PREFIX: + * New system calls will have a prefix of "sys_" unless overridden by + * the SYS_PREFIX macro. Valid values for this macro are [0..9] which + * results in prefixes "sys[0..9]_". It is also possible to set this + * macro to -1, which avoids all prefixes. + * + * This file defines a few internal symbols that all start with "LSS_". + * Do not access these symbols from outside this file. They are not part + * of the supported API. + * + * NOTE: This is a stripped down version of the official opensource + * version of linux_syscall_support.h, which lives at + * http://code.google.com/p/linux-syscall-support/ + * It includes only the syscalls that are used in perftools, plus a + * few extra. Here's the breakdown: + * 1) Perftools uses these: grep -rho 'sys_[a-z0-9_A-Z]* *(' src | sort -u + * sys__exit( + * sys_clone( + * sys_close( + * sys_fcntl( + * sys_fstat( + * sys_futex( + * sys_getcpu( + * sys_getdents64( + * sys_getppid( + * sys_gettid( + * sys_lseek( + * sys_mmap( + * sys_mremap( + * sys_munmap( + * sys_open( + * sys_pipe( + * sys_prctl( + * sys_ptrace( + * sys_ptrace_detach( + * sys_read( + * sys_sched_yield( + * sys_sigaction( + * sys_sigaltstack( + * sys_sigdelset( + * sys_sigfillset( + * sys_sigprocmask( + * sys_socket( + * sys_stat( + * sys_waitpid( + * 2) These are used as subroutines of the above: + * sys_getpid -- gettid + * sys_kill -- ptrace_detach + * sys_restore -- sigaction + * sys_restore_rt -- sigaction + * sys_socketcall -- socket + * sys_wait4 -- waitpid + * 3) I left these in even though they're not used. They either + * complement the above (write vs read) or are variants (rt_sigaction): + * sys_fstat64 + * sys_llseek + * sys_mmap2 + * sys_openat + * sys_getdents + * sys_rt_sigaction + * sys_rt_sigprocmask + * sys_sigaddset + * sys_sigemptyset + * sys_stat64 + * sys_write + */ +#ifndef SYS_LINUX_SYSCALL_SUPPORT_H +#define SYS_LINUX_SYSCALL_SUPPORT_H + +/* We currently only support x86-32, x86-64, ARM, MIPS, PPC/PPC64, Aarch64, + * s390, s390x, and riscv64 on Linux. + * Porting to other related platforms should not be difficult. + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__mips__) || defined(__mips64) || defined(__mips64el__) || defined(__PPC__) || \ + defined(__aarch64__) || defined(__s390__) || defined(__riscv)) \ + && (defined(__linux)) + +#ifndef SYS_CPLUSPLUS +#ifdef __cplusplus +/* Some system header files in older versions of gcc neglect to properly + * handle being included from C++. As it appears to be harmless to have + * multiple nested 'extern "C"' blocks, just add another one here. + */ +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __mips__ +/* Include definitions of the ABI currently in use. */ +#include +#endif + +#endif + +/* As glibc often provides subtly incompatible data structures (and implicit + * wrapper functions that convert them), we provide our own kernel data + * structures for use by the system calls. + * These structures have been developed by using Linux 2.6.23 headers for + * reference. Note though, we do not care about exact API compatibility + * with the kernel, and in fact the kernel often does not have a single + * API that works across architectures. Instead, we try to mimic the glibc + * API where reasonable, and only guarantee ABI compatibility with the + * kernel headers. + * Most notably, here are a few changes that were made to the structures + * defined by kernel headers: + * + * - we only define structures, but not symbolic names for kernel data + * types. For the latter, we directly use the native C datatype + * (i.e. "unsigned" instead of "mode_t"). + * - in a few cases, it is possible to define identical structures for + * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by + * standardizing on the 64bit version of the data types. In particular, + * this means that we use "unsigned" where the 32bit headers say + * "unsigned long". + * - overall, we try to minimize the number of cases where we need to + * conditionally define different structures. + * - the "struct kernel_sigaction" class of structures have been + * modified to more closely mimic glibc's API by introducing an + * anonymous union for the function pointer. + * - a small number of field names had to have an underscore appended to + * them, because glibc defines a global macro by the same name. + */ + +/* include/linux/dirent.h */ +struct kernel_dirent64 { + unsigned long long d_ino; + long long d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +/* include/linux/dirent.h */ +struct kernel_dirent { + long d_ino; + long d_off; + unsigned short d_reclen; + char d_name[256]; +}; + +/* include/linux/time.h */ +struct kernel_timespec { + long tv_sec; + long tv_nsec; +}; + +/* include/linux/time.h */ +struct kernel_timeval { + long tv_sec; + long tv_usec; +}; + +/* include/linux/resource.h */ +struct kernel_rusage { + struct kernel_timeval ru_utime; + struct kernel_timeval ru_stime; + long ru_maxrss; + long ru_ixrss; + long ru_idrss; + long ru_isrss; + long ru_minflt; + long ru_majflt; + long ru_nswap; + long ru_inblock; + long ru_oublock; + long ru_msgsnd; + long ru_msgrcv; + long ru_nsignals; + long ru_nvcsw; + long ru_nivcsw; +}; + +#if defined(__i386__) || defined(__arm__) \ + || defined(__PPC__) || (defined(__s390__) && !defined(__s390x__)) + +/* include/asm-{arm,i386,mips,ppc}/signal.h */ +struct kernel_old_sigaction { + union { + void (*sa_handler_)(int); + void (*sa_sigaction_)(int, siginfo_t *, void *); + }; + unsigned long sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +} __attribute__((packed,aligned(4))); +#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) + #define kernel_old_sigaction kernel_sigaction +#elif defined(__aarch64__) + // No kernel_old_sigaction defined for arm64. +#endif + +/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the + * exactly match the size of the signal set, even though the API was + * intended to be extensible. We define our own KERNEL_NSIG to deal with + * this. + * Please note that glibc provides signals [1.._NSIG-1], whereas the + * kernel (and this header) provides the range [1..KERNEL_NSIG]. The + * actual number of signals is obviously the same, but the constants + * differ by one. + */ +#ifdef __mips__ +#define KERNEL_NSIG 128 +#else +#define KERNEL_NSIG 64 +#endif + +/* include/asm-{arm,i386,mips,x86_64}/signal.h */ +struct kernel_sigset_t { + unsigned long sig[(KERNEL_NSIG + 8*sizeof(unsigned long) - 1)/ + (8*sizeof(unsigned long))]; +}; + +/* include/asm-{arm,generic,i386,mips,x86_64,ppc}/signal.h */ +struct kernel_sigaction { +#ifdef __mips__ + unsigned long sa_flags; + union { + void (*sa_handler_)(int); + void (*sa_sigaction_)(int, siginfo_t *, void *); + }; + struct kernel_sigset_t sa_mask; +#else + union { + void (*sa_handler_)(int); + void (*sa_sigaction_)(int, siginfo_t *, void *); + }; + unsigned long sa_flags; + void (*sa_restorer)(void); + struct kernel_sigset_t sa_mask; +#endif +}; + +/* include/asm-{arm,i386,mips,ppc,s390}/stat.h */ +#ifdef __mips__ +#if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +struct kernel_stat { +#else +struct kernel_stat64 { +#endif + unsigned st_dev; + unsigned __pad0[3]; + unsigned long long st_ino; + unsigned st_mode; + unsigned st_nlink; + unsigned st_uid; + unsigned st_gid; + unsigned st_rdev; + unsigned __pad1[3]; + long long st_size; + unsigned st_atime_; + unsigned st_atime_nsec_; + unsigned st_mtime_; + unsigned st_mtime_nsec_; + unsigned st_ctime_; + unsigned st_ctime_nsec_; + unsigned st_blksize; + unsigned __pad2; + unsigned long long st_blocks; +}; +#elif defined __PPC__ +struct kernel_stat64 { + unsigned long long st_dev; + unsigned long long st_ino; + unsigned st_nlink; + unsigned st_mode; + unsigned st_uid; + unsigned st_gid; + int __pad2; + unsigned long long st_rdev; + long long st_size; + long long st_blksize; + long long st_blocks; + kernel_timespec st_atim; + kernel_timespec st_mtim; + kernel_timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; + unsigned long __unused6; +}; +#else +struct kernel_stat64 { + unsigned long long st_dev; + unsigned char __pad0[4]; + unsigned __st_ino; + unsigned st_mode; + unsigned st_nlink; + unsigned st_uid; + unsigned st_gid; + unsigned long long st_rdev; + unsigned char __pad3[4]; + long long st_size; + unsigned st_blksize; + unsigned long long st_blocks; + unsigned st_atime_; + unsigned st_atime_nsec_; + unsigned st_mtime_; + unsigned st_mtime_nsec_; + unsigned st_ctime_; + unsigned st_ctime_nsec_; + unsigned long long st_ino; +}; +#endif + +/* include/asm-{arm,generic,i386,mips,x86_64,ppc,s390}/stat.h */ +#if defined(__i386__) || defined(__arm__) +struct kernel_stat { + /* The kernel headers suggest that st_dev and st_rdev should be 32bit + * quantities encoding 12bit major and 20bit minor numbers in an interleaved + * format. In reality, we do not see useful data in the top bits. So, + * we'll leave the padding in here, until we find a better solution. + */ + unsigned short st_dev; + short pad1; + unsigned st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + short pad2; + unsigned st_size; + unsigned st_blksize; + unsigned st_blocks; + unsigned st_atime_; + unsigned st_atime_nsec_; + unsigned st_mtime_; + unsigned st_mtime_nsec_; + unsigned st_ctime_; + unsigned st_ctime_nsec_; + unsigned __unused4; + unsigned __unused5; +}; +#elif defined(__x86_64__) +struct kernel_stat { + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_nlink; + unsigned st_mode; + unsigned st_uid; + unsigned st_gid; + unsigned __pad0; + uint64_t st_rdev; + int64_t st_size; + int64_t st_blksize; + int64_t st_blocks; + uint64_t st_atime_; + uint64_t st_atime_nsec_; + uint64_t st_mtime_; + uint64_t st_mtime_nsec_; + uint64_t st_ctime_; + uint64_t st_ctime_nsec_; + int64_t __unused[3]; +}; +#elif defined(__PPC__) +struct kernel_stat { + unsigned long long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned long st_mode; + unsigned st_uid; + unsigned st_gid; + int __pad2; + unsigned long long st_rdev; + long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + kernel_timespec st_atim; + kernel_timespec st_mtim; + kernel_timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; + unsigned long __unused6; +}; +#elif defined(__mips__) \ + && !(_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +struct kernel_stat { + unsigned st_dev; + int st_pad1[3]; + unsigned st_ino; + unsigned st_mode; + unsigned st_nlink; + unsigned st_uid; + unsigned st_gid; + unsigned st_rdev; + int st_pad2[2]; + long st_size; + int st_pad3; + long st_atime_; + long st_atime_nsec_; + long st_mtime_; + long st_mtime_nsec_; + long st_ctime_; + long st_ctime_nsec_; + int st_blksize; + int st_blocks; + int st_pad4[14]; +}; +#elif defined(__aarch64__) +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + unsigned long __pad1; + long st_size; + int st_blksize; + int __pad2; + long st_blocks; + long st_atime_; + unsigned long st_atime_nsec_; + long st_mtime_; + unsigned long st_mtime_nsec_; + long st_ctime_; + unsigned long st_ctime_nsec_; + unsigned int __unused4; + unsigned int __unused5; +}; +#elif defined(__s390x__) +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad1; + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_atime_; + unsigned long st_atime_nsec_; + unsigned long st_mtime_; + unsigned long st_mtime_nsec_; + unsigned long st_ctime_; + unsigned long st_ctime_nsec_; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; +#elif defined(__s390__) +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime_; + unsigned long st_atime_nsec_; + unsigned long st_mtime_; + unsigned long st_mtime_nsec_; + unsigned long st_ctime_; + unsigned long st_ctime_nsec_; + unsigned long __unused4; + unsigned long __unused5; +}; +#endif + + +/* Definitions missing from the standard header files */ +#ifndef O_DIRECTORY +#if defined(__arm__) +#define O_DIRECTORY 0040000 +#else +#define O_DIRECTORY 0200000 +#endif +#endif +#ifndef PR_GET_DUMPABLE +#define PR_GET_DUMPABLE 3 +#endif +#ifndef PR_SET_DUMPABLE +#define PR_SET_DUMPABLE 4 +#endif +#ifndef AT_FDCWD +#define AT_FDCWD (-100) +#endif +#ifndef AT_SYMLINK_NOFOLLOW +#define AT_SYMLINK_NOFOLLOW 0x100 +#endif +#ifndef AT_REMOVEDIR +#define AT_REMOVEDIR 0x200 +#endif +#ifndef MREMAP_FIXED +#define MREMAP_FIXED 2 +#endif +#ifndef SA_RESTORER +#define SA_RESTORER 0x04000000 +#endif + +#if defined(__i386__) +#ifndef __NR_rt_sigaction +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#endif +#ifndef __NR_stat64 +#define __NR_stat64 195 +#endif +#ifndef __NR_fstat64 +#define __NR_fstat64 197 +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 220 +#endif +#ifndef __NR_gettid +#define __NR_gettid 224 +#endif +#ifndef __NR_futex +#define __NR_futex 240 +#endif +#ifndef __NR_openat +#define __NR_openat 295 +#endif +#ifndef __NR_getcpu +#define __NR_getcpu 318 +#endif +/* End of i386 definitions */ +#elif defined(__arm__) +#ifndef __syscall +#if defined(__thumb__) || defined(__ARM_EABI__) +#define __SYS_REG(name) register long __sysreg __asm__("r6") = __NR_##name; +#define __SYS_REG_LIST(regs...) [sysreg] "r" (__sysreg) , ##regs +#define __syscall(name) "swi\t0" +#define __syscall_safe(name) \ + "push {r7}\n" \ + "mov r7,%[sysreg]\n" \ + __syscall(name)"\n" \ + "pop {r7}" +#else +#define __SYS_REG(name) +#define __SYS_REG_LIST(regs...) regs +#define __syscall(name) "swi\t" __sys1(__NR_##name) "" +#define __syscall_safe(name) __syscall(name) +#endif +#endif +#ifndef __NR_rt_sigaction +#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174) +#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175) +#endif +#ifndef __NR_stat64 +#define __NR_stat64 (__NR_SYSCALL_BASE + 195) +#endif +#ifndef __NR_fstat64 +#define __NR_fstat64 (__NR_SYSCALL_BASE + 197) +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 (__NR_SYSCALL_BASE + 217) +#endif +#ifndef __NR_gettid +#define __NR_gettid (__NR_SYSCALL_BASE + 224) +#endif +#ifndef __NR_futex +#define __NR_futex (__NR_SYSCALL_BASE + 240) +#endif +/* End of ARM definitions */ +#elif defined(__x86_64__) +#ifndef __NR_gettid +#define __NR_gettid 186 +#endif +#ifndef __NR_futex +#define __NR_futex 202 +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 217 +#endif +#ifndef __NR_openat +#define __NR_openat 257 +#endif +/* End of x86-64 definitions */ +#elif defined(__mips__) +#if _MIPS_SIM == _MIPS_SIM_ABI32 +#ifndef __NR_rt_sigaction +#define __NR_rt_sigaction (__NR_Linux + 194) +#define __NR_rt_sigprocmask (__NR_Linux + 195) +#endif +#ifndef __NR_stat64 +#define __NR_stat64 (__NR_Linux + 213) +#endif +#ifndef __NR_fstat64 +#define __NR_fstat64 (__NR_Linux + 215) +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 (__NR_Linux + 219) +#endif +#ifndef __NR_gettid +#define __NR_gettid (__NR_Linux + 222) +#endif +#ifndef __NR_futex +#define __NR_futex (__NR_Linux + 238) +#endif +#ifndef __NR_openat +#define __NR_openat (__NR_Linux + 288) +#endif +#ifndef __NR_fstatat +#define __NR_fstatat (__NR_Linux + 293) +#endif +#ifndef __NR_getcpu +#define __NR_getcpu (__NR_Linux + 312) +#endif +/* End of MIPS (old 32bit API) definitions */ +#elif (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +#ifndef __NR_gettid +#define __NR_gettid (__NR_Linux + 178) +#endif +#ifndef __NR_futex +#define __NR_futex (__NR_Linux + 194) +#endif +#ifndef __NR_openat +#define __NR_openat (__NR_Linux + 247) +#endif +#ifndef __NR_fstatat +#define __NR_fstatat (__NR_Linux + 252) +#endif +#ifndef __NR_getcpu +#define __NR_getcpu (__NR_Linux + 271) +#endif +/* End of MIPS (64bit API) definitions */ +#else +#ifndef __NR_gettid +#define __NR_gettid (__NR_Linux + 178) +#endif +#ifndef __NR_futex +#define __NR_futex (__NR_Linux + 194) +#endif +#ifndef __NR_openat +#define __NR_openat (__NR_Linux + 251) +#endif +#ifndef __NR_fstatat +#define __NR_fstatat (__NR_Linux + 256) +#endif +#ifndef __NR_getcpu +#define __NR_getcpu (__NR_Linux + 275) +#endif +/* End of MIPS (new 32bit API) definitions */ +#endif +/* End of MIPS definitions */ +#elif defined(__PPC__) +#ifndef __NR_rt_sigaction +#define __NR_rt_sigaction 173 +#define __NR_rt_sigprocmask 174 +#endif +#ifndef __NR_stat64 +#define __NR_stat64 195 +#endif +#ifndef __NR_fstat64 +#define __NR_fstat64 197 +#endif +#ifndef __NR_socket +#define __NR_socket 198 +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 202 +#endif +#ifndef __NR_gettid +#define __NR_gettid 207 +#endif +#ifndef __NR_futex +#define __NR_futex 221 +#endif +#ifndef __NR_openat +#define __NR_openat 286 +#endif +#ifndef __NR_getcpu +#define __NR_getcpu 302 +#endif +/* End of powerpc definitions */ +#elif defined(__aarch64__) +#ifndef __NR_fstatat +#define __NR_fstatat 79 +#endif +/* End of aarch64 definitions */ +#elif defined(__s390__) +#ifndef __NR_quotactl +#define __NR_quotactl 131 +#endif +#ifndef __NR_rt_sigreturn +#define __NR_rt_sigreturn 173 +#endif +#ifndef __NR_rt_sigaction +#define __NR_rt_sigaction 174 +#endif +#ifndef __NR_rt_sigprocmask +#define __NR_rt_sigprocmask 175 +#endif +#ifndef __NR_rt_sigpending +#define __NR_rt_sigpending 176 +#endif +#ifndef __NR_rt_sigsuspend +#define __NR_rt_sigsuspend 179 +#endif +#ifndef __NR_pread64 +#define __NR_pread64 180 +#endif +#ifndef __NR_pwrite64 +#define __NR_pwrite64 181 +#endif +#ifndef __NR_getdents64 +#define __NR_getdents64 220 +#endif +#ifndef __NR_readahead +#define __NR_readahead 222 +#endif +#ifndef __NR_setxattr +#define __NR_setxattr 224 +#endif +#ifndef __NR_lsetxattr +#define __NR_lsetxattr 225 +#endif +#ifndef __NR_getxattr +#define __NR_getxattr 227 +#endif +#ifndef __NR_lgetxattr +#define __NR_lgetxattr 228 +#endif +#ifndef __NR_listxattr +#define __NR_listxattr 230 +#endif +#ifndef __NR_llistxattr +#define __NR_llistxattr 231 +#endif +#ifndef __NR_gettid +#define __NR_gettid 236 +#endif +#ifndef __NR_tkill +#define __NR_tkill 237 +#endif +#ifndef __NR_futex +#define __NR_futex 238 +#endif +#ifndef __NR_sched_setaffinity +#define __NR_sched_setaffinity 239 +#endif +#ifndef __NR_sched_getaffinity +#define __NR_sched_getaffinity 240 +#endif +#ifndef __NR_set_tid_address +#define __NR_set_tid_address 252 +#endif +#ifndef __NR_clock_gettime +#define __NR_clock_gettime 260 +#endif +#ifndef __NR_clock_getres +#define __NR_clock_getres 261 +#endif +#ifndef __NR_statfs64 +#define __NR_statfs64 265 +#endif +#ifndef __NR_fstatfs64 +#define __NR_fstatfs64 266 +#endif +#ifndef __NR_ioprio_set +#define __NR_ioprio_set 282 +#endif +#ifndef __NR_ioprio_get +#define __NR_ioprio_get 283 +#endif +#ifndef __NR_openat +#define __NR_openat 288 +#endif +#ifndef __NR_unlinkat +#define __NR_unlinkat 294 +#endif +#ifndef __NR_move_pages +#define __NR_move_pages 310 +#endif +#ifndef __NR_getcpu +#define __NR_getcpu 311 +#endif +#ifndef __NR_fallocate +#define __NR_fallocate 314 +#endif +/* Some syscalls are named/numbered differently between s390 and s390x. */ +#ifdef __s390x__ +# ifndef __NR_getrlimit +# define __NR_getrlimit 191 +# endif +# ifndef __NR_setresuid +# define __NR_setresuid 208 +# endif +# ifndef __NR_getresuid +# define __NR_getresuid 209 +# endif +# ifndef __NR_setresgid +# define __NR_setresgid 210 +# endif +# ifndef __NR_getresgid +# define __NR_getresgid 211 +# endif +# ifndef __NR_setfsuid +# define __NR_setfsuid 215 +# endif +# ifndef __NR_setfsgid +# define __NR_setfsgid 216 +# endif +# ifndef __NR_fadvise64 +# define __NR_fadvise64 253 +# endif +# ifndef __NR_newfstatat +# define __NR_newfstatat 293 +# endif +#else /* __s390x__ */ +# ifndef __NR_getrlimit +# define __NR_getrlimit 76 +# endif +# ifndef __NR_setfsuid +# define __NR_setfsuid 138 +# endif +# ifndef __NR_setfsgid +# define __NR_setfsgid 139 +# endif +# ifndef __NR_setresuid +# define __NR_setresuid 164 +# endif +# ifndef __NR_getresuid +# define __NR_getresuid 165 +# endif +# ifndef __NR_setresgid +# define __NR_setresgid 170 +# endif +# ifndef __NR_getresgid +# define __NR_getresgid 171 +# endif +# ifndef __NR_ugetrlimit +# define __NR_ugetrlimit 191 +# endif +# ifndef __NR_mmap2 +# define __NR_mmap2 192 +# endif +# ifndef __NR_setresuid32 +# define __NR_setresuid32 208 +# endif +# ifndef __NR_getresuid32 +# define __NR_getresuid32 209 +# endif +# ifndef __NR_setresgid32 +# define __NR_setresgid32 210 +# endif +# ifndef __NR_getresgid32 +# define __NR_getresgid32 211 +# endif +# ifndef __NR_setfsuid32 +# define __NR_setfsuid32 215 +# endif +# ifndef __NR_setfsgid32 +# define __NR_setfsgid32 216 +# endif +# ifndef __NR_fadvise64_64 +# define __NR_fadvise64_64 264 +# endif +# ifndef __NR_fstatat64 +# define __NR_fstatat64 293 +# endif +#endif /* __s390__ */ +/* End of s390/s390x definitions */ +#elif defined(__riscv) +# ifndef __NR_gettid +# define __NR_gettid 178 +# endif +# ifndef __NR_futex +# define __NR_futex 422 +# endif +# ifndef __NR_getdents64 +# define __NR_getdents64 61 +# endif +# ifndef __NR_openat +# define __NR_openat 56 +# endif +# ifndef __NR_fstatat +# define __NR_fstatat 79 +# endif +#endif + + +/* After forking, we must make sure to only call system calls. */ +#if __BOUNDED_POINTERS__ + #error "Need to port invocations of syscalls for bounded ptrs" +#else + /* The core dumper and the thread lister get executed after threads + * have been suspended. As a consequence, we cannot call any functions + * that acquire locks. Unfortunately, libc wraps most system calls + * (e.g. in order to implement pthread_atfork, and to make calls + * cancellable), which means we cannot call these functions. Instead, + * we have to call syscall() directly. + */ + #undef LSS_ERRNO + #ifdef SYS_ERRNO + /* Allow the including file to override the location of errno. This can + * be useful when using clone() with the CLONE_VM option. + */ + #define LSS_ERRNO SYS_ERRNO + #else + #define LSS_ERRNO errno + #endif + + #undef LSS_INLINE + #ifdef SYS_INLINE + #define LSS_INLINE SYS_INLINE + #else + #define LSS_INLINE static inline + #endif + + /* Allow the including file to override the prefix used for all new + * system calls. By default, it will be set to "sys_". + */ + #undef LSS_NAME + #ifndef SYS_PREFIX + #define LSS_NAME(name) sys_##name + #elif SYS_PREFIX < 0 + #define LSS_NAME(name) name + #elif SYS_PREFIX == 0 + #define LSS_NAME(name) sys0_##name + #elif SYS_PREFIX == 1 + #define LSS_NAME(name) sys1_##name + #elif SYS_PREFIX == 2 + #define LSS_NAME(name) sys2_##name + #elif SYS_PREFIX == 3 + #define LSS_NAME(name) sys3_##name + #elif SYS_PREFIX == 4 + #define LSS_NAME(name) sys4_##name + #elif SYS_PREFIX == 5 + #define LSS_NAME(name) sys5_##name + #elif SYS_PREFIX == 6 + #define LSS_NAME(name) sys6_##name + #elif SYS_PREFIX == 7 + #define LSS_NAME(name) sys7_##name + #elif SYS_PREFIX == 8 + #define LSS_NAME(name) sys8_##name + #elif SYS_PREFIX == 9 + #define LSS_NAME(name) sys9_##name + #endif + + #undef LSS_RETURN + #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__aarch64__) || defined(__s390__) || defined(__riscv)) + /* Failing system calls return a negative result in the range of + * -1..-4095. These are "errno" values with the sign inverted. + */ + #define LSS_RETURN(type, res) \ + do { \ + if ((unsigned long)(res) >= (unsigned long)(-4095)) { \ + LSS_ERRNO = -(res); \ + res = -1; \ + } \ + return (type) (res); \ + } while (0) + #elif defined(__mips__) + /* On MIPS, failing system calls return -1, and set errno in a + * separate CPU register. + */ + #define LSS_RETURN(type, res, err) \ + do { \ + if (err) { \ + LSS_ERRNO = (res); \ + res = -1; \ + } \ + return (type) (res); \ + } while (0) + #elif defined(__PPC__) + /* On PPC, failing system calls return -1, and set errno in a + * separate CPU register. See linux/unistd.h. + */ + #define LSS_RETURN(type, res, err) \ + do { \ + if (err & 0x10000000 ) { \ + LSS_ERRNO = (res); \ + res = -1; \ + } \ + return (type) (res); \ + } while (0) + #endif + #if defined(__i386__) + #if defined(NO_FRAME_POINTER) && (100 * __GNUC__ + __GNUC_MINOR__ >= 404) + /* This only works for GCC-4.4 and above -- the first version to use + .cfi directives for dwarf unwind info. */ + #define CFI_ADJUST_CFA_OFFSET(adjust) \ + ".cfi_adjust_cfa_offset " #adjust "\n" + #else + #define CFI_ADJUST_CFA_OFFSET(adjust) /**/ + #endif + + /* In PIC mode (e.g. when building shared libraries), gcc for i386 + * reserves ebx. Unfortunately, most distribution ship with implementations + * of _syscallX() which clobber ebx. + * Also, most definitions of _syscallX() neglect to mark "memory" as being + * clobbered. This causes problems with compilers, that do a better job + * at optimizing across __asm__ calls. + * So, we just have to redefine all of the _syscallX() macros. + */ + #undef LSS_BODY + #define LSS_BODY(type,args...) \ + long __res; \ + __asm__ __volatile__("push %%ebx\n" \ + CFI_ADJUST_CFA_OFFSET(4) \ + "movl %2,%%ebx\n" \ + "int $0x80\n" \ + "pop %%ebx\n" \ + CFI_ADJUST_CFA_OFFSET(-4) \ + args \ + : "memory"); \ + LSS_RETURN(type,__res) + #undef _syscall0 + #define _syscall0(type,name) \ + type LSS_NAME(name)(void) { \ + long __res; \ + __asm__ volatile("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name) \ + : "memory"); \ + LSS_RETURN(type,__res); \ + } + #undef _syscall1 + #define _syscall1(type,name,type1,arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_BODY(type, \ + : "=a" (__res) \ + : "0" (__NR_##name), "ri" ((long)(arg1))); \ + } + #undef _syscall2 + #define _syscall2(type,name,type1,arg1,type2,arg2) \ + type LSS_NAME(name)(type1 arg1,type2 arg2) { \ + LSS_BODY(type, \ + : "=a" (__res) \ + : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \ + } + #undef _syscall3 + #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ + type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \ + LSS_BODY(type, \ + : "=a" (__res) \ + : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ + } + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_BODY(type, \ + : "=a" (__res) \ + : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ + } + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + long __res; \ + __asm__ __volatile__("push %%ebx\n" \ + "movl %2,%%ebx\n" \ + "movl %1,%%eax\n" \ + "int $0x80\n" \ + "pop %%ebx" \ + : "=a" (__res) \ + : "i" (__NR_##name), "ri" ((long)(arg1)), \ + "c" ((long)(arg2)), "d" ((long)(arg3)), \ + "S" ((long)(arg4)), "D" ((long)(arg5)) \ + : "memory"); \ + LSS_RETURN(type,__res); \ + } + #undef _syscall6 + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + long __res; \ + struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \ + __asm__ __volatile__("push %%ebp\n" \ + "push %%ebx\n" \ + "movl 4(%2),%%ebp\n" \ + "movl 0(%2), %%ebx\n" \ + "movl %1,%%eax\n" \ + "int $0x80\n" \ + "pop %%ebx\n" \ + "pop %%ebp" \ + : "=a" (__res) \ + : "i" (__NR_##name), "0" ((long)(&__s)), \ + "c" ((long)(arg2)), "d" ((long)(arg3)), \ + "S" ((long)(arg4)), "D" ((long)(arg5)) \ + : "memory"); \ + LSS_RETURN(type,__res); \ + } + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long __res; + __asm__ __volatile__(/* if (fn == NULL) + * return -EINVAL; + */ + "movl %3,%%ecx\n" + "jecxz 1f\n" + + /* if (child_stack == NULL) + * return -EINVAL; + */ + "movl %4,%%ecx\n" + "jecxz 1f\n" + + /* Set up alignment of the child stack: + * child_stack = (child_stack & ~0xF) - 20; + */ + "andl $-16,%%ecx\n" + "subl $20,%%ecx\n" + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + "movl %6,%%eax\n" + "movl %%eax,4(%%ecx)\n" + "movl %3,%%eax\n" + "movl %%eax,(%%ecx)\n" + + /* %eax = syscall(%eax = __NR_clone, + * %ebx = flags, + * %ecx = child_stack, + * %edx = parent_tidptr, + * %esi = newtls, + * %edi = child_tidptr) + * Also, make sure that %ebx gets preserved as it is + * used in PIC mode. + */ + "movl %8,%%esi\n" + "movl %7,%%edx\n" + "movl %5,%%eax\n" + "movl %9,%%edi\n" + "pushl %%ebx\n" + "movl %%eax,%%ebx\n" + "movl %2,%%eax\n" + "int $0x80\n" + + /* In the parent: restore %ebx + * In the child: move "fn" into %ebx + */ + "popl %%ebx\n" + + /* if (%eax != 0) + * return %eax; + */ + "test %%eax,%%eax\n" + "jnz 1f\n" + + /* In the child, now. Terminate frame pointer chain. + */ + "movl $0,%%ebp\n" + + /* Call "fn". "arg" is already on the stack. + */ + "call *%%ebx\n" + + /* Call _exit(%ebx). Unfortunately older versions + * of gcc restrict the number of arguments that can + * be passed to asm(). So, we need to hard-code the + * system call number. + */ + "movl %%eax,%%ebx\n" + "movl $1,%%eax\n" + "int $0x80\n" + + /* Return to parent. + */ + "1:\n" + : "=a" (__res) + : "0"(-EINVAL), "i"(__NR_clone), + "m"(fn), "m"(child_stack), "m"(flags), "m"(arg), + "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr) + : "memory", "ecx", "edx", "esi", "edi"); + LSS_RETURN(int, __res); + } + + LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { + /* On i386, the kernel does not know how to return from a signal + * handler. Instead, it relies on user space to provide a + * restorer function that calls the {rt_,}sigreturn() system call. + * Unfortunately, we cannot just reference the glibc version of this + * function, as glibc goes out of its way to make it inaccessible. + */ + void (*res)(void); + __asm__ __volatile__("call 2f\n" + "0:.align 16\n" + "1:movl %1,%%eax\n" + "int $0x80\n" + "2:popl %0\n" + "addl $(1b-0b),%0\n" + : "=a" (res) + : "i" (__NR_rt_sigreturn)); + return res; + } + LSS_INLINE void (*LSS_NAME(restore)(void))(void) { + /* On i386, the kernel does not know how to return from a signal + * handler. Instead, it relies on user space to provide a + * restorer function that calls the {rt_,}sigreturn() system call. + * Unfortunately, we cannot just reference the glibc version of this + * function, as glibc goes out of its way to make it inaccessible. + */ + void (*res)(void); + __asm__ __volatile__("call 2f\n" + "0:.align 16\n" + "1:pop %%eax\n" + "movl %1,%%eax\n" + "int $0x80\n" + "2:popl %0\n" + "addl $(1b-0b),%0\n" + : "=a" (res) + : "i" (__NR_sigreturn)); + return res; + } + #elif defined(__x86_64__) + /* There are no known problems with any of the _syscallX() macros + * currently shipping for x86_64, but we still need to be able to define + * our own version so that we can override the location of the errno + * location (e.g. when using the clone() system call with the CLONE_VM + * option). + */ + #undef LSS_ENTRYPOINT + #define LSS_ENTRYPOINT "syscall\n" + + /* The x32 ABI has 32 bit longs, but the syscall interface is 64 bit. + * We need to explicitly cast to an unsigned 64 bit type to avoid implicit + * sign extension. We can't cast pointers directly because those are + * 32 bits, and gcc will dump ugly warnings about casting from a pointer + * to an integer of a different size. + */ + #undef LSS_SYSCALL_ARG + #define LSS_SYSCALL_ARG(a) ((uint64_t)(uintptr_t)(a)) + #undef _LSS_RETURN + #define _LSS_RETURN(type, res, cast) \ + do { \ + if ((uint64_t)(res) >= (uint64_t)(-4095)) { \ + LSS_ERRNO = -(res); \ + res = -1; \ + } \ + return (type)(cast)(res); \ + } while (0) + #undef LSS_RETURN + #define LSS_RETURN(type, res) _LSS_RETURN(type, res, uintptr_t) + + #undef _LSS_BODY + #define _LSS_BODY(nr, type, name, cast, ...) \ + long long __res; \ + __asm__ __volatile__(LSS_BODY_ASM##nr LSS_ENTRYPOINT \ + : "=a" (__res) \ + : "0" (__NR_##name) LSS_BODY_ARG##nr(__VA_ARGS__) \ + : LSS_BODY_CLOBBER##nr "r11", "rcx", "memory"); \ + _LSS_RETURN(type, __res, cast) + #undef LSS_BODY + #define LSS_BODY(nr, type, name, args...) \ + _LSS_BODY(nr, type, name, uintptr_t, ## args) + + #undef LSS_BODY_ASM0 + #undef LSS_BODY_ASM1 + #undef LSS_BODY_ASM2 + #undef LSS_BODY_ASM3 + #undef LSS_BODY_ASM4 + #undef LSS_BODY_ASM5 + #undef LSS_BODY_ASM6 + #define LSS_BODY_ASM0 + #define LSS_BODY_ASM1 LSS_BODY_ASM0 + #define LSS_BODY_ASM2 LSS_BODY_ASM1 + #define LSS_BODY_ASM3 LSS_BODY_ASM2 + #define LSS_BODY_ASM4 LSS_BODY_ASM3 "movq %5,%%r10;" + #define LSS_BODY_ASM5 LSS_BODY_ASM4 "movq %6,%%r8;" + #define LSS_BODY_ASM6 LSS_BODY_ASM5 "movq %7,%%r9;" + + #undef LSS_BODY_CLOBBER0 + #undef LSS_BODY_CLOBBER1 + #undef LSS_BODY_CLOBBER2 + #undef LSS_BODY_CLOBBER3 + #undef LSS_BODY_CLOBBER4 + #undef LSS_BODY_CLOBBER5 + #undef LSS_BODY_CLOBBER6 + #define LSS_BODY_CLOBBER0 + #define LSS_BODY_CLOBBER1 LSS_BODY_CLOBBER0 + #define LSS_BODY_CLOBBER2 LSS_BODY_CLOBBER1 + #define LSS_BODY_CLOBBER3 LSS_BODY_CLOBBER2 + #define LSS_BODY_CLOBBER4 LSS_BODY_CLOBBER3 "r10", + #define LSS_BODY_CLOBBER5 LSS_BODY_CLOBBER4 "r8", + #define LSS_BODY_CLOBBER6 LSS_BODY_CLOBBER5 "r9", + + #undef LSS_BODY_ARG0 + #undef LSS_BODY_ARG1 + #undef LSS_BODY_ARG2 + #undef LSS_BODY_ARG3 + #undef LSS_BODY_ARG4 + #undef LSS_BODY_ARG5 + #undef LSS_BODY_ARG6 + #define LSS_BODY_ARG0() + #define LSS_BODY_ARG1(arg1) \ + LSS_BODY_ARG0(), "D" (arg1) + #define LSS_BODY_ARG2(arg1, arg2) \ + LSS_BODY_ARG1(arg1), "S" (arg2) + #define LSS_BODY_ARG3(arg1, arg2, arg3) \ + LSS_BODY_ARG2(arg1, arg2), "d" (arg3) + #define LSS_BODY_ARG4(arg1, arg2, arg3, arg4) \ + LSS_BODY_ARG3(arg1, arg2, arg3), "r" (arg4) + #define LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5) \ + LSS_BODY_ARG4(arg1, arg2, arg3, arg4), "r" (arg5) + #define LSS_BODY_ARG6(arg1, arg2, arg3, arg4, arg5, arg6) \ + LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5), "r" (arg6) + + #undef _syscall0 + #define _syscall0(type,name) \ + type LSS_NAME(name)() { \ + LSS_BODY(0, type, name); \ + } + #undef _syscall1 + #define _syscall1(type,name,type1,arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_BODY(1, type, name, LSS_SYSCALL_ARG(arg1)); \ + } + #undef _syscall2 + #define _syscall2(type,name,type1,arg1,type2,arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_BODY(2, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2));\ + } + #undef _syscall3 + #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_BODY(3, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ + LSS_SYSCALL_ARG(arg3)); \ + } + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_BODY(4, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ + LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4));\ + } + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_BODY(5, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ + LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \ + LSS_SYSCALL_ARG(arg5)); \ + } + #undef _syscall6 + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_BODY(6, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \ + LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \ + LSS_SYSCALL_ARG(arg5), LSS_SYSCALL_ARG(arg6));\ + } + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long long __res; + { + __asm__ __volatile__(/* if (fn == NULL) + * return -EINVAL; + */ + "testq %4,%4\n" + "jz 1f\n" + + /* if (child_stack == NULL) + * return -EINVAL; + */ + "testq %5,%5\n" + "jz 1f\n" + + /* Set up alignment of the child stack: + * child_stack = (child_stack & ~0xF) - 16; + */ + "andq $-16,%5\n" + "subq $16,%5\n" + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + "movq %7,8(%5)\n" + "movq %4,0(%5)\n" + + /* %rax = syscall(%rax = __NR_clone, + * %rdi = flags, + * %rsi = child_stack, + * %rdx = parent_tidptr, + * %r8 = new_tls, + * %r10 = child_tidptr) + */ + "movq %2,%%rax\n" + "movq %9,%%r8\n" + "movq %10,%%r10\n" + "syscall\n" + + /* if (%rax != 0) + * return; + */ + "testq %%rax,%%rax\n" + "jnz 1f\n" + + /* In the child. Terminate frame pointer chain. + */ + "xorq %%rbp,%%rbp\n" + + /* Call "fn(arg)". + */ + "popq %%rax\n" + "popq %%rdi\n" + "call *%%rax\n" + + /* Call _exit(%ebx). + */ + "movq %%rax,%%rdi\n" + "movq %3,%%rax\n" + "syscall\n" + + /* Return to parent. + */ + "1:\n" + : "=a" (__res) + : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), + "r"(LSS_SYSCALL_ARG(fn)), + "S"(LSS_SYSCALL_ARG(child_stack)), + "D"(LSS_SYSCALL_ARG(flags)), + "r"(LSS_SYSCALL_ARG(arg)), + "d"(LSS_SYSCALL_ARG(parent_tidptr)), + "r"(LSS_SYSCALL_ARG(newtls)), + "r"(LSS_SYSCALL_ARG(child_tidptr)) + : "memory", "r8", "r10", "r11", "rcx"); + } + LSS_RETURN(int, __res); + } + + LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { + /* On x86-64, the kernel does not know how to return from + * a signal handler. Instead, it relies on user space to provide a + * restorer function that calls the rt_sigreturn() system call. + * Unfortunately, we cannot just reference the glibc version of this + * function, as glibc goes out of its way to make it inaccessible. + */ + long long res; + __asm__ __volatile__("call 2f\n" + "0:.align 16\n" + "1:movq %1,%%rax\n" + "syscall\n" + "2:popq %0\n" + "addq $(1b-0b),%0\n" + : "=a" (res) + : "i" (__NR_rt_sigreturn)); + return (void (*)(void))(uintptr_t)res; + } + #elif defined(__arm__) + /* Most definitions of _syscallX() neglect to mark "memory" as being + * clobbered. This causes problems with compilers, that do a better job + * at optimizing across __asm__ calls. + * So, we just have to redefine all fo the _syscallX() macros. + */ + #undef LSS_REG + #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a + + /* r0..r3 are scratch registers and not preserved across function + * calls. We need to first evaluate the first 4 syscall arguments + * and store them on stack. They must be loaded into r0..r3 after + * all function calls to avoid r0..r3 being clobbered. + */ + #undef LSS_SAVE_ARG + #define LSS_SAVE_ARG(r,a) long __tmp##r = (long)a + #undef LSS_LOAD_ARG + #define LSS_LOAD_ARG(r) register long __r##r __asm__("r"#r) = __tmp##r + + #undef LSS_BODY + #define LSS_BODY(type, name, args...) \ + register long __res_r0 __asm__("r0"); \ + long __res; \ + __SYS_REG(name) \ + __asm__ __volatile__ (__syscall_safe(name) \ + : "=r"(__res_r0) \ + : __SYS_REG_LIST(args) \ + : "lr", "memory"); \ + __res = __res_r0; \ + LSS_RETURN(type, __res) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)() { \ + LSS_BODY(type, name); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + /* There is no need for using a volatile temp. */ \ + LSS_REG(0, arg1); \ + LSS_BODY(type, name, "r"(__r0)); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_SAVE_ARG(0, arg1); \ + LSS_SAVE_ARG(1, arg2); \ + LSS_LOAD_ARG(0); \ + LSS_LOAD_ARG(1); \ + LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_SAVE_ARG(0, arg1); \ + LSS_SAVE_ARG(1, arg2); \ + LSS_SAVE_ARG(2, arg3); \ + LSS_LOAD_ARG(0); \ + LSS_LOAD_ARG(1); \ + LSS_LOAD_ARG(2); \ + LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \ + } + #undef _syscall4 + #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_SAVE_ARG(0, arg1); \ + LSS_SAVE_ARG(1, arg2); \ + LSS_SAVE_ARG(2, arg3); \ + LSS_SAVE_ARG(3, arg4); \ + LSS_LOAD_ARG(0); \ + LSS_LOAD_ARG(1); \ + LSS_LOAD_ARG(2); \ + LSS_LOAD_ARG(3); \ + LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \ + } + #undef _syscall5 + #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_SAVE_ARG(0, arg1); \ + LSS_SAVE_ARG(1, arg2); \ + LSS_SAVE_ARG(2, arg3); \ + LSS_SAVE_ARG(3, arg4); \ + LSS_REG(4, arg5); \ + LSS_LOAD_ARG(0); \ + LSS_LOAD_ARG(1); \ + LSS_LOAD_ARG(2); \ + LSS_LOAD_ARG(3); \ + LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ + "r"(__r4)); \ + } + #undef _syscall6 + #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_SAVE_ARG(0, arg1); \ + LSS_SAVE_ARG(1, arg2); \ + LSS_SAVE_ARG(2, arg3); \ + LSS_SAVE_ARG(3, arg4); \ + LSS_REG(4, arg5); \ + LSS_REG(5, arg6); \ + LSS_LOAD_ARG(0); \ + LSS_LOAD_ARG(1); \ + LSS_LOAD_ARG(2); \ + LSS_LOAD_ARG(3); \ + LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ + "r"(__r4), "r"(__r5)); \ + } + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + register long __res __asm__("r5"); + { + if (fn == NULL || child_stack == NULL) { + __res = -EINVAL; + goto clone_exit; + } + + /* stash first 4 arguments on stack first because we can only load + * them after all function calls. + */ + int tmp_flags = flags; + int * tmp_stack = (int*) child_stack; + void * tmp_ptid = parent_tidptr; + void * tmp_tls = newtls; + + register int *__ctid __asm__("r4") = child_tidptr; + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + *(--tmp_stack) = (int) arg; + *(--tmp_stack) = (int) fn; + + /* We must load r0..r3 last after all possible function calls. */ + register int __flags __asm__("r0") = tmp_flags; + register void *__stack __asm__("r1") = tmp_stack; + register void *__ptid __asm__("r2") = tmp_ptid; + register void *__tls __asm__("r3") = tmp_tls; + + /* %r0 = syscall(%r0 = flags, + * %r1 = child_stack, + * %r2 = parent_tidptr, + * %r3 = newtls, + * %r4 = child_tidptr) + */ + __SYS_REG(clone) + __asm__ __volatile__(/* %r0 = syscall(%r0 = flags, + * %r1 = child_stack, + * %r2 = parent_tidptr, + * %r3 = newtls, + * %r4 = child_tidptr) + */ + "push {r7}\n" + "mov r7,%1\n" + __syscall(clone)"\n" + + /* if (%r0 != 0) + * return %r0; + */ + "movs %0,r0\n" + "bne 1f\n" + + /* In the child, now. Call "fn(arg)". + */ + "ldr r0,[sp, #4]\n" + "mov lr,pc\n" + "ldr pc,[sp]\n" + + /* Call _exit(%r0), which never returns. We only + * need to set r7 for EABI syscall ABI but we do + * this always to simplify code sharing between + * old and new syscall ABIs. + */ + "mov r7,%2\n" + __syscall(exit)"\n" + + /* Pop r7 from the stack only in the parent. + */ + "1: pop {r7}\n" + : "=r" (__res) + : "r"(__sysreg), + "i"(__NR_exit), "r"(__stack), "r"(__flags), + "r"(__ptid), "r"(__tls), "r"(__ctid) + : "cc", "lr", "memory"); + } + clone_exit: + LSS_RETURN(int, __res); + } + #elif defined(__mips__) + #undef LSS_REG + #define LSS_REG(r,a) register unsigned long __r##r __asm__("$"#r) = \ + (unsigned long)(a) + + #if _MIPS_SIM == _MIPS_SIM_ABI32 + // See http://sources.redhat.com/ml/libc-alpha/2004-10/msg00050.html + // or http://www.linux-mips.org/archives/linux-mips/2004-10/msg00142.html + #define MIPS_SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12",\ + "$13", "$14", "$15", "$24", "$25", "memory" + #else + #define MIPS_SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" + #endif + + #undef LSS_BODY + #define LSS_BODY(type,name,r7,...) \ + register unsigned long __v0 __asm__("$2") = __NR_##name; \ + __asm__ __volatile__ ("syscall\n" \ + : "=&r"(__v0), r7 (__r7) \ + : "0"(__v0), ##__VA_ARGS__ \ + : MIPS_SYSCALL_CLOBBERS); \ + LSS_RETURN(type, __v0, __r7) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)() { \ + register unsigned long __r7 __asm__("$7"); \ + LSS_BODY(type, name, "=r"); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + register unsigned long __r7 __asm__("$7"); \ + LSS_REG(4, arg1); LSS_BODY(type, name, "=r", "r"(__r4)); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + register unsigned long __r7 __asm__("$7"); \ + LSS_REG(4, arg1); LSS_REG(5, arg2); \ + LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + register unsigned long __r7 __asm__("$7"); \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \ + } + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_REG(7, arg4); \ + LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \ + } + #undef _syscall5 + #if _MIPS_SIM == _MIPS_SIM_ABI32 + /* The old 32bit MIPS system call API passes the fifth and sixth argument + * on the stack, whereas the new APIs use registers "r8" and "r9". + */ + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_REG(7, arg4); \ + register unsigned long __v0 __asm__("$2"); \ + __asm__ __volatile__ (".set noreorder\n" \ + "lw $2, %6\n" \ + "subu $29, 32\n" \ + "sw $2, 16($29)\n" \ + "li $2, %2\n" \ + "syscall\n" \ + "addiu $29, 32\n" \ + ".set reorder\n" \ + : "=&r"(__v0), "+r" (__r7) \ + : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ + "r"(__r6), "m" ((unsigned long)arg5) \ + : MIPS_SYSCALL_CLOBBERS); \ + LSS_RETURN(type, __v0, __r7); \ + } + #else + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_REG(7, arg4); LSS_REG(8, arg5); \ + LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ + "r"(__r8)); \ + } + #endif + #undef _syscall6 + #if _MIPS_SIM == _MIPS_SIM_ABI32 + /* The old 32bit MIPS system call API passes the fifth and sixth argument + * on the stack, whereas the new APIs use registers "r8" and "r9". + */ + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_REG(7, arg4); \ + register unsigned long __v0 __asm__("$2"); \ + __asm__ __volatile__ (".set noreorder\n" \ + "lw $2, %6\n" \ + "lw $8, %7\n" \ + "subu $29, 32\n" \ + "sw $2, 16($29)\n" \ + "sw $8, 20($29)\n" \ + "li $2, %2\n" \ + "syscall\n" \ + "addiu $29, 32\n" \ + ".set reorder\n" \ + : "=&r"(__v0), "+r" (__r7) \ + : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ + "r"(__r6), "m" ((unsigned long)arg5), \ + "m" ((unsigned long)arg6) \ + : MIPS_SYSCALL_CLOBBERS); \ + LSS_RETURN(type, __v0, __r7); \ + } + #else + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5,type6 arg6) { \ + LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ + LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6); \ + LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ + "r"(__r8), "r"(__r9)); \ + } + #endif + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + register unsigned long __v0 __asm__("$2"); + register unsigned long __r7 __asm__("$7") = (unsigned long)newtls; + { + register int __flags __asm__("$4") = flags; + register void *__stack __asm__("$5") = child_stack; + register void *__ptid __asm__("$6") = parent_tidptr; + register int *__ctid __asm__("$8") = child_tidptr; + __asm__ __volatile__( + #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 + "subu $29,24\n" + #elif _MIPS_SIM == _MIPS_SIM_NABI32 + "sub $29,16\n" + #else + "dsubu $29,16\n" + #endif + + /* if (fn == NULL || child_stack == NULL) + * return -EINVAL; + */ + "li %0,%2\n" + "beqz %5,1f\n" + "beqz %6,1f\n" + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 + "subu %6,32\n" + "sw %5,0(%6)\n" + "sw %8,4(%6)\n" + #elif _MIPS_SIM == _MIPS_SIM_NABI32 + "sub %6,32\n" + "sw %5,0(%6)\n" + "sw %8,8(%6)\n" + #else + "dsubu %6,32\n" + "sd %5,0(%6)\n" + "sd %8,8(%6)\n" + #endif + + /* $7 = syscall($4 = flags, + * $5 = child_stack, + * $6 = parent_tidptr, + * $7 = newtls, + * $8 = child_tidptr) + */ + "li $2,%3\n" + "syscall\n" + + /* if ($7 != 0) + * return $2; + */ + "bnez $7,1f\n" + "bnez $2,1f\n" + + /* In the child, now. Call "fn(arg)". + */ + #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 + "lw $25,0($29)\n" + "lw $4,4($29)\n" + #elif _MIPS_SIM == _MIPS_SIM_NABI32 + "lw $25,0($29)\n" + "lw $4,8($29)\n" + #else + "ld $25,0($29)\n" + "ld $4,8($29)\n" + #endif + "jalr $25\n" + + /* Call _exit($2) + */ + "move $4,$2\n" + "li $2,%4\n" + "syscall\n" + + "1:\n" + #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 + "addu $29, 24\n" + #elif _MIPS_SIM == _MIPS_SIM_NABI32 + "add $29, 16\n" + #else + "daddu $29,16\n" + #endif + : "=&r" (__v0), "=r" (__r7) + : "i"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), + "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), + "r"(__ptid), "r"(__r7), "r"(__ctid) + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$24", "memory"); + } + LSS_RETURN(int, __v0, __r7); + } + #elif defined (__PPC__) + #undef LSS_LOADARGS_0 + #define LSS_LOADARGS_0(name, dummy...) \ + __sc_0 = __NR_##name + #undef LSS_LOADARGS_1 + #define LSS_LOADARGS_1(name, arg1) \ + LSS_LOADARGS_0(name); \ + __sc_3 = (unsigned long) (arg1) + #undef LSS_LOADARGS_2 + #define LSS_LOADARGS_2(name, arg1, arg2) \ + LSS_LOADARGS_1(name, arg1); \ + __sc_4 = (unsigned long) (arg2) + #undef LSS_LOADARGS_3 + #define LSS_LOADARGS_3(name, arg1, arg2, arg3) \ + LSS_LOADARGS_2(name, arg1, arg2); \ + __sc_5 = (unsigned long) (arg3) + #undef LSS_LOADARGS_4 + #define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \ + LSS_LOADARGS_3(name, arg1, arg2, arg3); \ + __sc_6 = (unsigned long) (arg4) + #undef LSS_LOADARGS_5 + #define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ + LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \ + __sc_7 = (unsigned long) (arg5) + #undef LSS_LOADARGS_6 + #define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ + LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ + __sc_8 = (unsigned long) (arg6) + #undef LSS_ASMINPUT_0 + #define LSS_ASMINPUT_0 "0" (__sc_0) + #undef LSS_ASMINPUT_1 + #define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1" (__sc_3) + #undef LSS_ASMINPUT_2 + #define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2" (__sc_4) + #undef LSS_ASMINPUT_3 + #define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3" (__sc_5) + #undef LSS_ASMINPUT_4 + #define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4" (__sc_6) + #undef LSS_ASMINPUT_5 + #define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5" (__sc_7) + #undef LSS_ASMINPUT_6 + #define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6" (__sc_8) + #undef LSS_BODY + #define LSS_BODY(nr, type, name, args...) \ + long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + register unsigned long __sc_8 __asm__ ("r8"); \ + \ + LSS_LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "mfcr %0" \ + : "=&r" (__sc_0), \ + "=&r" (__sc_3), "=&r" (__sc_4), \ + "=&r" (__sc_5), "=&r" (__sc_6), \ + "=&r" (__sc_7), "=&r" (__sc_8) \ + : LSS_ASMINPUT_##nr \ + : "cr0", "ctr", "memory", \ + "r9", "r10", "r11", "r12"); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + LSS_RETURN(type, __sc_ret, __sc_err) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)(void) { \ + LSS_BODY(0, type, name); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_BODY(1, type, name, arg1); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_BODY(2, type, name, arg1, arg2); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_BODY(3, type, name, arg1, arg2, arg3); \ + } + #undef _syscall4 + #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \ + } + #undef _syscall5 + #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \ + } + #undef _syscall6 + #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ + } + /* clone function adapted from glibc 2.18 clone.S */ + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long __ret, __err; + { +#if defined(__PPC64__) + +/* Stack frame offsets. */ +#if _CALL_ELF != 2 +#define FRAME_MIN_SIZE 112 +#define FRAME_TOC_SAVE 40 +#else +#define FRAME_MIN_SIZE 32 +#define FRAME_TOC_SAVE 24 +#endif + + + register int (*__fn)(void *) __asm__ ("r3") = fn; + register void *__cstack __asm__ ("r4") = child_stack; + register int __flags __asm__ ("r5") = flags; + register void * __arg __asm__ ("r6") = arg; + register int * __ptidptr __asm__ ("r7") = parent_tidptr; + register void * __newtls __asm__ ("r8") = newtls; + register int * __ctidptr __asm__ ("r9") = child_tidptr; + __asm__ __volatile__( + /* check for fn == NULL + * and child_stack == NULL + */ + "cmpdi cr0, %6, 0\n\t" + "cmpdi cr1, %7, 0\n\t" + "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" + "beq- cr0, 1f\n\t" + + /* set up stack frame for child */ + "clrrdi %7, %7, 4\n\t" + "li 0, 0\n\t" + "stdu 0, -%13(%7)\n\t" + + /* fn, arg, child_stack are saved acrVoss the syscall */ + "mr 28, %6\n\t" + "mr 29, %7\n\t" + "mr 27, %9\n\t" + + /* syscall + r3 == flags + r4 == child_stack + r5 == parent_tidptr + r6 == newtls + r7 == child_tidptr */ + "mr 3, %8\n\t" + "mr 5, %10\n\t" + "mr 6, %11\n\t" + "mr 7, %12\n\t" + "li 0, %4\n\t" + "sc\n\t" + + /* Test if syscall was successful */ + "cmpdi cr1, 3, 0\n\t" + "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" + "bne- cr1, 1f\n\t" + + /* Do the function call */ + "std 2, %14(1)\n\t" +#if _CALL_ELF != 2 + "ld 0, 0(28)\n\t" + "ld 2, 8(28)\n\t" + "mtctr 0\n\t" +#else + "mr 12, 28\n\t" + "mtctr 12\n\t" +#endif + "mr 3, 27\n\t" + "bctrl\n\t" + "ld 2, %14(1)\n\t" + + /* Call _exit(r3) */ + "li 0, %5\n\t" + "sc\n\t" + + /* Return to parent */ + "1:\n\t" + "mr %0, 3\n\t" + : "=r" (__ret), "=r" (__err) + : "0" (-1), "i" (EINVAL), + "i" (__NR_clone), "i" (__NR_exit), + "r" (__fn), "r" (__cstack), "r" (__flags), + "r" (__arg), "r" (__ptidptr), "r" (__newtls), + "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE) + : "cr0", "cr1", "memory", "ctr", + "r0", "r29", "r27", "r28"); +#else + register int (*__fn)(void *) __asm__ ("r8") = fn; + register void *__cstack __asm__ ("r4") = child_stack; + register int __flags __asm__ ("r3") = flags; + register void * __arg __asm__ ("r9") = arg; + register int * __ptidptr __asm__ ("r5") = parent_tidptr; + register void * __newtls __asm__ ("r6") = newtls; + register int * __ctidptr __asm__ ("r7") = child_tidptr; + __asm__ __volatile__( + /* check for fn == NULL + * and child_stack == NULL + */ + "cmpwi cr0, %6, 0\n\t" + "cmpwi cr1, %7, 0\n\t" + "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" + "beq- cr0, 1f\n\t" + + /* set up stack frame for child */ + "clrrwi %7, %7, 4\n\t" + "li 0, 0\n\t" + "stwu 0, -16(%7)\n\t" + + /* fn, arg, child_stack are saved across the syscall: r28-30 */ + "mr 28, %6\n\t" + "mr 29, %7\n\t" + "mr 27, %9\n\t" + + /* syscall */ + "li 0, %4\n\t" + /* flags already in r3 + * child_stack already in r4 + * ptidptr already in r5 + * newtls already in r6 + * ctidptr already in r7 + */ + "sc\n\t" + + /* Test if syscall was successful */ + "cmpwi cr1, 3, 0\n\t" + "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" + "bne- cr1, 1f\n\t" + + /* Do the function call */ + "mtctr 28\n\t" + "mr 3, 27\n\t" + "bctrl\n\t" + + /* Call _exit(r3) */ + "li 0, %5\n\t" + "sc\n\t" + + /* Return to parent */ + "1:\n" + "mfcr %1\n\t" + "mr %0, 3\n\t" + : "=r" (__ret), "=r" (__err) + : "0" (-1), "1" (EINVAL), + "i" (__NR_clone), "i" (__NR_exit), + "r" (__fn), "r" (__cstack), "r" (__flags), + "r" (__arg), "r" (__ptidptr), "r" (__newtls), + "r" (__ctidptr) + : "cr0", "cr1", "memory", "ctr", + "r0", "r29", "r27", "r28"); + +#endif + } + LSS_RETURN(int, __ret, __err); + } + #elif defined(__aarch64__) + #undef LSS_REG + #define LSS_REG(r,a) register long __x##r __asm__("x"#r) = (long)a + #undef LSS_BODY + #define LSS_BODY(type,name,args...) \ + register long __res_x0 __asm__("x0"); \ + long __res; \ + __asm__ __volatile__ ("mov x8, %1\n" \ + "svc 0x0\n" \ + : "=r"(__res_x0) \ + : "i"(__NR_##name) , ## args \ + : "x8", "memory"); \ + __res = __res_x0; \ + LSS_RETURN(type, __res) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)(void) { \ + LSS_BODY(type, name); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__x0)); \ + } + #undef _syscall2 + #define _syscall2_long(type, name, svc, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); \ + LSS_BODY(type, svc, "r"(__x0), "r"(__x1)); \ + } + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + _syscall2_long(type, name, name, type1, arg1, type2, arg2) + #undef _syscall3 + #define _syscall3_long(type, name, svc, type1, arg1, type2, arg2, \ + type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "r"(__x2)); \ + } + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + _syscall3_long(type, name, name, type1, arg1, type2, arg2, \ + type3, arg3) + #undef _syscall4 + #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3)); \ + } + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); LSS_REG(4, arg5); \ + LSS_BODY(type, name, "r"(__x0), "r"(__x1), "r"(__x2), "r"(__x3), \ + "r"(__x4)); \ + } + #undef _syscall6 + #define _syscall6_long(type,name,svc,type1,arg1,type2,arg2,type3,arg3, \ + type4,arg4,type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ + LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \ + LSS_BODY(type, svc, "r"(__x0), "r"(__x1), "x"(__x2), "r"(__x3), \ + "r"(__x4), "r"(__x5)); \ + } + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + _syscall6_long(type,name,name,type1,arg1,type2,arg2,type3,arg3, \ + type4,arg4,type5,arg5,type6,arg6) + /* clone function adapted from glibc 2.18 clone.S */ + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long __res; + { + register int (*__fn)(void *) __asm__("x0") = fn; + register void *__stack __asm__("x1") = child_stack; + register int __flags __asm__("x2") = flags; + register void *__arg __asm__("x3") = arg; + register int *__ptid __asm__("x4") = parent_tidptr; + register void *__tls __asm__("x5") = newtls; + register int *__ctid __asm__("x6") = child_tidptr; + __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) + * return -EINVAL; + */ + "cbz x0,1f\n" + "cbz x1,1f\n" + + /* Push "arg" and "fn" onto the stack that will be + * used by the child. + */ + "stp x0,x3, [x1, #-16]!\n" + + "mov x0,x2\n" /* flags */ + "mov x2,x4\n" /* ptid */ + "mov x3,x5\n" /* tls */ + "mov x4,x6\n" /* ctid */ + "mov x8,%9\n" /* clone */ + + "svc 0x0\n" + + /* if (%r0 != 0) + * return %r0; + */ + "cmp x0, #0\n" + "bne 2f\n" + + /* In the child, now. Call "fn(arg)". + */ + "ldp x1, x0, [sp], #16\n" + "blr x1\n" + + /* Call _exit(%r0). + */ + "mov x8, %10\n" + "svc 0x0\n" + "1:\n" + "mov x8, %1\n" + "2:\n" + : "=r" (__res) + : "i"(-EINVAL), + "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), + "r"(__ptid), "r"(__tls), "r"(__ctid), + "i"(__NR_clone), "i"(__NR_exit) + : "x8", "x30", "memory"); + } + LSS_RETURN(int, __res); + } + #elif defined(__s390__) + #undef LSS_REG + #define LSS_REG(r, a) register unsigned long __r##r __asm__("r"#r) = (unsigned long) a + #undef LSS_BODY + #define LSS_BODY(type, name, args...) \ + register unsigned long __nr __asm__("r1") \ + = (unsigned long)(__NR_##name); \ + register long __res_r2 __asm__("r2"); \ + long __res; \ + __asm__ __volatile__ \ + ("svc 0\n\t" \ + : "=d"(__res_r2) \ + : "d"(__nr), ## args \ + : "memory"); \ + __res = __res_r2; \ + LSS_RETURN(type, __res) + #undef _syscall0 + #define _syscall0(type, name) \ + type LSS_NAME(name)(void) { \ + LSS_BODY(type, name); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + LSS_REG(2, arg1); \ + LSS_BODY(type, name, "0"(__r2)); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_REG(2, arg1); LSS_REG(3, arg2); \ + LSS_BODY(type, name, "0"(__r2), "d"(__r3)); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \ + LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4)); \ + } + #undef _syscall4 + #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \ + type4 arg4) { \ + LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \ + LSS_REG(5, arg4); \ + LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \ + "d"(__r5)); \ + } + #undef _syscall5 + #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \ + type4 arg4, type5 arg5) { \ + LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \ + LSS_REG(5, arg4); LSS_REG(6, arg5); \ + LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \ + "d"(__r5), "d"(__r6)); \ + } + #undef _syscall6 + #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \ + type4 arg4, type5 arg5, type6 arg6) { \ + LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \ + LSS_REG(5, arg4); LSS_REG(6, arg5); LSS_REG(7, arg6); \ + LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \ + "d"(__r5), "d"(__r6), "d"(__r7)); \ + } + LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, + int flags, void *arg, int *parent_tidptr, + void *newtls, int *child_tidptr) { + long __ret; + { + register int (*__fn)(void *) __asm__ ("r1") = fn; + register void *__cstack __asm__ ("r2") = child_stack; + register int __flags __asm__ ("r3") = flags; + register void *__arg __asm__ ("r0") = arg; + register int *__ptidptr __asm__ ("r4") = parent_tidptr; + register void *__newtls __asm__ ("r6") = newtls; + register int *__ctidptr __asm__ ("r5") = child_tidptr; + __asm__ __volatile__ ( + #ifndef __s390x__ + /* arg already in r0 */ + "ltr %4, %4\n\t" /* check fn, which is already in r1 */ + "jz 1f\n\t" /* NULL function pointer, return -EINVAL */ + "ltr %5, %5\n\t" /* check child_stack, which is already in r2 */ + "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */ + /* flags already in r3 */ + /* parent_tidptr already in r4 */ + /* child_tidptr already in r5 */ + /* newtls already in r6 */ + "svc %2\n\t" /* invoke clone syscall */ + "ltr %0,%%r2\n\t" /* load return code into __ret and test */ + "jnz 1f\n\t" /* return to parent if non-zero */ + /* start child thread */ + "lr %%r2, %7\n\t" /* set first parameter to void *arg */ + "ahi %%r15, -96\n\t" /* make room on the stack for the save area */ + "xc 0(4,%%r15), 0(%%r15)\n\t" + "basr %%r14, %4\n\t" /* jump to fn */ + "svc %3\n" /* invoke exit syscall */ + "1:\n" + #else + /* arg already in r0 */ + "ltgr %4, %4\n\t" /* check fn, which is already in r1 */ + "jz 1f\n\t" /* NULL function pointer, return -EINVAL */ + "ltgr %5, %5\n\t" /* check child_stack, which is already in r2 */ + "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */ + /* flags already in r3 */ + /* parent_tidptr already in r4 */ + /* child_tidptr already in r5 */ + /* newtls already in r6 */ + "svc %2\n\t" /* invoke clone syscall */ + "ltgr %0, %%r2\n\t" /* load return code into __ret and test */ + "jnz 1f\n\t" /* return to parent if non-zero */ + /* start child thread */ + "lgr %%r2, %7\n\t" /* set first parameter to void *arg */ + "aghi %%r15, -160\n\t" /* make room on the stack for the save area */ + "xc 0(8,%%r15), 0(%%r15)\n\t" + "basr %%r14, %4\n\t" /* jump to fn */ + "svc %3\n" /* invoke exit syscall */ + "1:\n" + #endif + : "=r" (__ret) + : "0" (-EINVAL), "i" (__NR_clone), "i" (__NR_exit), + "d" (__fn), "d" (__cstack), "d" (__flags), "d" (__arg), + "d" (__ptidptr), "d" (__newtls), "d" (__ctidptr) + : "cc", "r14", "memory" + ); + } + LSS_RETURN(int, __ret); + } + #elif defined(__riscv) + #undef LSS_REG + #define LSS_REG(r,a) register long __a##r __asm__("a"#r) = \ + (long)(a) + + #undef LSS_BODY + #define LSS_BODY(type, name, args...) \ + register long __a7 __asm__("a7") = __NR_##name; \ + long __res; \ + __asm__ __volatile__ ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), ##args \ + : "memory"); \ + __res = __a0; \ + LSS_RETURN(type, __res) + #undef _syscall0 + #define _syscall0(type,name) \ + type LSS_NAME(name)() { \ + register long __a7 __asm__("a7") = __NR_##name; \ + register long __a0 __asm__("a0"); \ + long __res; \ + __asm__ __volatile__ ( \ + "scall\n\t" \ + : "=r" (__a0) \ + : "r" (__a7) \ + : "memory"); \ + __res = __a0; \ + LSS_RETURN(type, __res); \ + } + #undef _syscall1 + #define _syscall1(type, name, type1, arg1) \ + type LSS_NAME(name)(type1 arg1) { \ + /* There is no need for using a volatile temp. */ \ + LSS_REG(0, arg1); \ + LSS_BODY(type, name); \ + } + #undef _syscall2 + #define _syscall2(type, name, type1, arg1, type2, arg2) \ + type LSS_NAME(name)(type1 arg1, type2 arg2) { \ + LSS_REG(0, arg1); \ + LSS_REG(1, arg2); \ + LSS_BODY(type, name, "r"(__a1)); \ + } + #undef _syscall3 + #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ + LSS_REG(0, arg1); \ + LSS_REG(1, arg2); \ + LSS_REG(2, arg3); \ + LSS_BODY(type, name, "r"(__a1), "r"(__a2)); \ + } + #undef _syscall4 + #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + LSS_REG(0, arg1); \ + LSS_REG(1, arg2); \ + LSS_REG(2, arg3); \ + LSS_REG(3, arg4); \ + LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3)); \ + } + #undef _syscall5 + #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) { \ + LSS_REG(0, arg1); \ + LSS_REG(1, arg2); \ + LSS_REG(2, arg3); \ + LSS_REG(3, arg4); \ + LSS_REG(4, arg5); \ + LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4)); \ + } + #undef _syscall6 + #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ + type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) { \ + LSS_REG(0, arg1); \ + LSS_REG(1, arg2); \ + LSS_REG(2, arg3); \ + LSS_REG(3, arg4); \ + LSS_REG(4, arg5); \ + LSS_REG(5, arg6); \ + LSS_BODY(type, name, "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), \ + "r"(__a5)); \ + } + #endif + #define __NR__exit __NR_exit + #define __NR__gettid __NR_gettid + #define __NR__mremap __NR_mremap + LSS_INLINE _syscall1(int, close, int, f) + LSS_INLINE _syscall1(int, _exit, int, e) +#if defined(__aarch64__) && defined (__ILP32__) + /* aarch64_ilp32 uses fcntl64 for sys_fcntl() */ + LSS_INLINE _syscall3_long(int, fcntl, fcntl64, int, f, + int, c, long, a) +#else + LSS_INLINE _syscall3(int, fcntl, int, f, + int, c, long, a) +#endif +#if defined(__aarch64__) && defined (__ILP32__) + /* aarch64_ilp32 uses fstat64 for sys_fstat() */ + LSS_INLINE _syscall2_long(int, fstat, fstat64, int, f, + struct kernel_stat*, b) +#else + LSS_INLINE _syscall2(int, fstat, int, f, + struct kernel_stat*, b) +#endif + LSS_INLINE _syscall6(int, futex, int*, a, + int, o, int, v, + struct kernel_timespec*, t, + int*, a2, + int, v3) +#ifdef __NR_getdents64 + LSS_INLINE _syscall3(int, getdents64, int, f, + struct kernel_dirent64*, d, int, c) +#define KERNEL_DIRENT kernel_dirent64 +#define GETDENTS sys_getdents64 +#else + LSS_INLINE _syscall3(int, getdents, int, f, + struct kernel_dirent*, d, int, c) +#define KERNEL_DIRENT kernel_dirent +#define GETDENTS sys_getdents +#endif + LSS_INLINE _syscall0(pid_t, getpid) + LSS_INLINE _syscall0(pid_t, getppid) + LSS_INLINE _syscall0(pid_t, _gettid) + LSS_INLINE _syscall2(int, kill, pid_t, p, + int, s) + #if defined(__x86_64__) + /* Need to make sure off_t isn't truncated to 32-bits under x32. */ + LSS_INLINE off_t LSS_NAME(lseek)(int f, off_t o, int w) { + _LSS_BODY(3, off_t, lseek, off_t, LSS_SYSCALL_ARG(f), (uint64_t)(o), + LSS_SYSCALL_ARG(w)); + } + #elif defined(__aarch64__) && defined (__ILP32__) + /* aarch64_ilp32 uses llseek for sys_lseek() */ + LSS_INLINE _syscall3_long(off_t, lseek, llseek, int, f, + off_t, o, int, w) + #else + LSS_INLINE _syscall3(off_t, lseek, int, f, + off_t, o, int, w) + #endif + LSS_INLINE _syscall2(int, munmap, void*, s, + size_t, l) + LSS_INLINE _syscall5(void*, _mremap, void*, o, + size_t, os, size_t, ns, + unsigned long, f, void *, a) + LSS_INLINE _syscall2(int, prctl, int, o, + long, a) + LSS_INLINE _syscall4(long, ptrace, int, r, + pid_t, p, void *, a, void *, d) + LSS_INLINE _syscall3(ssize_t, read, int, f, + void *, b, size_t, c) + LSS_INLINE _syscall4(int, rt_sigaction, int, s, + const struct kernel_sigaction*, a, + struct kernel_sigaction*, o, size_t, c) + LSS_INLINE _syscall4(int, rt_sigprocmask, int, h, + const struct kernel_sigset_t*, s, + struct kernel_sigset_t*, o, size_t, c); + LSS_INLINE _syscall0(int, sched_yield) + LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s, + const stack_t*, o) + #if defined(__NR_fstatat) + LSS_INLINE _syscall4(int, fstatat, int, d, const char *, p, + struct kernel_stat*, b, int, flags) + LSS_INLINE int LSS_NAME(stat)(const char* p, struct kernel_stat* b) { + return LSS_NAME(fstatat)(AT_FDCWD,p,b,0); + } + #else + LSS_INLINE _syscall2(int, stat, const char*, f, + struct kernel_stat*, b) + #endif + LSS_INLINE _syscall3(ssize_t, write, int, f, + const void *, b, size_t, c) + #if defined(__NR_getcpu) + LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu, + unsigned *, node, void *, unused); + #endif + #if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) + LSS_INLINE _syscall3(int, socket, int, d, + int, t, int, p) + #endif + #if defined(__x86_64__) || defined(__s390x__) + LSS_INLINE int LSS_NAME(sigaction)(int signum, + const struct kernel_sigaction *act, + struct kernel_sigaction *oldact) { + #if defined(__x86_64__) + /* On x86_64, the kernel requires us to always set our own + * SA_RESTORER in order to be able to return from a signal handler. + * This function must have a "magic" signature that the "gdb" + * (and maybe the kernel?) can recognize. + */ + if (act != NULL && !(act->sa_flags & SA_RESTORER)) { + struct kernel_sigaction a = *act; + a.sa_flags |= SA_RESTORER; + a.sa_restorer = LSS_NAME(restore_rt)(); + return LSS_NAME(rt_sigaction)(signum, &a, oldact, + (KERNEL_NSIG+7)/8); + } else + #endif + return LSS_NAME(rt_sigaction)(signum, act, oldact, + (KERNEL_NSIG+7)/8); + } + + LSS_INLINE int LSS_NAME(sigprocmask)(int how, + const struct kernel_sigset_t *set, + struct kernel_sigset_t *oldset) { + return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); + } + #endif + #if (defined(__aarch64__)) || \ + (defined(__mips__) \ + && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)) + LSS_INLINE int LSS_NAME(sigaction)(int signum, + const struct kernel_sigaction *act, + struct kernel_sigaction *oldact) { + return LSS_NAME(rt_sigaction)(signum, act, oldact, (KERNEL_NSIG+7)/8); + + } + LSS_INLINE int LSS_NAME(sigprocmask)(int how, + const struct kernel_sigset_t *set, + struct kernel_sigset_t *oldset) { + return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); + } + #endif + #ifdef __NR_wait4 + LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, + int*, s, int, o, + struct kernel_rusage*, r) + LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){ + return LSS_NAME(wait4)(pid, status, options, 0); + } + #else + LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, + int*, s, int, o) + #endif + #ifdef __NR_openat + LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m) + LSS_INLINE int LSS_NAME(open)(const char* p, int f, int m) { + return LSS_NAME(openat)(AT_FDCWD,p,f,m ); + } + #else + LSS_INLINE _syscall3(int, open, const char*, p, + int, f, int, m) + #endif + LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) { + memset(&set->sig, 0, sizeof(set->sig)); + return 0; + } + + LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) { + memset(&set->sig, -1, sizeof(set->sig)); + return 0; + } + + LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set, + int signum) { + if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { + LSS_ERRNO = EINVAL; + return -1; + } else { + set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] + |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0]))); + return 0; + } + } + + LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set, + int signum) { + if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { + LSS_ERRNO = EINVAL; + return -1; + } else { + set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] + &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0])))); + return 0; + } + } + + #if defined(__i386__) || \ + defined(__arm__) || \ + (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \ + defined(__PPC__) || \ + (defined(__s390__) && !defined(__s390x__)) + #define __NR__sigaction __NR_sigaction + #define __NR__sigprocmask __NR_sigprocmask + LSS_INLINE _syscall2(int, fstat64, int, f, + struct kernel_stat64 *, b) + LSS_INLINE _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, + loff_t *, res, uint, wh) +#if defined(__s390__) && !defined(__s390x__) + /* On s390, mmap2() arguments are passed in memory. */ + LSS_INLINE void* LSS_NAME(_mmap2)(void *s, size_t l, int p, int f, int d, + off_t o) { + unsigned long buf[6] = { (unsigned long) s, (unsigned long) l, + (unsigned long) p, (unsigned long) f, + (unsigned long) d, (unsigned long) o }; + LSS_REG(2, buf); + LSS_BODY(void*, mmap2, "0"(__r2)); + } +#elif !defined(__PPC64__) + #define __NR__mmap2 __NR_mmap2 + LSS_INLINE _syscall6(void*, _mmap2, void*, s, + size_t, l, int, p, + int, f, int, d, + off_t, o) +#endif + LSS_INLINE _syscall3(int, _sigaction, int, s, + const struct kernel_old_sigaction*, a, + struct kernel_old_sigaction*, o) + LSS_INLINE _syscall3(int, _sigprocmask, int, h, + const unsigned long*, s, + unsigned long*, o) + LSS_INLINE _syscall2(int, stat64, const char *, p, + struct kernel_stat64 *, b) + + LSS_INLINE int LSS_NAME(sigaction)(int signum, + const struct kernel_sigaction *act, + struct kernel_sigaction *oldact) { + int old_errno = LSS_ERRNO; + int rc; + struct kernel_sigaction a; + if (act != NULL) { + a = *act; + #ifdef __i386__ + /* On i386, the kernel requires us to always set our own + * SA_RESTORER when using realtime signals. Otherwise, it does not + * know how to return from a signal handler. This function must have + * a "magic" signature that the "gdb" (and maybe the kernel?) can + * recognize. + * Apparently, a SA_RESTORER is implicitly set by the kernel, when + * using non-realtime signals. + * + * TODO: Test whether ARM needs a restorer + */ + if (!(a.sa_flags & SA_RESTORER)) { + a.sa_flags |= SA_RESTORER; + a.sa_restorer = (a.sa_flags & SA_SIGINFO) + ? LSS_NAME(restore_rt)() : LSS_NAME(restore)(); + } + #endif + } + rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact, + (KERNEL_NSIG+7)/8); + if (rc < 0 && LSS_ERRNO == ENOSYS) { + struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa; + if (!act) { + ptr_a = NULL; + } else { + oa.sa_handler_ = act->sa_handler_; + memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask)); + #ifndef __mips__ + oa.sa_restorer = act->sa_restorer; + #endif + oa.sa_flags = act->sa_flags; + } + if (!oldact) { + ptr_oa = NULL; + } + LSS_ERRNO = old_errno; + rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa); + if (rc == 0 && oldact) { + if (act) { + memcpy(oldact, act, sizeof(*act)); + } else { + memset(oldact, 0, sizeof(*oldact)); + } + oldact->sa_handler_ = ptr_oa->sa_handler_; + oldact->sa_flags = ptr_oa->sa_flags; + memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask)); + #ifndef __mips__ + oldact->sa_restorer = ptr_oa->sa_restorer; + #endif + } + } + return rc; + } + + LSS_INLINE int LSS_NAME(sigprocmask)(int how, + const struct kernel_sigset_t *set, + struct kernel_sigset_t *oldset) { + int olderrno = LSS_ERRNO; + int rc = LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); + if (rc < 0 && LSS_ERRNO == ENOSYS) { + LSS_ERRNO = olderrno; + if (oldset) { + LSS_NAME(sigemptyset)(oldset); + } + rc = LSS_NAME(_sigprocmask)(how, + set ? &set->sig[0] : NULL, + oldset ? &oldset->sig[0] : NULL); + } + return rc; + } + #endif + #if defined(__i386__) || \ + defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \ + (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \ + (defined(__PPC__) && !defined(__PPC64__)) || \ + (defined(__s390__) && !defined(__s390x__)) + /* On these architectures, implement mmap() with mmap2(). */ + LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d, + int64_t o) { + if (o % 4096) { + LSS_ERRNO = EINVAL; + return (void *) -1; + } + return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096)); + } + #elif defined(__s390x__) + /* On s390x, mmap() arguments are passed in memory. */ + LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d, + int64_t o) { + unsigned long buf[6] = { (unsigned long) s, (unsigned long) l, + (unsigned long) p, (unsigned long) f, + (unsigned long) d, (unsigned long) o }; + LSS_REG(2, buf); + LSS_BODY(void*, mmap, "0"(__r2)); + } + #elif defined(__x86_64__) + /* Need to make sure __off64_t isn't truncated to 32-bits under x32. */ + LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d, + int64_t o) { + LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l), + LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f), + LSS_SYSCALL_ARG(d), (uint64_t)(o)); + } + #elif defined(__aarch64__) && defined (__ILP32__) + /* aarch64_ilp32 uses mmap2 for sys_mmap() */ + LSS_INLINE _syscall6_long(void*, mmap, mmap2, void*, addr, size_t, length, + int, prot, int, flags, int, fd, int64_t, offset) + #else + /* Remaining 64-bit architectures. */ + LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot, + int, flags, int, fd, int64_t, offset) + #endif + #if defined(__i386__) || \ + defined(__PPC__) || \ + (defined(__arm__) && !defined(__ARM_EABI__)) || \ + (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \ + defined(__s390__) + + /* See sys_socketcall in net/socket.c in kernel source. + * It de-multiplexes on its first arg and unpacks the arglist + * array in its second arg. + */ + LSS_INLINE _syscall2(int, socketcall, int, c, unsigned long*, a) + + LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { + unsigned long args[3] = { + (unsigned long) domain, + (unsigned long) type, + (unsigned long) protocol + }; + return LSS_NAME(socketcall)(1, args); + } + #elif defined(__ARM_EABI__) + LSS_INLINE _syscall3(int, socket, int, d, + int, t, int, p) + #endif + #if defined(__mips__) + /* sys_pipe() on MIPS has non-standard calling conventions, as it returns + * both file handles through CPU registers. + */ + LSS_INLINE int LSS_NAME(pipe)(int *p) { + register unsigned long __v0 __asm__("$2") = __NR_pipe; + register unsigned long __v1 __asm__("$3"); + register unsigned long __r7 __asm__("$7"); + __asm__ __volatile__ ("syscall\n" + : "=&r"(__v0), "=&r"(__v1), "+r" (__r7) + : "0"(__v0) + : "$8", "$9", "$10", "$11", "$12", + "$13", "$14", "$15", "$24", "memory"); + if (__r7) { + LSS_ERRNO = __v0; + return -1; + } else { + p[0] = __v0; + p[1] = __v1; + return 0; + } + } + #elif defined(__NR_pipe2) + LSS_INLINE _syscall2(int, pipe2, int *, p, + int, f ) + LSS_INLINE int LSS_NAME(pipe)( int * p) { + return LSS_NAME(pipe2)(p, 0); + } + #else + LSS_INLINE _syscall1(int, pipe, int *, p) + #endif + + LSS_INLINE pid_t LSS_NAME(gettid)() { + pid_t tid = LSS_NAME(_gettid)(); + if (tid != -1) { + return tid; + } + return LSS_NAME(getpid)(); + } + + LSS_INLINE void *LSS_NAME(mremap)(void *old_address, size_t old_size, + size_t new_size, int flags, ...) { + va_list ap; + void *new_address, *rc; + va_start(ap, flags); + new_address = va_arg(ap, void *); + rc = LSS_NAME(_mremap)(old_address, old_size, new_size, + flags, new_address); + va_end(ap); + return rc; + } + + LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) { + /* PTRACE_DETACH can sometimes forget to wake up the tracee and it + * then sends job control signals to the real parent, rather than to + * the tracer. We reduce the risk of this happening by starting a + * whole new time slice, and then quickly sending a SIGCONT signal + * right after detaching from the tracee. + */ + int rc, err; + LSS_NAME(sched_yield)(); + rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0); + err = LSS_ERRNO; + LSS_NAME(kill)(pid, SIGCONT); + LSS_ERRNO = err; + return rc; + } +#endif + +#if defined(__cplusplus) && !defined(SYS_CPLUSPLUS) +} +#endif + +#endif +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.cc b/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.cc new file mode 100644 index 000000000..1e7f137bd --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.cc @@ -0,0 +1,707 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2005-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: Markus Gutschke + */ + +#include "base/linuxthreads.h" + +#ifdef THREADS +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "base/linux_syscall_support.h" +#include "base/thread_lister.h" + +#ifndef CLONE_UNTRACED +#define CLONE_UNTRACED 0x00800000 +#endif + + +/* Synchronous signals that should not be blocked while in the lister thread. + */ +static const int sync_signals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS, + SIGXCPU, SIGXFSZ }; + +/* itoa() is not a standard function, and we cannot safely call printf() + * after suspending threads. So, we just implement our own copy. A + * recursive approach is the easiest here. + */ +static char *local_itoa(char *buf, int i) { + if (i < 0) { + *buf++ = '-'; + return local_itoa(buf, -i); + } else { + if (i >= 10) + buf = local_itoa(buf, i/10); + *buf++ = (i%10) + '0'; + *buf = '\000'; + return buf; + } +} + + +/* Wrapper around clone() that runs "fn" on the same stack as the + * caller! Unlike fork(), the cloned thread shares the same address space. + * The caller must be careful to use only minimal amounts of stack until + * the cloned thread has returned. + * There is a good chance that the cloned thread and the caller will share + * the same copy of errno! + */ +#ifdef __GNUC__ +#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3 +/* Try to force this function into a separate stack frame, and make sure + * that arguments are passed on the stack. + */ +static int local_clone (int (*fn)(void *), void *arg, ...) + __attribute__ ((noinline)); +#endif +#endif + +/* To avoid the gap cross page boundaries, increase by the large parge + * size mostly PowerPC system uses. */ +#ifdef __PPC64__ +#define CLONE_STACK_SIZE 65536 +#else +#define CLONE_STACK_SIZE 4096 +#endif + +static int local_clone (int (*fn)(void *), void *arg, ...) { + /* Leave 4kB of gap between the callers stack and the new clone. This + * should be more than sufficient for the caller to call waitpid() until + * the cloned thread terminates. + * + * It is important that we set the CLONE_UNTRACED flag, because newer + * versions of "gdb" otherwise attempt to attach to our thread, and will + * attempt to reap its status codes. This subsequently results in the + * caller hanging indefinitely in waitpid(), waiting for a change in + * status that will never happen. By setting the CLONE_UNTRACED flag, we + * prevent "gdb" from stealing events, but we still expect the thread + * lister to fail, because it cannot PTRACE_ATTACH to the process that + * is being debugged. This is OK and the error code will be reported + * correctly. + */ + return sys_clone(fn, (char *)&arg - CLONE_STACK_SIZE, + CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_UNTRACED, arg, 0, 0, 0); +} + + +/* Local substitute for the atoi() function, which is not necessarily safe + * to call once threads are suspended (depending on whether libc looks up + * locale information, when executing atoi()). + */ +static int local_atoi(const char *s) { + int n = 0; + int neg = *s == '-'; + if (neg) + s++; + while (*s >= '0' && *s <= '9') + n = 10*n + (*s++ - '0'); + return neg ? -n : n; +} + + +/* Re-runs fn until it doesn't cause EINTR + */ +#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) + + +/* Wrap a class around system calls, in order to give us access to + * a private copy of errno. This only works in C++, but it has the + * advantage of not needing nested functions, which are a non-standard + * language extension. + */ +#ifdef __cplusplus +namespace { + class SysCalls { + public: + #define SYS_CPLUSPLUS + #define SYS_ERRNO my_errno + #define SYS_INLINE inline + #define SYS_PREFIX -1 + #undef SYS_LINUX_SYSCALL_SUPPORT_H + #include "linux_syscall_support.h" + SysCalls() : my_errno(0) { } + int my_errno; + }; +} +#define ERRNO sys.my_errno +#else +#define ERRNO my_errno +#endif + + +/* Wrapper for open() which is guaranteed to never return EINTR. + */ +static int c_open(const char *fname, int flags, int mode) { + ssize_t rc; + NO_INTR(rc = sys_open(fname, flags, mode)); + return rc; +} + + +/* abort() is not safely reentrant, and changes it's behavior each time + * it is called. This means, if the main application ever called abort() + * we cannot safely call it again. This would happen if we were called + * from a SIGABRT signal handler in the main application. So, document + * that calling SIGABRT from the thread lister makes it not signal safe + * (and vice-versa). + * Also, since we share address space with the main application, we + * cannot call abort() from the callback and expect the main application + * to behave correctly afterwards. In fact, the only thing we can do, is + * to terminate the main application with extreme prejudice (aka + * PTRACE_KILL). + * We set up our own SIGABRT handler to do this. + * In order to find the main application from the signal handler, we + * need to store information about it in global variables. This is + * safe, because the main application should be suspended at this + * time. If the callback ever called TCMalloc_ResumeAllProcessThreads(), then + * we are running a higher risk, though. So, try to avoid calling + * abort() after calling TCMalloc_ResumeAllProcessThreads. + */ +static volatile int *sig_pids, sig_num_threads, sig_proc, sig_marker; + + +/* Signal handler to help us recover from dying while we are attached to + * other threads. + */ +static void SignalHandler(int signum, siginfo_t *si, void *data) { + if (sig_pids != NULL) { + if (signum == SIGABRT) { + while (sig_num_threads-- > 0) { + /* Not sure if sched_yield is really necessary here, but it does not */ + /* hurt, and it might be necessary for the same reasons that we have */ + /* to do so in sys_ptrace_detach(). */ + sys_sched_yield(); + sys_ptrace(PTRACE_KILL, sig_pids[sig_num_threads], 0, 0); + } + } else if (sig_num_threads > 0) { + TCMalloc_ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids); + } + } + sig_pids = NULL; + if (sig_marker >= 0) + NO_INTR(sys_close(sig_marker)); + sig_marker = -1; + if (sig_proc >= 0) + NO_INTR(sys_close(sig_proc)); + sig_proc = -1; + + sys__exit(signum == SIGABRT ? 1 : 2); +} + + +/* Try to dirty the stack, and hope that the compiler is not smart enough + * to optimize this function away. Or worse, the compiler could inline the + * function and permanently allocate the data on the stack. + */ +static void DirtyStack(size_t amount) { + char buf[amount]; + memset(buf, 0, amount); + sys_read(-1, buf, amount); +} + + +/* Data structure for passing arguments to the lister thread. + */ +#define ALT_STACKSIZE (MINSIGSTKSZ + 4096) + +struct ListerParams { + int result, err; + char *altstack_mem; + ListAllProcessThreadsCallBack callback; + void *parameter; + va_list ap; + sem_t *lock; +}; + + +static void ListerThread(struct ListerParams *args) { + int found_parent = 0; + pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); + char proc_self_task[80], marker_name[48], *marker_path; + const char *proc_paths[3]; + const char *const *proc_path = proc_paths; + int proc = -1, marker = -1, num_threads = 0; + int max_threads = 0, sig; + struct kernel_stat marker_sb, proc_sb; + stack_t altstack; + + /* Wait for parent thread to set appropriate permissions + * to allow ptrace activity + */ + if (sem_wait(args->lock) < 0) { + goto failure; + } + + /* Create "marker" that we can use to detect threads sharing the same + * address space and the same file handles. By setting the FD_CLOEXEC flag + * we minimize the risk of misidentifying child processes as threads; + * and since there is still a race condition, we will filter those out + * later, anyway. + */ + if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || + sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { + failure: + args->result = -1; + args->err = errno; + if (marker >= 0) + NO_INTR(sys_close(marker)); + sig_marker = marker = -1; + if (proc >= 0) + NO_INTR(sys_close(proc)); + sig_proc = proc = -1; + sys__exit(1); + } + + /* Compute search paths for finding thread directories in /proc */ + local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); + strcpy(marker_name, proc_self_task); + marker_path = marker_name + strlen(marker_name); + strcat(proc_self_task, "/task/"); + proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ + proc_paths[1] = "/proc/"; /* /proc/ */ + proc_paths[2] = NULL; + + /* Compute path for marker socket in /proc */ + local_itoa(strcpy(marker_path, "/fd/") + 4, marker); + if (sys_stat(marker_name, &marker_sb) < 0) { + goto failure; + } + + /* Catch signals on an alternate pre-allocated stack. This way, we can + * safely execute the signal handler even if we ran out of memory. + */ + memset(&altstack, 0, sizeof(altstack)); + altstack.ss_sp = args->altstack_mem; + altstack.ss_flags = 0; + altstack.ss_size = ALT_STACKSIZE; + sys_sigaltstack(&altstack, (const stack_t *)NULL); + + /* Some kernels forget to wake up traced processes, when the + * tracer dies. So, intercept synchronous signals and make sure + * that we wake up our tracees before dying. It is the caller's + * responsibility to ensure that asynchronous signals do not + * interfere with this function. + */ + sig_marker = marker; + sig_proc = -1; + for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { + struct kernel_sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction_ = SignalHandler; + sys_sigfillset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; + sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); + } + + /* Read process directories in /proc/... */ + for (;;) { + /* Some kernels know about threads, and hide them in "/proc" + * (although they are still there, if you know the process + * id). Threads are moved into a separate "task" directory. We + * check there first, and then fall back on the older naming + * convention if necessary. + */ + if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { + if (*++proc_path != NULL) + continue; + goto failure; + } + if (sys_fstat(proc, &proc_sb) < 0) + goto failure; + + /* Since we are suspending threads, we cannot call any libc + * functions that might acquire locks. Most notably, we cannot + * call malloc(). So, we have to allocate memory on the stack, + * instead. Since we do not know how much memory we need, we + * make a best guess. And if we guessed incorrectly we retry on + * a second iteration (by jumping to "detach_threads"). + * + * Unless the number of threads is increasing very rapidly, we + * should never need to do so, though, as our guestimate is very + * conservative. + */ + if (max_threads < proc_sb.st_nlink + 100) + max_threads = proc_sb.st_nlink + 100; + + /* scope */ { + pid_t pids[max_threads]; + int added_entries = 0; + sig_num_threads = num_threads; + sig_pids = pids; + for (;;) { + struct KERNEL_DIRENT *entry; + char buf[4096]; + ssize_t nbytes = GETDENTS(proc, (struct KERNEL_DIRENT *)buf, + sizeof(buf)); + if (nbytes < 0) + goto failure; + else if (nbytes == 0) { + if (added_entries) { + /* Need to keep iterating over "/proc" in multiple + * passes until we no longer find any more threads. This + * algorithm eventually completes, when all threads have + * been suspended. + */ + added_entries = 0; + sys_lseek(proc, 0, SEEK_SET); + continue; + } + break; + } + for (entry = (struct KERNEL_DIRENT *)buf; + entry < (struct KERNEL_DIRENT *)&buf[nbytes]; + entry = (struct KERNEL_DIRENT *)((char *)entry+entry->d_reclen)) { + if (entry->d_ino != 0) { + const char *ptr = entry->d_name; + pid_t pid; + + /* Some kernels hide threads by preceding the pid with a '.' */ + if (*ptr == '.') + ptr++; + + /* If the directory is not numeric, it cannot be a + * process/thread + */ + if (*ptr < '0' || *ptr > '9') + continue; + pid = local_atoi(ptr); + + /* Attach (and suspend) all threads */ + if (pid && pid != clone_pid) { + struct kernel_stat tmp_sb; + char fname[entry->d_reclen + 48]; + strcat(strcat(strcpy(fname, "/proc/"), + entry->d_name), marker_path); + + /* Check if the marker is identical to the one we created */ + if (sys_stat(fname, &tmp_sb) >= 0 && + marker_sb.st_ino == tmp_sb.st_ino) { + long i, j; + + /* Found one of our threads, make sure it is no duplicate */ + for (i = 0; i < num_threads; i++) { + /* Linear search is slow, but should not matter much for + * the typically small number of threads. + */ + if (pids[i] == pid) { + /* Found a duplicate; most likely on second pass */ + goto next_entry; + } + } + + /* Check whether data structure needs growing */ + if (num_threads >= max_threads) { + /* Back to square one, this time with more memory */ + NO_INTR(sys_close(proc)); + goto detach_threads; + } + + /* Attaching to thread suspends it */ + pids[num_threads++] = pid; + sig_num_threads = num_threads; + if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, + (void *)0) < 0) { + /* If operation failed, ignore thread. Maybe it + * just died? There might also be a race + * condition with a concurrent core dumper or + * with a debugger. In that case, we will just + * make a best effort, rather than failing + * entirely. + */ + num_threads--; + sig_num_threads = num_threads; + goto next_entry; + } + while (sys_waitpid(pid, (int *)0, __WALL) < 0) { + if (errno != EINTR) { + sys_ptrace_detach(pid); + num_threads--; + sig_num_threads = num_threads; + goto next_entry; + } + } + + if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || + sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { + /* Address spaces are distinct, even though both + * processes show the "marker". This is probably + * a forked child process rather than a thread. + */ + sys_ptrace_detach(pid); + num_threads--; + sig_num_threads = num_threads; + } else { + found_parent |= pid == ppid; + added_entries++; + } + } + } + } + next_entry:; + } + } + NO_INTR(sys_close(proc)); + sig_proc = proc = -1; + + /* If we failed to find any threads, try looking somewhere else in + * /proc. Maybe, threads are reported differently on this system. + */ + if (num_threads > 1 || !*++proc_path) { + NO_INTR(sys_close(marker)); + sig_marker = marker = -1; + + /* If we never found the parent process, something is very wrong. + * Most likely, we are running in debugger. Any attempt to operate + * on the threads would be very incomplete. Let's just report an + * error to the caller. + */ + if (!found_parent) { + TCMalloc_ResumeAllProcessThreads(num_threads, pids); + sys__exit(3); + } + + /* Now we are ready to call the callback, + * which takes care of resuming the threads for us. + */ + args->result = args->callback(args->parameter, num_threads, + pids, args->ap); + args->err = errno; + + /* Callback should have resumed threads, but better safe than sorry */ + if (TCMalloc_ResumeAllProcessThreads(num_threads, pids)) { + /* Callback forgot to resume at least one thread, report error */ + args->err = EINVAL; + args->result = -1; + } + + sys__exit(0); + } + detach_threads: + /* Resume all threads prior to retrying the operation */ + TCMalloc_ResumeAllProcessThreads(num_threads, pids); + sig_pids = NULL; + num_threads = 0; + sig_num_threads = num_threads; + max_threads += 100; + } + } +} + + +/* This function gets the list of all linux threads of the current process + * passes them to the 'callback' along with the 'parameter' pointer; at the + * call back call time all the threads are paused via + * PTRACE_ATTACH. + * The callback is executed from a separate thread which shares only the + * address space, the filesystem, and the filehandles with the caller. Most + * notably, it does not share the same pid and ppid; and if it terminates, + * the rest of the application is still there. 'callback' is supposed to do + * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if + * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous + * signals are blocked. If the 'callback' decides to unblock them, it must + * ensure that they cannot terminate the application, or that + * TCMalloc_ResumeAllProcessThreads will get called. + * It is an error for the 'callback' to make any library calls that could + * acquire locks. Most notably, this means that most system calls have to + * avoid going through libc. Also, this means that it is not legal to call + * exit() or abort(). + * We return -1 on error and the return value of 'callback' on success. + */ +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...) { + char altstack_mem[ALT_STACKSIZE]; + struct ListerParams args; + pid_t clone_pid; + int dumpable = 1, sig; + struct kernel_sigset_t sig_blocked, sig_old; + sem_t lock; + + va_start(args.ap, callback); + + /* If we are short on virtual memory, initializing the alternate stack + * might trigger a SIGSEGV. Let's do this early, before it could get us + * into more trouble (i.e. before signal handlers try to use the alternate + * stack, and before we attach to other threads). + */ + memset(altstack_mem, 0, sizeof(altstack_mem)); + + /* Some of our cleanup functions could conceivable use more stack space. + * Try to touch the stack right now. This could be defeated by the compiler + * being too smart for it's own good, so try really hard. + */ + DirtyStack(32768); + + /* Make this process "dumpable". This is necessary in order to ptrace() + * after having called setuid(). + */ + dumpable = sys_prctl(PR_GET_DUMPABLE, 0); + if (!dumpable) + sys_prctl(PR_SET_DUMPABLE, 1); + + /* Fill in argument block for dumper thread */ + args.result = -1; + args.err = 0; + args.altstack_mem = altstack_mem; + args.parameter = parameter; + args.callback = callback; + args.lock = &lock; + + /* Before cloning the thread lister, block all asynchronous signals, as we */ + /* are not prepared to handle them. */ + sys_sigfillset(&sig_blocked); + for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { + sys_sigdelset(&sig_blocked, sync_signals[sig]); + } + if (sys_sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old)) { + args.err = errno; + args.result = -1; + goto failed; + } + + /* scope */ { + /* After cloning, both the parent and the child share the same instance + * of errno. We must make sure that at least one of these processes + * (in our case, the parent) uses modified syscall macros that update + * a local copy of errno, instead. + */ + #ifdef __cplusplus + #define sys0_sigprocmask sys.sigprocmask + #define sys0_waitpid sys.waitpid + SysCalls sys; + #else + int my_errno; + #define SYS_ERRNO my_errno + #define SYS_INLINE inline + #define SYS_PREFIX 0 + #undef SYS_LINUX_SYSCALL_SUPPORT_H + #include "linux_syscall_support.h" + #endif + + /* Lock before clone so that parent can set + * ptrace permissions (if necessary) prior + * to ListerThread actually executing + */ + if (sem_init(&lock, 0, 0) == 0) { + + int clone_errno; + clone_pid = local_clone((int (*)(void *))ListerThread, &args); + clone_errno = errno; + + sys_sigprocmask(SIG_SETMASK, &sig_old, &sig_old); + + if (clone_pid >= 0) { +#ifdef PR_SET_PTRACER + /* In newer versions of glibc permission must explicitly + * be given to allow for ptrace. + */ + prctl(PR_SET_PTRACER, clone_pid, 0, 0, 0); +#endif + /* Releasing the lock here allows the + * ListerThread to execute and ptrace us. + */ + sem_post(&lock); + int status, rc; + while ((rc = sys0_waitpid(clone_pid, &status, __WALL)) < 0 && + ERRNO == EINTR) { + /* Keep waiting */ + } + if (rc < 0) { + args.err = ERRNO; + args.result = -1; + } else if (WIFEXITED(status)) { + switch (WEXITSTATUS(status)) { + case 0: break; /* Normal process termination */ + case 2: args.err = EFAULT; /* Some fault (e.g. SIGSEGV) detected */ + args.result = -1; + break; + case 3: args.err = EPERM; /* Process is already being traced */ + args.result = -1; + break; + default:args.err = ECHILD; /* Child died unexpectedly */ + args.result = -1; + break; + } + } else if (!WIFEXITED(status)) { + args.err = EFAULT; /* Terminated due to an unhandled signal*/ + args.result = -1; + } + sem_destroy(&lock); + } else { + args.result = -1; + args.err = clone_errno; + } + } else { + args.result = -1; + args.err = errno; + } + } + + /* Restore the "dumpable" state of the process */ +failed: + if (!dumpable) + sys_prctl(PR_SET_DUMPABLE, dumpable); + + va_end(args.ap); + + errno = args.err; + return args.result; +} + +/* This function resumes the list of all linux threads that + * TCMalloc_ListAllProcessThreads pauses before giving to its callback. + * The function returns non-zero if at least one thread was + * suspended and has now been resumed. + */ +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { + int detached_at_least_one = 0; + while (num_threads-- > 0) { + detached_at_least_one |= sys_ptrace_detach(thread_pids[num_threads]) >= 0; + } + return detached_at_least_one; +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.h b/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.h new file mode 100644 index 000000000..a087628bf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/linuxthreads.h @@ -0,0 +1,55 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2005-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: Markus Gutschke + */ + +#ifndef _LINUXTHREADS_H +#define _LINUXTHREADS_H + +/* Include thread_lister.h to get the interface that we implement for linux. + */ + +/* We currently only support certain platforms on Linux. Porting to other + * related platforms should not be difficult. + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__mips__) || defined(__PPC__) || defined(__aarch64__) || \ + defined(__s390__)) && defined(__linux) + +/* Define the THREADS symbol to make sure that there is exactly one core dumper + * built into the library. + */ +#define THREADS "Linux /proc" + +#endif + +#endif /* _LINUXTHREADS_H */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/logging.cc b/trunk/3rdparty/gperftools-2-fit/src/base/logging.cc new file mode 100644 index 000000000..52d9bd361 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/logging.cc @@ -0,0 +1,108 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// This file just provides storage for FLAGS_verbose. + +#include +#include "base/logging.h" +#include "base/commandlineflags.h" + +DEFINE_int32(verbose, EnvToInt("PERFTOOLS_VERBOSE", 0), + "Set to numbers >0 for more verbose output, or <0 for less. " + "--verbose == -4 means we log fatal errors only."); + + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) + +// While windows does have a POSIX-compatible API +// (_open/_write/_close), it acquires memory. Using this lower-level +// windows API is the closest we can get to being "raw". +RawFD RawOpenForWriting(const char* filename) { + // CreateFile allocates memory if file_name isn't absolute, so if + // that ever becomes a problem then we ought to compute the absolute + // path on its behalf (perhaps the ntdll/kernel function isn't aware + // of the working directory?) + RawFD fd = CreateFileA(filename, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, NULL); + if (fd != kIllegalRawFD && GetLastError() == ERROR_ALREADY_EXISTS) + SetEndOfFile(fd); // truncate the existing file + return fd; +} + +void RawWrite(RawFD handle, const char* buf, size_t len) { + while (len > 0) { + DWORD wrote; + BOOL ok = WriteFile(handle, buf, len, &wrote, NULL); + // We do not use an asynchronous file handle, so ok==false means an error + if (!ok) break; + buf += wrote; + len -= wrote; + } +} + +void RawClose(RawFD handle) { + CloseHandle(handle); +} + +#else // _WIN32 || __CYGWIN__ || __CYGWIN32__ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +// Re-run fn until it doesn't cause EINTR. +#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) + +RawFD RawOpenForWriting(const char* filename) { + return open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664); +} + +void RawWrite(RawFD fd, const char* buf, size_t len) { + while (len > 0) { + ssize_t r; + NO_INTR(r = write(fd, buf, len)); + if (r <= 0) break; + buf += r; + len -= r; + } +} + +void RawClose(RawFD fd) { + NO_INTR(close(fd)); +} + +#endif // _WIN32 || __CYGWIN__ || __CYGWIN32__ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/logging.h b/trunk/3rdparty/gperftools-2-fit/src/base/logging.h new file mode 100644 index 000000000..94b9138c7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/logging.h @@ -0,0 +1,259 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// This file contains #include information about logging-related stuff. +// Pretty much everybody needs to #include this file so that they can +// log various happenings. +// +#ifndef _LOGGING_H_ +#define _LOGGING_H_ + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include // for write() +#endif +#include // for strlen(), strcmp() +#include +#include // 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. +// (In windows, we can't call it because it might call malloc.) +// 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. +#if defined(_MSC_VER) +#define WRITE_TO_STDERR(buf, len) WriteToStderr(buf, len); // in port.cc +#elif defined(HAVE_SYS_SYSCALL_H) +#include +#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 + +// MSVC and mingw define their own, safe version of vnsprintf (the +// windows one in broken) in port.cc. Everyone else can use the +// version here. We had to give it a unique name for windows. +#ifndef _WIN32 +# define perftools_vsnprintf vsnprintf +#endif + + +// We log all messages at this log-level and below. +// INFO == -1, WARNING == -2, ERROR == -3, FATAL == -4 +DECLARE_int32(verbose); + +// CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG, so the check will be executed regardless of +// compilation mode. Therefore, it is safe to do things like: +// 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_TO_STDERR("Check failed: " #condition "\n", \ + sizeof("Check failed: " #condition "\n")-1); \ + abort(); \ + } \ + } while (0) + +// This takes a message to print. The name is historical. +#define RAW_CHECK(condition, message) \ + do { \ + if (!(condition)) { \ + WRITE_TO_STDERR("Check failed: " #condition ": " message "\n", \ + sizeof("Check failed: " #condition ": " message "\n")-1);\ + abort(); \ + } \ + } while (0) + +// This is like RAW_CHECK, but only in debug-mode +#ifdef NDEBUG +enum { DEBUG_MODE = 0 }; +#define RAW_DCHECK(condition, message) +#else +enum { DEBUG_MODE = 1 }; +#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message) +#endif + +// This prints errno as well. Note we use write instead of printf/puts to +// avoid the risk we'll call malloc(). +#define PCHECK(condition) \ + do { \ + if (!(condition)) { \ + const int err_no = errno; \ + 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); \ + abort(); \ + } \ + } while (0) + +// Helper macro for binary operators; prints the two values on error +// Don't use this macro directly in your code, use CHECK_EQ et al below + +// WARNING: These don't compile correctly if one of the arguments is a pointer +// and the other is NULL. To work around this, simply static_cast NULL to the +// type of the desired pointer. + +// TODO(jandrews): Also print the values in case of failure. Requires some +// sort of type-sensitive ToString() function. +#define CHECK_OP(op, val1, val2) \ + do { \ + if (!((val1) op (val2))) { \ + fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \ + abort(); \ + } \ + } while (0) + +#define CHECK_EQ(val1, val2) CHECK_OP(==, val1, val2) +#define CHECK_NE(val1, val2) CHECK_OP(!=, val1, val2) +#define CHECK_LE(val1, val2) CHECK_OP(<=, val1, val2) +#define CHECK_LT(val1, val2) CHECK_OP(< , val1, val2) +#define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2) +#define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2) + +// Synonyms for CHECK_* that are used in some unittests. +#define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2) +#define EXPECT_NE(val1, val2) CHECK_NE(val1, val2) +#define EXPECT_LE(val1, val2) CHECK_LE(val1, val2) +#define EXPECT_LT(val1, val2) CHECK_LT(val1, val2) +#define EXPECT_GE(val1, val2) CHECK_GE(val1, val2) +#define EXPECT_GT(val1, val2) CHECK_GT(val1, val2) +#define ASSERT_EQ(val1, val2) EXPECT_EQ(val1, val2) +#define ASSERT_NE(val1, val2) EXPECT_NE(val1, val2) +#define ASSERT_LE(val1, val2) EXPECT_LE(val1, val2) +#define ASSERT_LT(val1, val2) EXPECT_LT(val1, val2) +#define ASSERT_GE(val1, val2) EXPECT_GE(val1, val2) +#define ASSERT_GT(val1, val2) EXPECT_GT(val1, val2) +// As are these variants. +#define EXPECT_TRUE(cond) CHECK(cond) +#define EXPECT_FALSE(cond) CHECK(!(cond)) +#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0) +#define ASSERT_TRUE(cond) EXPECT_TRUE(cond) +#define ASSERT_FALSE(cond) EXPECT_FALSE(cond) +#define ASSERT_STREQ(a, b) EXPECT_STREQ(a, b) + +// 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) +#define DCHECK_NE(val1, val2) +#define DCHECK_LE(val1, val2) +#define DCHECK_LT(val1, val2) +#define DCHECK_GE(val1, val2) +#define DCHECK_GT(val1, val2) +#else +#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) +#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) +#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) +#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) +#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) +#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) +#endif + + +#ifdef ERROR +#undef ERROR // may conflict with ERROR macro on windows +#endif +enum LogSeverity {INFO = -1, WARNING = -2, ERROR = -3, FATAL = -4}; + +// NOTE: we add a newline to the end of the output if it's not there already +inline void LogPrintf(int severity, const char* pat, va_list ap) { + // We write directly to the stderr file descriptor and avoid FILE + // buffering because that may invoke malloc() + char buf[600]; + perftools_vsnprintf(buf, sizeof(buf)-1, pat, ap); + if (buf[0] != '\0' && buf[strlen(buf)-1] != '\n') { + assert(strlen(buf)+1 < sizeof(buf)); + strcat(buf, "\n"); + } + WRITE_TO_STDERR(buf, strlen(buf)); + if ((severity) == FATAL) + abort(); // LOG(FATAL) indicates a big problem, so don't run atexit() calls +} + +// Note that since the order of global constructors is unspecified, +// global code that calls RAW_LOG may execute before FLAGS_verbose is set. +// Such code will run with verbosity == 0 no matter what. +#define VLOG_IS_ON(severity) (FLAGS_verbose >= severity) + +// In a better world, we'd use __VA_ARGS__, but VC++ 7 doesn't support it. +#define LOG_PRINTF(severity, pat) do { \ + if (VLOG_IS_ON(severity)) { \ + va_list ap; \ + va_start(ap, pat); \ + LogPrintf(severity, pat, ap); \ + va_end(ap); \ + } \ +} while (0) + +// RAW_LOG is the main function; some synonyms are used in unittests. +inline void RAW_LOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); } +inline void RAW_VLOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); } +inline void LOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); } +inline void VLOG(int lvl, const char* pat, ...) { LOG_PRINTF(lvl, pat); } +inline void LOG_IF(int lvl, bool cond, const char* pat, ...) { + if (cond) LOG_PRINTF(lvl, pat); +} + +// This isn't technically logging, but it's also IO and also is an +// attempt to be "raw" -- that is, to not use any higher-level libc +// routines that might allocate memory or (ideally) try to allocate +// locks. We use an opaque file handle (not necessarily an int) +// to allow even more low-level stuff in the future. +// Like other "raw" routines, these functions are best effort, and +// thus don't return error codes (except RawOpenForWriting()). +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) +#ifndef NOMINMAX +#define NOMINMAX // @#!$& windows +#endif +#include +typedef HANDLE RawFD; +const RawFD kIllegalRawFD = INVALID_HANDLE_VALUE; +#else +typedef int RawFD; +const RawFD kIllegalRawFD = -1; // what open returns if it fails +#endif // defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) + +RawFD RawOpenForWriting(const char* filename); // uses default permissions +void RawWrite(RawFD fd, const char* buf, size_t len); +void RawClose(RawFD fd); + +#endif // _LOGGING_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.cc b/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.cc new file mode 100644 index 000000000..db91155ba --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.cc @@ -0,0 +1,580 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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. + */ + +// A low-level allocator that can be used by other low-level +// modules without introducing dependency cycles. +// This allocator is slow and wasteful of memory; +// it should not be used when performance is key. + +#include "base/low_level_alloc.h" +#include "base/dynamic_annotations.h" +#include "base/spinlock.h" +#include "base/logging.h" +#include "malloc_hook-inl.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_MMAP +#include +#endif +#include // for placement-new + +// 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 + +// A first-fit allocator with amortized logarithmic free() time. + +LowLevelAlloc::PagesAllocator::~PagesAllocator() { +} + +// --------------------------------------------------------------------------- +static const int kMaxLevel = 30; + +// We put this class-only struct in a namespace to avoid polluting the +// global namespace with this struct name (thus risking an ODR violation). +namespace low_level_alloc_internal { + // This struct describes one allocated block, or one free block. + struct AllocList { + struct Header { + intptr_t size; // size of entire region, including this field. Must be + // first. Valid in both allocated and unallocated blocks + intptr_t magic; // kMagicAllocated or kMagicUnallocated xor this + LowLevelAlloc::Arena *arena; // pointer to parent arena + void *dummy_for_alignment; // aligns regions to 0 mod 2*sizeof(void*) + } header; + + // Next two fields: in unallocated blocks: freelist skiplist data + // in allocated blocks: overlaps with client data + int levels; // levels in skiplist used + AllocList *next[kMaxLevel]; // actually has levels elements. + // The AllocList node may not have room for + // all kMaxLevel entries. See max_fit in + // LLA_SkiplistLevels() + }; +} +using low_level_alloc_internal::AllocList; + + +// --------------------------------------------------------------------------- +// A trivial skiplist implementation. This is used to keep the freelist +// in address order while taking only logarithmic time per insert and delete. + +// An integer approximation of log2(size/base) +// Requires size >= base. +static int IntLog2(size_t size, size_t base) { + int result = 0; + for (size_t i = size; i > base; i >>= 1) { // i == floor(size/2**result) + result++; + } + // floor(size / 2**result) <= base < floor(size / 2**(result-1)) + // => log2(size/(base+1)) <= result < 1+log2(size/base) + // => result ~= log2(size/base) + return result; +} + +// Return a random integer n: p(n)=1/(2**n) if 1 <= n; p(n)=0 if n < 1. +static int Random() { + static uint32 r = 1; // no locking---it's not critical + int result = 1; + while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) { + result++; + } + return result; +} + +// Return a number of skiplist levels for a node of size bytes, where +// base is the minimum node size. Compute level=log2(size / base)+n +// where n is 1 if random is false and otherwise a random number generated with +// the standard distribution for a skiplist: See Random() above. +// Bigger nodes tend to have more skiplist levels due to the log2(size / base) +// term, so first-fit searches touch fewer nodes. "level" is clipped so +// level max_fit) level = max_fit; + if (level > kMaxLevel-1) level = kMaxLevel - 1; + RAW_CHECK(level >= 1, "block not big enough for even one level"); + return level; +} + +// Return "atleast", the first element of AllocList *head s.t. *atleast >= *e. +// For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater +// points to the last element at level i in the AllocList less than *e, or is +// head if no such element exists. +static AllocList *LLA_SkiplistSearch(AllocList *head, + AllocList *e, AllocList **prev) { + AllocList *p = head; + for (int level = head->levels - 1; level >= 0; level--) { + for (AllocList *n; (n = p->next[level]) != 0 && n < e; p = n) { + } + prev[level] = p; + } + return (head->levels == 0) ? 0 : prev[0]->next[0]; +} + +// Insert element *e into AllocList *head. Set prev[] as LLA_SkiplistSearch. +// Requires that e->levels be previously set by the caller (using +// LLA_SkiplistLevels()) +static void LLA_SkiplistInsert(AllocList *head, AllocList *e, + AllocList **prev) { + LLA_SkiplistSearch(head, e, prev); + for (; head->levels < e->levels; head->levels++) { // extend prev pointers + prev[head->levels] = head; // to all *e's levels + } + for (int i = 0; i != e->levels; i++) { // add element to list + e->next[i] = prev[i]->next[i]; + prev[i]->next[i] = e; + } +} + +// Remove element *e from AllocList *head. Set prev[] as LLA_SkiplistSearch(). +// Requires that e->levels be previous set by the caller (using +// LLA_SkiplistLevels()) +static void LLA_SkiplistDelete(AllocList *head, AllocList *e, + AllocList **prev) { + AllocList *found = LLA_SkiplistSearch(head, e, prev); + RAW_CHECK(e == found, "element not in freelist"); + for (int i = 0; i != e->levels && prev[i]->next[i] == e; i++) { + prev[i]->next[i] = e->next[i]; + } + while (head->levels > 0 && head->next[head->levels - 1] == 0) { + head->levels--; // reduce head->levels if level unused + } +} + +// --------------------------------------------------------------------------- +// Arena implementation + +struct LowLevelAlloc::Arena { + Arena() : mu(SpinLock::LINKER_INITIALIZED) {} // does nothing; for static init + explicit Arena(int) : pagesize(0) {} // set pagesize to zero explicitly + // for non-static init + + SpinLock mu; // protects freelist, allocation_count, + // pagesize, roundup, min_size + AllocList freelist; // head of free list; sorted by addr (under mu) + int32 allocation_count; // count of allocated blocks (under mu) + int32 flags; // flags passed to NewArena (ro after init) + size_t pagesize; // ==getpagesize() (init under mu, then ro) + size_t roundup; // lowest power of 2 >= max(16,sizeof (AllocList)) + // (init under mu, then ro) + size_t min_size; // smallest allocation block size + // (init under mu, then ro) + PagesAllocator *allocator; +}; + +// The default arena, which is used when 0 is passed instead of an Arena +// pointer. +static struct LowLevelAlloc::Arena default_arena; + +// Non-malloc-hooked arenas: used only to allocate metadata for arenas that +// do not want malloc hook reporting, so that for them there's no malloc hook +// reporting even during arena creation. +static struct LowLevelAlloc::Arena unhooked_arena; +static struct LowLevelAlloc::Arena unhooked_async_sig_safe_arena; + +namespace { + + class DefaultPagesAllocator : public LowLevelAlloc::PagesAllocator { + public: + virtual ~DefaultPagesAllocator() {}; + virtual void *MapPages(int32 flags, size_t size); + virtual void UnMapPages(int32 flags, void *addr, size_t size); + }; + +} + +// magic numbers to identify allocated and unallocated blocks +static const intptr_t kMagicAllocated = 0x4c833e95; +static const intptr_t kMagicUnallocated = ~kMagicAllocated; + +namespace { + class SCOPED_LOCKABLE ArenaLock { + public: + explicit ArenaLock(LowLevelAlloc::Arena *arena) + EXCLUSIVE_LOCK_FUNCTION(arena->mu) + : left_(false), mask_valid_(false), arena_(arena) { + if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { + // We've decided not to support async-signal-safe arena use until + // there a demonstrated need. Here's how one could do it though + // (would need to be made more portable). +#if 0 + sigset_t all; + sigfillset(&all); + this->mask_valid_ = + (pthread_sigmask(SIG_BLOCK, &all, &this->mask_) == 0); +#else + RAW_CHECK(false, "We do not yet support async-signal-safe arena."); +#endif + } + this->arena_->mu.Lock(); + } + ~ArenaLock() { RAW_CHECK(this->left_, "haven't left Arena region"); } + void Leave() UNLOCK_FUNCTION() { + this->arena_->mu.Unlock(); +#if 0 + if (this->mask_valid_) { + pthread_sigmask(SIG_SETMASK, &this->mask_, 0); + } +#endif + this->left_ = true; + } + private: + bool left_; // whether left region + bool mask_valid_; +#if 0 + sigset_t mask_; // old mask of blocked signals +#endif + LowLevelAlloc::Arena *arena_; + DISALLOW_COPY_AND_ASSIGN(ArenaLock); + }; +} // anonymous namespace + +// create an appropriate magic number for an object at "ptr" +// "magic" should be kMagicAllocated or kMagicUnallocated +inline static intptr_t Magic(intptr_t magic, AllocList::Header *ptr) { + return magic ^ reinterpret_cast(ptr); +} + +// Initialize the fields of an Arena +static void ArenaInit(LowLevelAlloc::Arena *arena) { + if (arena->pagesize == 0) { + arena->pagesize = getpagesize(); + // Round up block sizes to a power of two close to the header size. + arena->roundup = 16; + while (arena->roundup < sizeof (arena->freelist.header)) { + arena->roundup += arena->roundup; + } + // Don't allocate blocks less than twice the roundup size to avoid tiny + // free blocks. + arena->min_size = 2 * arena->roundup; + arena->freelist.header.size = 0; + arena->freelist.header.magic = + Magic(kMagicUnallocated, &arena->freelist.header); + arena->freelist.header.arena = arena; + arena->freelist.levels = 0; + memset(arena->freelist.next, 0, sizeof (arena->freelist.next)); + arena->allocation_count = 0; + if (arena == &default_arena) { + // Default arena should be hooked, e.g. for heap-checker to trace + // pointer chains through objects in the default arena. + arena->flags = LowLevelAlloc::kCallMallocHook; + } else if (arena == &unhooked_async_sig_safe_arena) { + arena->flags = LowLevelAlloc::kAsyncSignalSafe; + } else { + arena->flags = 0; // other arenas' flags may be overridden by client, + // but unhooked_arena will have 0 in 'flags'. + } + arena->allocator = LowLevelAlloc::GetDefaultPagesAllocator(); + } +} + +// L < meta_data_arena->mu +LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32 flags, + Arena *meta_data_arena) { + return NewArenaWithCustomAlloc(flags, meta_data_arena, NULL); +} + +// L < meta_data_arena->mu +LowLevelAlloc::Arena *LowLevelAlloc::NewArenaWithCustomAlloc(int32 flags, + Arena *meta_data_arena, + PagesAllocator *allocator) { + RAW_CHECK(meta_data_arena != 0, "must pass a valid arena"); + if (meta_data_arena == &default_arena) { + if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { + meta_data_arena = &unhooked_async_sig_safe_arena; + } else if ((flags & LowLevelAlloc::kCallMallocHook) == 0) { + meta_data_arena = &unhooked_arena; + } + } + // Arena(0) uses the constructor for non-static contexts + Arena *result = + new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(0); + ArenaInit(result); + result->flags = flags; + if (allocator) { + result->allocator = allocator; + } + return result; +} + +// L < arena->mu, L < arena->arena->mu +bool LowLevelAlloc::DeleteArena(Arena *arena) { + RAW_CHECK(arena != 0 && arena != &default_arena && arena != &unhooked_arena, + "may not delete default arena"); + ArenaLock section(arena); + bool empty = (arena->allocation_count == 0); + section.Leave(); + if (empty) { + while (arena->freelist.next[0] != 0) { + AllocList *region = arena->freelist.next[0]; + size_t size = region->header.size; + arena->freelist.next[0] = region->next[0]; + RAW_CHECK(region->header.magic == + Magic(kMagicUnallocated, ®ion->header), + "bad magic number in DeleteArena()"); + RAW_CHECK(region->header.arena == arena, + "bad arena pointer in DeleteArena()"); + RAW_CHECK(size % arena->pagesize == 0, + "empty arena has non-page-aligned block size"); + RAW_CHECK(reinterpret_cast(region) % arena->pagesize == 0, + "empty arena has non-page-aligned block"); + int munmap_result; + if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) == 0) { + munmap_result = munmap(region, size); + } else { + munmap_result = MallocHook::UnhookedMUnmap(region, size); + } + RAW_CHECK(munmap_result == 0, + "LowLevelAlloc::DeleteArena: munmap failed address"); + } + Free(arena); + } + return empty; +} + +// --------------------------------------------------------------------------- + +// Return value rounded up to next multiple of align. +// align must be a power of two. +static intptr_t RoundUp(intptr_t addr, intptr_t align) { + return (addr + align - 1) & ~(align - 1); +} + +// Equivalent to "return prev->next[i]" but with sanity checking +// that the freelist is in the correct order, that it +// consists of regions marked "unallocated", and that no two regions +// are adjacent in memory (they should have been coalesced). +// L < arena->mu +static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) { + RAW_CHECK(i < prev->levels, "too few levels in Next()"); + AllocList *next = prev->next[i]; + if (next != 0) { + RAW_CHECK(next->header.magic == Magic(kMagicUnallocated, &next->header), + "bad magic number in Next()"); + RAW_CHECK(next->header.arena == arena, + "bad arena pointer in Next()"); + if (prev != &arena->freelist) { + RAW_CHECK(prev < next, "unordered freelist"); + RAW_CHECK(reinterpret_cast(prev) + prev->header.size < + reinterpret_cast(next), "malformed freelist"); + } + } + return next; +} + +// Coalesce list item "a" with its successor if they are adjacent. +static void Coalesce(AllocList *a) { + AllocList *n = a->next[0]; + if (n != 0 && reinterpret_cast(a) + a->header.size == + reinterpret_cast(n)) { + LowLevelAlloc::Arena *arena = a->header.arena; + a->header.size += n->header.size; + n->header.magic = 0; + n->header.arena = 0; + AllocList *prev[kMaxLevel]; + LLA_SkiplistDelete(&arena->freelist, n, prev); + LLA_SkiplistDelete(&arena->freelist, a, prev); + a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size, true); + LLA_SkiplistInsert(&arena->freelist, a, prev); + } +} + +// Adds block at location "v" to the free list +// L >= arena->mu +static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) { + AllocList *f = reinterpret_cast( + reinterpret_cast(v) - sizeof (f->header)); + RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header), + "bad magic number in AddToFreelist()"); + RAW_CHECK(f->header.arena == arena, + "bad arena pointer in AddToFreelist()"); + f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size, true); + AllocList *prev[kMaxLevel]; + LLA_SkiplistInsert(&arena->freelist, f, prev); + f->header.magic = Magic(kMagicUnallocated, &f->header); + Coalesce(f); // maybe coalesce with successor + Coalesce(prev[0]); // maybe coalesce with predecessor +} + +// Frees storage allocated by LowLevelAlloc::Alloc(). +// L < arena->mu +void LowLevelAlloc::Free(void *v) { + if (v != 0) { + AllocList *f = reinterpret_cast( + reinterpret_cast(v) - sizeof (f->header)); + RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header), + "bad magic number in Free()"); + LowLevelAlloc::Arena *arena = f->header.arena; + if ((arena->flags & kCallMallocHook) != 0) { + MallocHook::InvokeDeleteHook(v); + } + ArenaLock section(arena); + AddToFreelist(v, arena); + RAW_CHECK(arena->allocation_count > 0, "nothing in arena to free"); + arena->allocation_count--; + section.Leave(); + } +} + +// allocates and returns a block of size bytes, to be freed with Free() +// L < arena->mu +static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { + void *result = 0; + if (request != 0) { + AllocList *s; // will point to region that satisfies request + ArenaLock section(arena); + ArenaInit(arena); + // round up with header + size_t req_rnd = RoundUp(request + sizeof (s->header), arena->roundup); + for (;;) { // loop until we find a suitable region + // find the minimum levels that a block of this size must have + int i = LLA_SkiplistLevels(req_rnd, arena->min_size, false) - 1; + if (i < arena->freelist.levels) { // potential blocks exist + AllocList *before = &arena->freelist; // predecessor of s + while ((s = Next(i, before, arena)) != 0 && s->header.size < req_rnd) { + before = s; + } + if (s != 0) { // we found a region + break; + } + } + // we unlock before mmap() both because mmap() may call a callback hook, + // and because it may be slow. + arena->mu.Unlock(); + // mmap generous 64K chunks to decrease + // the chances/impact of fragmentation: + size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16); + void *new_pages = arena->allocator->MapPages(arena->flags, new_pages_size); + arena->mu.Lock(); + s = reinterpret_cast(new_pages); + s->header.size = new_pages_size; + // Pretend the block is allocated; call AddToFreelist() to free it. + s->header.magic = Magic(kMagicAllocated, &s->header); + s->header.arena = arena; + AddToFreelist(&s->levels, arena); // insert new region into free list + } + AllocList *prev[kMaxLevel]; + LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list + // s points to the first free region that's big enough + if (req_rnd + arena->min_size <= s->header.size) { // big enough to split + AllocList *n = reinterpret_cast + (req_rnd + reinterpret_cast(s)); + n->header.size = s->header.size - req_rnd; + n->header.magic = Magic(kMagicAllocated, &n->header); + n->header.arena = arena; + s->header.size = req_rnd; + AddToFreelist(&n->levels, arena); + } + s->header.magic = Magic(kMagicAllocated, &s->header); + RAW_CHECK(s->header.arena == arena, ""); + arena->allocation_count++; + section.Leave(); + result = &s->levels; + } + return result; +} + +void *LowLevelAlloc::Alloc(size_t request) { + void *result = DoAllocWithArena(request, &default_arena); + if ((default_arena.flags & kCallMallocHook) != 0) { + // this call must be directly in the user-called allocator function + // for MallocHook::GetCallerStackTrace to work properly + MallocHook::InvokeNewHook(result, request); + } + return result; +} + +void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) { + RAW_CHECK(arena != 0, "must pass a valid arena"); + void *result = DoAllocWithArena(request, arena); + if ((arena->flags & kCallMallocHook) != 0) { + // this call must be directly in the user-called allocator function + // for MallocHook::GetCallerStackTrace to work properly + MallocHook::InvokeNewHook(result, request); + } + return result; +} + +LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() { + return &default_arena; +} + +static DefaultPagesAllocator *default_pages_allocator; +static union { + char chars[sizeof(DefaultPagesAllocator)]; + void *ptr; +} debug_pages_allocator_space; + +LowLevelAlloc::PagesAllocator *LowLevelAlloc::GetDefaultPagesAllocator(void) { + if (default_pages_allocator) { + return default_pages_allocator; + } + default_pages_allocator = new (debug_pages_allocator_space.chars) DefaultPagesAllocator(); + return default_pages_allocator; +} + +void *DefaultPagesAllocator::MapPages(int32 flags, size_t size) { + void *new_pages; + if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) { + new_pages = MallocHook::UnhookedMMap(0, size, + PROT_WRITE|PROT_READ, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + } else { + new_pages = mmap(0, size, + PROT_WRITE|PROT_READ, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + } + RAW_CHECK(new_pages != MAP_FAILED, "mmap error"); + + return new_pages; +} + +void DefaultPagesAllocator::UnMapPages(int32 flags, void *region, size_t size) { + int munmap_result; + if ((flags & LowLevelAlloc::kAsyncSignalSafe) == 0) { + munmap_result = munmap(region, size); + } else { + munmap_result = MallocHook::UnhookedMUnmap(region, size); + } + RAW_CHECK(munmap_result == 0, + "LowLevelAlloc::DeleteArena: munmap failed address"); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.h b/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.h new file mode 100644 index 000000000..406bfff0c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/low_level_alloc.h @@ -0,0 +1,120 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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. + */ + +#if !defined(_BASE_LOW_LEVEL_ALLOC_H_) +#define _BASE_LOW_LEVEL_ALLOC_H_ + +// A simple thread-safe memory allocator that does not depend on +// mutexes or thread-specific data. It is intended to be used +// sparingly, and only when malloc() would introduce an unwanted +// dependency, such as inside the heap-checker. + +#include +#include // for size_t +#include "base/basictypes.h" + +class LowLevelAlloc { + public: + class PagesAllocator { + public: + virtual ~PagesAllocator(); + virtual void *MapPages(int32 flags, size_t size) = 0; + virtual void UnMapPages(int32 flags, void *addr, size_t size) = 0; + }; + + static PagesAllocator *GetDefaultPagesAllocator(void); + + struct Arena; // an arena from which memory may be allocated + + // Returns a pointer to a block of at least "request" bytes + // that have been newly allocated from the specific arena. + // for Alloc() call the DefaultArena() is used. + // Returns 0 if passed request==0. + // Does not return 0 under other circumstances; it crashes if memory + // is not available. + static void *Alloc(size_t request) + ATTRIBUTE_SECTION(malloc_hook); + static void *AllocWithArena(size_t request, Arena *arena) + ATTRIBUTE_SECTION(malloc_hook); + + // Deallocates a region of memory that was previously allocated with + // Alloc(). Does nothing if passed 0. "s" must be either 0, + // or must have been returned from a call to Alloc() and not yet passed to + // Free() since that call to Alloc(). The space is returned to the arena + // from which it was allocated. + static void Free(void *s) ATTRIBUTE_SECTION(malloc_hook); + + // ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free + // are to put all callers of MallocHook::Invoke* in this module + // into special section, + // so that MallocHook::GetCallerStackTrace can function accurately. + + // Create a new arena. + // The root metadata for the new arena is allocated in the + // meta_data_arena; the DefaultArena() can be passed for meta_data_arena. + // These values may be ored into flags: + enum { + // Report calls to Alloc() and Free() via the MallocHook interface. + // Set in the DefaultArena. + kCallMallocHook = 0x0001, + + // Make calls to Alloc(), Free() be async-signal-safe. Not set in + // DefaultArena(). + kAsyncSignalSafe = 0x0002, + + // When used with DefaultArena(), the NewArena() and DeleteArena() calls + // obey the flags given explicitly in the NewArena() call, even if those + // flags differ from the settings in DefaultArena(). So the call + // NewArena(kAsyncSignalSafe, DefaultArena()) is itself async-signal-safe, + // as well as generatating an arena that provides async-signal-safe + // Alloc/Free. + }; + static Arena *NewArena(int32 flags, Arena *meta_data_arena); + + // note: pages allocator will never be destroyed and allocated pages will never be freed + // When allocator is NULL, it's same as NewArena + static Arena *NewArenaWithCustomAlloc(int32 flags, Arena *meta_data_arena, PagesAllocator *allocator); + + // Destroys an arena allocated by NewArena and returns true, + // provided no allocated blocks remain in the arena. + // If allocated blocks remain in the arena, does nothing and + // returns false. + // It is illegal to attempt to destroy the DefaultArena(). + static bool DeleteArena(Arena *arena); + + // The default arena that always exists. + static Arena *DefaultArena(); + + private: + LowLevelAlloc(); // no instances +}; + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/simple_mutex.h b/trunk/3rdparty/gperftools-2-fit/src/base/simple_mutex.h new file mode 100644 index 000000000..5913b9e61 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/simple_mutex.h @@ -0,0 +1,332 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein. +// +// A simple mutex wrapper, supporting locks and read-write locks. +// You should assume the locks are *not* re-entrant. +// +// To use: you should define the following macros in your configure.ac: +// ACX_PTHREAD +// AC_RWLOCK +// The latter is defined in ../autoconf. +// +// This class is meant to be internal-only and should be wrapped by an +// internal namespace. Before you use this module, please give the +// name of your internal namespace for this module. Or, if you want +// to expose it, you'll want to move it to the Google namespace. We +// cannot put this class in global namespace because there can be some +// problems when we have multiple versions of Mutex in each shared object. +// +// NOTE: TryLock() is broken for NO_THREADS mode, at least in NDEBUG +// mode. +// +// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy: +// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html +// Because of that, we might as well use windows locks for +// cygwin. They seem to be more reliable than the cygwin pthreads layer. +// +// TRICKY IMPLEMENTATION NOTE: +// This class is designed to be safe to use during +// dynamic-initialization -- that is, by global constructors that are +// run before main() starts. The issue in this case is that +// dynamic-initialization happens in an unpredictable order, and it +// could be that someone else's dynamic initializer could call a +// function that tries to acquire this mutex -- but that all happens +// before this mutex's constructor has run. (This can happen even if +// the mutex and the function that uses the mutex are in the same .cc +// file.) Basically, because Mutex does non-trivial work in its +// constructor, it's not, in the naive implementation, safe to use +// before dynamic initialization has run on it. +// +// The solution used here is to pair the actual mutex primitive with a +// bool that is set to true when the mutex is dynamically initialized. +// (Before that it's false.) Then we modify all mutex routines to +// look at the bool, and not try to lock/unlock until the bool makes +// it to true (which happens after the Mutex constructor has run.) +// +// This works because before main() starts -- particularly, during +// dynamic initialization -- there are no threads, so a) it's ok that +// the mutex operations are a no-op, since we don't need locking then +// anyway; and b) we can be quite confident our bool won't change +// state between a call to Lock() and a call to Unlock() (that would +// require a global constructor in one translation unit to call Lock() +// and another global constructor in another translation unit to call +// Unlock() later, which is pretty perverse). +// +// That said, it's tricky, and can conceivably fail; it's safest to +// avoid trying to acquire a mutex in a global constructor, if you +// can. One way it can fail is that a really smart compiler might +// initialize the bool to true at static-initialization time (too +// early) rather than at dynamic-initialization time. To discourage +// that, we set is_safe_ to true in code (not the constructor +// colon-initializer) and set it to true via a function that always +// evaluates to true, but that the compiler can't know always +// evaluates to true. This should be good enough. +// +// A related issue is code that could try to access the mutex +// after it's been destroyed in the global destructors (because +// the Mutex global destructor runs before some other global +// destructor, that tries to acquire the mutex). The way we +// deal with this is by taking a constructor arg that global +// mutexes should pass in, that causes the destructor to do no +// work. We still depend on the compiler not doing anything +// weird to a Mutex's memory after it is destroyed, but for a +// static global variable, that's pretty safe. + +#ifndef GOOGLE_MUTEX_H_ +#define GOOGLE_MUTEX_H_ + +#include + +#if defined(NO_THREADS) + typedef int MutexType; // to keep a lock-count +#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN // We only need minimal includes +# endif + // We need Windows NT or later for TryEnterCriticalSection(). If you + // don't need that functionality, you can remove these _WIN32_WINNT + // lines, and change TryLock() to assert(0) or something. +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +# endif +# include + typedef CRITICAL_SECTION MutexType; +#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) + // Needed for pthread_rwlock_*. If it causes problems, you could take it + // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it + // *does* cause problems for FreeBSD, or MacOSX, but isn't needed + // for locking there.) +# ifdef __linux__ +# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls +# endif +# include + typedef pthread_rwlock_t MutexType; +#elif defined(HAVE_PTHREAD) +# include + typedef pthread_mutex_t MutexType; +#else +# error Need to implement mutex.h for your architecture, or #define NO_THREADS +#endif + +#include +#include // for abort() + +#define MUTEX_NAMESPACE perftools_mutex_namespace + +namespace MUTEX_NAMESPACE { + +class Mutex { + public: + // This is used for the single-arg constructor + enum LinkerInitialized { LINKER_INITIALIZED }; + + // Create a Mutex that is not held by anybody. This constructor is + // typically used for Mutexes allocated on the heap or the stack. + inline Mutex(); + // This constructor should be used for global, static Mutex objects. + // It inhibits work being done by the destructor, which makes it + // safer for code that tries to acqiure this mutex in their global + // destructor. + inline Mutex(LinkerInitialized); + + // Destructor + inline ~Mutex(); + + inline void Lock(); // Block if needed until free then acquire exclusively + inline void Unlock(); // Release a lock acquired via Lock() + inline bool TryLock(); // If free, Lock() and return true, else return false + // Note that on systems that don't support read-write locks, these may + // be implemented as synonyms to Lock() and Unlock(). So you can use + // these for efficiency, but don't use them anyplace where being able + // to do shared reads is necessary to avoid deadlock. + inline void ReaderLock(); // Block until free or shared then acquire a share + inline void ReaderUnlock(); // Release a read share of this Mutex + inline void WriterLock() { Lock(); } // Acquire an exclusive lock + inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() + + private: + MutexType mutex_; + // We want to make sure that the compiler sets is_safe_ to true only + // when we tell it to, and never makes assumptions is_safe_ is + // always true. volatile is the most reliable way to do that. + volatile bool is_safe_; + // This indicates which constructor was called. + bool destroy_; + + inline void SetIsSafe() { is_safe_ = true; } + + // Catch the error of writing Mutex when intending MutexLock. + Mutex(Mutex* /*ignored*/) {} + // Disallow "evil" constructors + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +// Now the implementation of Mutex for various systems +#if defined(NO_THREADS) + +// When we don't have threads, we can be either reading or writing, +// but not both. We can have lots of readers at once (in no-threads +// mode, that's most likely to happen in recursive function calls), +// but only one writer. We represent this by having mutex_ be -1 when +// writing and a number > 0 when reading (and 0 when no lock is held). +// +// In debug mode, we assert these invariants, while in non-debug mode +// we do nothing, for efficiency. That's why everything is in an +// assert. + +Mutex::Mutex() : mutex_(0) { } +Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { } +Mutex::~Mutex() { assert(mutex_ == 0); } +void Mutex::Lock() { assert(--mutex_ == -1); } +void Mutex::Unlock() { assert(mutex_++ == -1); } +bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } +void Mutex::ReaderLock() { assert(++mutex_ > 0); } +void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } + +#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) + +Mutex::Mutex() : destroy_(true) { + InitializeCriticalSection(&mutex_); + SetIsSafe(); +} +Mutex::Mutex(LinkerInitialized) : destroy_(false) { + InitializeCriticalSection(&mutex_); + SetIsSafe(); +} +Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); } +void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } +void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } +bool Mutex::TryLock() { return is_safe_ ? + TryEnterCriticalSection(&mutex_) != 0 : true; } +void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks +void Mutex::ReaderUnlock() { Unlock(); } + +#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() : destroy_(true) { + SetIsSafe(); + if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); +} +Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { + SetIsSafe(); + if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +bool Mutex::TryLock() { return is_safe_ ? + pthread_rwlock_trywrlock(&mutex_) == 0 : true; } +void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } +void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +#undef SAFE_PTHREAD + +#elif defined(HAVE_PTHREAD) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() : destroy_(true) { + SetIsSafe(); + if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); +} +Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) { + SetIsSafe(); + if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } +bool Mutex::TryLock() { return is_safe_ ? + pthread_mutex_trylock(&mutex_) == 0 : true; } +void Mutex::ReaderLock() { Lock(); } +void Mutex::ReaderUnlock() { Unlock(); } +#undef SAFE_PTHREAD + +#endif + +// -------------------------------------------------------------------------- +// Some helper classes + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class MutexLock { + public: + explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } + ~MutexLock() { mu_->Unlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + MutexLock(const MutexLock&); + void operator=(const MutexLock&); +}; + +// ReaderMutexLock and WriterMutexLock do the same, for rwlocks +class ReaderMutexLock { + public: + explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } + ~ReaderMutexLock() { mu_->ReaderUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + ReaderMutexLock(const ReaderMutexLock&); + void operator=(const ReaderMutexLock&); +}; + +class WriterMutexLock { + public: + explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } + ~WriterMutexLock() { mu_->WriterUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + WriterMutexLock(const WriterMutexLock&); + void operator=(const WriterMutexLock&); +}; + +// Catch bug where variable name is omitted, e.g. MutexLock (&mu); +#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) +#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) +#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) + +} // namespace MUTEX_NAMESPACE + +using namespace MUTEX_NAMESPACE; + +#undef MUTEX_NAMESPACE + +#endif /* #define GOOGLE_SIMPLE_MUTEX_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.cc b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.cc new file mode 100644 index 000000000..d2a9e1c23 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.cc @@ -0,0 +1,129 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +#include +#include "base/spinlock.h" +#include "base/spinlock_internal.h" +#include "base/sysinfo.h" /* for GetSystemCPUsCount() */ + +// NOTE on the Lock-state values: +// +// kSpinLockFree represents the unlocked state +// kSpinLockHeld represents the locked state with no waiters +// kSpinLockSleeper represents the locked state with waiters + +static int adaptive_spin_count = 0; + +const base::LinkerInitialized SpinLock::LINKER_INITIALIZED = + base::LINKER_INITIALIZED; + +namespace { +struct SpinLock_InitHelper { + SpinLock_InitHelper() { + // On multi-cpu machines, spin for longer before yielding + // the processor or sleeping. Reduces idle time significantly. + if (GetSystemCPUsCount() > 1) { + adaptive_spin_count = 1000; + } + } +}; + +// Hook into global constructor execution: +// We do not do adaptive spinning before that, +// but nothing lock-intensive should be going on at that time. +static SpinLock_InitHelper init_helper; + +inline void SpinlockPause(void) { +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + __asm__ __volatile__("rep; nop" : : ); +#endif +} + +} // unnamed namespace + +// Monitor the lock to see if its value changes within some time +// period (adaptive_spin_count loop iterations). The last value read +// from the lock is returned from the method. +Atomic32 SpinLock::SpinLoop() { + int c = adaptive_spin_count; + while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) { + SpinlockPause(); + } + return base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree, + kSpinLockSleeper); +} + +void SpinLock::SlowLock() { + Atomic32 lock_value = SpinLoop(); + + int lock_wait_call_count = 0; + while (lock_value != kSpinLockFree) { + // If the lock is currently held, but not marked as having a sleeper, mark + // it as having a sleeper. + if (lock_value == kSpinLockHeld) { + // Here, just "mark" that the thread is going to sleep. Don't store the + // lock wait time in the lock as that will cause the current lock + // owner to think it experienced contention. + lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_, + kSpinLockHeld, + kSpinLockSleeper); + if (lock_value == kSpinLockHeld) { + // Successfully transitioned to kSpinLockSleeper. Pass + // kSpinLockSleeper to the SpinLockDelay routine to properly indicate + // the last lock_value observed. + lock_value = kSpinLockSleeper; + } else if (lock_value == kSpinLockFree) { + // Lock is free again, so try and acquire it before sleeping. The + // new lock state will be the number of cycles this thread waited if + // this thread obtains the lock. + lock_value = base::subtle::Acquire_CompareAndSwap(&lockword_, + kSpinLockFree, + kSpinLockSleeper); + continue; // skip the delay at the end of the loop + } + } + + // Wait for an OS specific delay. + base::internal::SpinLockDelay(&lockword_, lock_value, + ++lock_wait_call_count); + // Spin again after returning from the wait routine to give this thread + // some chance of obtaining the lock. + lock_value = SpinLoop(); + } +} + +void SpinLock::SlowUnlock() { + // wake waiter if necessary + base::internal::SpinLockWake(&lockword_, false); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.h b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.h new file mode 100644 index 000000000..118f54133 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock.h @@ -0,0 +1,132 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +// SpinLock is async signal safe. +// If used within a signal handler, all lock holders +// should block the signal even outside the signal handler. + +#ifndef BASE_SPINLOCK_H_ +#define BASE_SPINLOCK_H_ + +#include +#include "base/atomicops.h" +#include "base/basictypes.h" +#include "base/dynamic_annotations.h" +#include "base/thread_annotations.h" + +class LOCKABLE SpinLock { + public: + SpinLock() : lockword_(kSpinLockFree) { } + + // Special constructor for use with static SpinLock objects. E.g., + // + // static SpinLock lock(base::LINKER_INITIALIZED); + // + // When intialized using this constructor, we depend on the fact + // that the linker has already initialized the memory appropriately. + // A SpinLock constructed like this can be freely used from global + // initializers without worrying about the order in which global + // initializers run. + explicit SpinLock(base::LinkerInitialized /*x*/) { + // Does nothing; lockword_ is already initialized + } + + // Acquire this SpinLock. + inline void Lock() EXCLUSIVE_LOCK_FUNCTION() { + if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree, + kSpinLockHeld) != kSpinLockFree) { + SlowLock(); + } + } + + // Try to acquire this SpinLock without blocking and return true if the + // acquisition was successful. If the lock was not acquired, false is + // returned. If this SpinLock is free at the time of the call, TryLock + // will return true with high probability. + inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { + bool res = + (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree, + kSpinLockHeld) == kSpinLockFree); + return res; + } + + // Release this SpinLock, which must be held by the calling thread. + inline void Unlock() UNLOCK_FUNCTION() { + uint64 prev_value = static_cast( + base::subtle::Release_AtomicExchange(&lockword_, kSpinLockFree)); + if (prev_value != kSpinLockHeld) { + // Speed the wakeup of any waiter. + SlowUnlock(); + } + } + + // Determine if the lock is held. When the lock is held by the invoking + // thread, true will always be returned. Intended to be used as + // CHECK(lock.IsHeld()). + inline bool IsHeld() const { + return base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree; + } + + static const base::LinkerInitialized LINKER_INITIALIZED; // backwards compat + private: + enum { kSpinLockFree = 0 }; + enum { kSpinLockHeld = 1 }; + enum { kSpinLockSleeper = 2 }; + + volatile Atomic32 lockword_; + + void SlowLock(); + void SlowUnlock(); + Atomic32 SpinLoop(); + + DISALLOW_COPY_AND_ASSIGN(SpinLock); +}; + +// Corresponding locker object that arranges to acquire a spinlock for +// the duration of a C++ scope. +class SCOPED_LOCKABLE SpinLockHolder { + private: + SpinLock* lock_; + public: + inline explicit SpinLockHolder(SpinLock* l) EXCLUSIVE_LOCK_FUNCTION(l) + : lock_(l) { + l->Lock(); + } + inline ~SpinLockHolder() UNLOCK_FUNCTION() { lock_->Unlock(); } +}; +// Catch bug where variable name is omitted, e.g. SpinLockHolder (&lock); +#define SpinLockHolder(x) COMPILE_ASSERT(0, spin_lock_decl_missing_var_name) + + +#endif // BASE_SPINLOCK_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.cc b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.cc new file mode 100644 index 000000000..d9629717b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.cc @@ -0,0 +1,102 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2010, 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. + */ + +// The OS-specific header included below must provide two calls: +// base::internal::SpinLockDelay() and base::internal::SpinLockWake(). +// See spinlock_internal.h for the spec of SpinLockWake(). + +// void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) +// SpinLockDelay() generates an apprproate spin delay on iteration "loop" of a +// spin loop on location *w, whose previously observed value was "value". +// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick, +// or may wait for a delay that can be truncated by a call to SpinlockWake(w). +// In all cases, it must return in bounded time even if SpinlockWake() is not +// called. + +#include "base/spinlock_internal.h" + +// forward declaration for use by spinlock_*-inl.h +namespace base { namespace internal { static int SuggestedDelayNS(int loop); }} + +#if defined(_WIN32) +#include "base/spinlock_win32-inl.h" +#elif defined(__linux__) +#include "base/spinlock_linux-inl.h" +#else +#include "base/spinlock_posix-inl.h" +#endif + +namespace base { +namespace internal { + +// Return a suggested delay in nanoseconds for iteration number "loop" +static int SuggestedDelayNS(int loop) { + // Weak pseudo-random number generator to get some spread between threads + // when many are spinning. +#ifdef BASE_HAS_ATOMIC64 + static base::subtle::Atomic64 rand; + uint64 r = base::subtle::NoBarrier_Load(&rand); + r = 0x5deece66dLL * r + 0xb; // numbers from nrand48() + base::subtle::NoBarrier_Store(&rand, r); + + r <<= 16; // 48-bit random number now in top 48-bits. + if (loop < 0 || loop > 32) { // limit loop to 0..32 + loop = 32; + } + // loop>>3 cannot exceed 4 because loop cannot exceed 32. + // Select top 20..24 bits of lower 48 bits, + // giving approximately 0ms to 16ms. + // Mean is exponential in loop for first 32 iterations, then 8ms. + // The futex path multiplies this by 16, since we expect explicit wakeups + // almost always on that path. + return r >> (44 - (loop >> 3)); +#else + static Atomic32 rand; + uint32 r = base::subtle::NoBarrier_Load(&rand); + r = 0x343fd * r + 0x269ec3; // numbers from MSVC++ + base::subtle::NoBarrier_Store(&rand, r); + + r <<= 1; // 31-bit random number now in top 31-bits. + if (loop < 0 || loop > 32) { // limit loop to 0..32 + loop = 32; + } + // loop>>3 cannot exceed 4 because loop cannot exceed 32. + // Select top 20..24 bits of lower 31 bits, + // giving approximately 0ms to 16ms. + // Mean is exponential in loop for first 32 iterations, then 8ms. + // The futex path multiplies this by 16, since we expect explicit wakeups + // almost always on that path. + return r >> (12 - (loop >> 3)); +#endif +} + +} // namespace internal +} // namespace base diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.h b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.h new file mode 100644 index 000000000..aa47e67d4 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_internal.h @@ -0,0 +1,51 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2010, 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. + * + * --- + * This file is an internal part spinlock.cc and once.cc + * It may not be used directly by code outside of //base. + */ + +#ifndef BASE_SPINLOCK_INTERNAL_H_ +#define BASE_SPINLOCK_INTERNAL_H_ + +#include +#include "base/basictypes.h" +#include "base/atomicops.h" + +namespace base { +namespace internal { + +void SpinLockWake(volatile Atomic32 *w, bool all); +void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop); + +} // namespace internal +} // namespace base +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_linux-inl.h b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_linux-inl.h new file mode 100644 index 000000000..ad48aaebd --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_linux-inl.h @@ -0,0 +1,103 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2009, 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. + * + * --- + * This file is a Linux-specific part of spinlock_internal.cc + */ + +#include +#include +#include +#include +#include +#include + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 + +// Note: Instead of making direct system calls that are inlined, we rely +// on the syscall() function in glibc to do the right thing. + +static bool have_futex; +static int futex_private_flag = FUTEX_PRIVATE_FLAG; + +namespace { +static struct InitModule { + InitModule() { + int x = 0; + // futexes are ints, so we can use them only when + // that's the same size as the lockword_ in SpinLock. + have_futex = (sizeof(Atomic32) == sizeof(int) && + syscall(__NR_futex, &x, FUTEX_WAKE, 1, NULL, NULL, 0) >= 0); + if (have_futex && syscall(__NR_futex, &x, FUTEX_WAKE | futex_private_flag, + 1, NULL, NULL, 0) < 0) { + futex_private_flag = 0; + } + } +} init_module; + +} // anonymous namespace + + +namespace base { +namespace internal { + +void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) { + if (loop != 0) { + int save_errno = errno; + struct timespec tm; + tm.tv_sec = 0; + if (have_futex) { + tm.tv_nsec = base::internal::SuggestedDelayNS(loop); + } else { + tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin + } + if (have_futex) { + tm.tv_nsec *= 16; // increase the delay; we expect explicit wakeups + syscall(__NR_futex, reinterpret_cast(const_cast(w)), + FUTEX_WAIT | futex_private_flag, value, + reinterpret_cast(&tm), NULL, 0); + } else { + nanosleep(&tm, NULL); + } + errno = save_errno; + } +} + +void SpinLockWake(volatile Atomic32 *w, bool all) { + if (have_futex) { + syscall(__NR_futex, reinterpret_cast(const_cast(w)), + FUTEX_WAKE | futex_private_flag, all ? INT_MAX : 1, NULL, NULL, 0); + } +} + +} // namespace internal +} // namespace base diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_posix-inl.h b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_posix-inl.h new file mode 100644 index 000000000..f4d217b5f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_posix-inl.h @@ -0,0 +1,63 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2009, 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. + * + * --- + * This file is a Posix-specific part of spinlock_internal.cc + */ + +#include +#include +#ifdef HAVE_SCHED_H +#include /* For sched_yield() */ +#endif +#include /* For nanosleep() */ + +namespace base { +namespace internal { + +void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) { + int save_errno = errno; + if (loop == 0) { + } else if (loop == 1) { + sched_yield(); + } else { + struct timespec tm; + tm.tv_sec = 0; + tm.tv_nsec = base::internal::SuggestedDelayNS(loop); + nanosleep(&tm, NULL); + } + errno = save_errno; +} + +void SpinLockWake(volatile Atomic32 *w, bool all) { +} + +} // namespace internal +} // namespace base diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_win32-inl.h b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_win32-inl.h new file mode 100644 index 000000000..05caa54a3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/spinlock_win32-inl.h @@ -0,0 +1,54 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2009, 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. + * + * --- + * This file is a Win32-specific part of spinlock_internal.cc + */ + + +#include + +namespace base { +namespace internal { + +void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) { + if (loop == 0) { + } else if (loop == 1) { + Sleep(0); + } else { + Sleep(base::internal::SuggestedDelayNS(loop) / 1000000); + } +} + +void SpinLockWake(volatile Atomic32 *w, bool all) { +} + +} // namespace internal +} // namespace base diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/stl_allocator.h b/trunk/3rdparty/gperftools-2-fit/src/base/stl_allocator.h new file mode 100644 index 000000000..94debe82c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/stl_allocator.h @@ -0,0 +1,98 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Maxim Lifantsev + */ + + +#ifndef BASE_STL_ALLOCATOR_H_ +#define BASE_STL_ALLOCATOR_H_ + +#include + +#include // for ptrdiff_t +#include + +#include "base/logging.h" + +// Generic allocator class for STL objects +// that uses a given type-less allocator Alloc, which must provide: +// static void* Alloc::Allocate(size_t size); +// static void Alloc::Free(void* ptr, size_t size); +// +// STL_Allocator provides the same thread-safety +// guarantees as MyAlloc. +// +// Usage example: +// set, STL_Allocator > my_set; +// CAVEAT: Parts of the code below are probably specific +// to the STL version(s) we are using. +// The code is simply lifted from what std::allocator<> provides. +template +class STL_Allocator { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template struct rebind { + typedef STL_Allocator other; + }; + + STL_Allocator() { } + STL_Allocator(const STL_Allocator&) { } + template STL_Allocator(const STL_Allocator&) { } + ~STL_Allocator() { } + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pointer allocate(size_type n, const void* = 0) { + RAW_DCHECK((n * sizeof(T)) / sizeof(T) == n, "n is too big to allocate"); + return static_cast(Alloc::Allocate(n * sizeof(T))); + } + void deallocate(pointer p, size_type n) { Alloc::Free(p, n * sizeof(T)); } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + void construct(pointer p, const T& val) { ::new(p) T(val); } + void construct(pointer p) { ::new(p) T(); } + void destroy(pointer p) { p->~T(); } + + // There's no state, so these allocators are always equal + bool operator==(const STL_Allocator&) const { return true; } +}; + +#endif // BASE_STL_ALLOCATOR_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.cc b/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.cc new file mode 100644 index 000000000..669efaf62 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.cc @@ -0,0 +1,878 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2006, 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. + +#include +#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(__CYGWIN__) && !defined(__CYGWIN32) +# define PLATFORM_WINDOWS 1 +#endif + +#include // for isspace() +#include // for getenv() +#include // for snprintf(), sscanf() +#include // for memmove(), memchr(), etc. +#include // for open() +#include // for errno +#ifdef HAVE_UNISTD_H +#include // for read() +#endif +#if defined __MACH__ // Mac OS X, almost certainly +#include // for iterating over dll's in ProcMapsIter +#include // for iterating over dll's in ProcMapsIter +#include +#include // how we figure out numcpu's on OS X +#elif defined __FreeBSD__ +#include +#elif defined __sun__ // Solaris +#include // for, e.g., prmap_t +#elif defined(PLATFORM_WINDOWS) +#include // for getpid() (actually, _getpid()) +#include // for SHGetValueA() +#include // for Module32First() +#endif +#include "base/sysinfo.h" +#include "base/commandlineflags.h" +#include "base/dynamic_annotations.h" // for RunningOnValgrind +#include "base/logging.h" + +#ifdef PLATFORM_WINDOWS +#ifdef 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. +// In unicode mode, tlhelp32.h #defines MODULEENTRY32 to be +// MODULEENTRY32W. These #undefs are the only way I see to get back +// access to the original, ascii struct (and related functions). +#undef MODULEENTRY32 +#undef Module32First +#undef Module32Next +#undef PMODULEENTRY32 +#undef LPMODULEENTRY32 +#endif /* MODULEENTRY32 */ +// MinGW doesn't seem to define this, perhaps some windowsen don't either. +#ifndef TH32CS_SNAPMODULE32 +#define TH32CS_SNAPMODULE32 0 +#endif /* TH32CS_SNAPMODULE32 */ +#endif /* PLATFORM_WINDOWS */ + +// 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_SYS_SYSCALL_H +# include +#endif +#ifdef SYS_open // solaris 11, at least sometimes, only defines SYS_openat +# define safeopen(filename, mode) syscall(SYS_open, filename, mode) +#else +# define safeopen(filename, mode) open(filename, mode) +#endif +#ifdef SYS_read +# define saferead(fd, buffer, size) syscall(SYS_read, fd, buffer, size) +#else +# define saferead(fd, buffer, size) read(fd, buffer, size) +#endif +#ifdef SYS_close +# define safeclose(fd) syscall(SYS_close, fd) +#else +# define safeclose(fd) close(fd) +#endif + +// ---------------------------------------------------------------------- +// GetenvBeforeMain() +// GetUniquePathFromEnv() +// Some non-trivial getenv-related functions. +// ---------------------------------------------------------------------- + +// we reimplement memcmp and friends to avoid depending on any glibc +// calls too early in the process lifetime. This allows us to use +// GetenvBeforeMain from inside ifunc handler +static int slow_memcmp(const void *_a, const void *_b, size_t n) { + const uint8_t *a = reinterpret_cast(_a); + const uint8_t *b = reinterpret_cast(_b); + while (n-- != 0) { + uint8_t ac = *a++; + uint8_t bc = *b++; + if (ac != bc) { + if (ac < bc) { + return -1; + } + return 1; + } + } + return 0; +} + +static const char *slow_memchr(const char *s, int c, size_t n) { + uint8_t ch = static_cast(c); + while (n--) { + if (*s++ == ch) { + return s - 1; + } + } + return 0; +} + +static size_t slow_strlen(const char *s) { + const char *s2 = slow_memchr(s, '\0', static_cast(-1)); + return s2 - s; +} + +// It's not safe to call getenv() in the malloc hooks, because they +// might be called extremely early, before libc is done setting up +// correctly. In particular, the thread library may not be done +// setting up errno. So instead, we use the built-in __environ array +// if it exists, and otherwise read /proc/self/environ directly, using +// system calls to read the file, and thus avoid setting errno. +// /proc/self/environ has a limit of how much data it exports (around +// 8K), so it's not an ideal solution. +const char* GetenvBeforeMain(const char* name) { + const int namelen = slow_strlen(name); +#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h + if (__environ) { // can exist but be NULL, if statically linked + for (char** p = __environ; *p; p++) { + if (!slow_memcmp(*p, name, namelen) && (*p)[namelen] == '=') + return *p + namelen+1; + } + return NULL; + } +#endif +#if defined(PLATFORM_WINDOWS) + // TODO(mbelshe) - repeated calls to this function will overwrite the + // contents of the static buffer. + static char envvar_buf[1024]; // enough to hold any envvar we care about + if (!GetEnvironmentVariableA(name, envvar_buf, sizeof(envvar_buf)-1)) + return NULL; + return envvar_buf; +#endif + // static is ok because this function should only be called before + // main(), when we're single-threaded. + static char envbuf[16<<10]; + if (*envbuf == '\0') { // haven't read the environ yet + int fd = safeopen("/proc/self/environ", O_RDONLY); + // 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); + } + const char* p = envbuf; + while (*p != '\0') { // will happen at the \0\0 that terminates the buffer + // proc file has the format NAME=value\0NAME=value\0NAME=value\0... + const char* endp = (char*)slow_memchr(p, '\0', + sizeof(envbuf) - (p - envbuf)); + if (endp == NULL) // this entry isn't NUL terminated + return NULL; + else if (!slow_memcmp(p, name, namelen) && p[namelen] == '=') // it's a match + return p + namelen+1; // point after = + p = endp + 1; + } + return NULL; // env var never found +} + +extern "C" { + const char* TCMallocGetenvSafe(const char* name) { + return GetenvBeforeMain(name); + } +} + +// 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, +// or is the empty string, leave path unchanged and returns false. +// The reason this is non-trivial is that this function handles munged +// pathnames. Here's why: +// +// If we're a child process of the 'main' process, we can't just use +// getenv("CPUPROFILE") -- the parent process will be using that path. +// Instead we append our pid to the pathname. How do we tell if we're a +// child process? Ideally we'd set an environment variable that all +// our children would inherit. But -- and this is seemingly a bug in +// gcc -- if you do a setenv() in a shared libarary in a global +// constructor, the environment setting is lost by the time main() is +// called. The only safe thing we can do in such a situation is to +// modify the existing envvar. So we do a hack: in the parent, we set +// the high bit of the 1st char of CPUPROFILE. In the child, we +// notice the high bit is set and append the pid(). This works +// assuming cpuprofile filenames don't normally have the high bit set +// in their first character! If that assumption is violated, we'll +// still get a profile, but one with an unexpected name. +// TODO(csilvers): set an envvar instead when we can do it reliably. +bool GetUniquePathFromEnv(const char* env_name, char* path) { + char* envval = getenv(env_name); + if (envval == NULL || *envval == '\0') + return false; + if (envval[0] & 128) { // high bit is set + snprintf(path, PATH_MAX, "%c%s_%u", // add pid and clear high bit + envval[0] & 127, envval+1, (unsigned int)(getpid())); + } else { + snprintf(path, PATH_MAX, "%s", envval); + envval[0] |= 128; // set high bit for kids to see + } + return true; +} + +int GetSystemCPUsCount() +{ +#if defined(PLATFORM_WINDOWS) + // Get the number of processors. + SYSTEM_INFO info; + GetSystemInfo(&info); + return info.dwNumberOfProcessors; +#else + long rv = sysconf(_SC_NPROCESSORS_ONLN); + if (rv < 0) { + return 1; + } + return static_cast(rv); +#endif +} + +// ---------------------------------------------------------------------- + +#if defined __linux__ || defined __FreeBSD__ || defined __sun__ || defined __CYGWIN__ || defined __CYGWIN32__ +static void ConstructFilename(const char* spec, pid_t pid, + char* buf, int buf_size) { + CHECK_LT(snprintf(buf, buf_size, + spec, + static_cast(pid ? pid : getpid())), buf_size); +} +#endif + +// A templatized helper function instantiated for Mach (OS X) only. +// It can handle finding info for both 32 bits and 64 bits. +// Returns true if it successfully handled the hdr, false else. +#ifdef __MACH__ // Mac OS X, almost certainly +template +static bool NextExtMachHelper(const mach_header* hdr, + int current_image, int current_load_cmd, + uint64 *start, uint64 *end, char **flags, + uint64 *offset, int64 *inode, char **filename, + uint64 *file_mapping, uint64 *file_pages, + uint64 *anon_mapping, uint64 *anon_pages, + dev_t *dev) { + static char kDefaultPerms[5] = "r-xp"; + if (hdr->magic != kMagic) + return false; + const char* lc = (const char *)hdr + sizeof(MachHeader); + // 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 == kLCSegment) { + const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image); + const SegmentCommand* sc = (const SegmentCommand *)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(_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; + } + + return false; +} +#endif + +// Finds |c| in |text|, and assign '\0' at the found position. +// The original character at the modified position should be |c|. +// A pointer to the modified position is stored in |endptr|. +// |endptr| should not be NULL. +static bool ExtractUntilChar(char *text, int c, char **endptr) { + CHECK_NE(text, NULL); + CHECK_NE(endptr, NULL); + char *found; + found = strchr(text, c); + if (found == NULL) { + *endptr = NULL; + return false; + } + + *endptr = found; + *found = '\0'; + return true; +} + +// Increments |*text_pointer| while it points a whitespace character. +// It is to follow sscanf's whilespace handling. +static void SkipWhileWhitespace(char **text_pointer, int c) { + if (isspace(c)) { + while (isspace(**text_pointer) && isspace(*((*text_pointer) + 1))) { + ++(*text_pointer); + } + } +} + +template +static T StringToInteger(char *text, char **endptr, int base) { + assert(false); + return T(); +} + +template<> +int StringToInteger(char *text, char **endptr, int base) { + return strtol(text, endptr, base); +} + +template<> +int64 StringToInteger(char *text, char **endptr, int base) { + return strtoll(text, endptr, base); +} + +template<> +uint64 StringToInteger(char *text, char **endptr, int base) { + return strtoull(text, endptr, base); +} + +template +static T StringToIntegerUntilChar( + char *text, int base, int c, char **endptr_result) { + CHECK_NE(endptr_result, NULL); + *endptr_result = NULL; + + char *endptr_extract; + if (!ExtractUntilChar(text, c, &endptr_extract)) + return 0; + + T result; + char *endptr_strto; + result = StringToInteger(text, &endptr_strto, base); + *endptr_extract = c; + + if (endptr_extract != endptr_strto) + return 0; + + *endptr_result = endptr_extract; + SkipWhileWhitespace(endptr_result, c); + + return result; +} + +static char *CopyStringUntilChar( + char *text, unsigned out_len, int c, char *out) { + char *endptr; + if (!ExtractUntilChar(text, c, &endptr)) + return NULL; + + strncpy(out, text, out_len); + out[out_len-1] = '\0'; + *endptr = c; + + SkipWhileWhitespace(&endptr, c); + return endptr; +} + +template +static bool StringToIntegerUntilCharWithCheck( + T *outptr, char *text, int base, int c, char **endptr) { + *outptr = StringToIntegerUntilChar(*endptr, base, c, endptr); + if (*endptr == NULL || **endptr == '\0') return false; + ++(*endptr); + return true; +} + +static bool ParseProcMapsLine(char *text, uint64 *start, uint64 *end, + char *flags, uint64 *offset, + int *major, int *minor, int64 *inode, + unsigned *filename_offset) { +#if defined(__linux__) + /* + * It's similar to: + * sscanf(text, "%"SCNx64"-%"SCNx64" %4s %"SCNx64" %x:%x %"SCNd64" %n", + * start, end, flags, offset, major, minor, inode, filename_offset) + */ + char *endptr = text; + if (endptr == NULL || *endptr == '\0') return false; + + if (!StringToIntegerUntilCharWithCheck(start, endptr, 16, '-', &endptr)) + return false; + + if (!StringToIntegerUntilCharWithCheck(end, endptr, 16, ' ', &endptr)) + return false; + + endptr = CopyStringUntilChar(endptr, 5, ' ', flags); + if (endptr == NULL || *endptr == '\0') return false; + ++endptr; + + if (!StringToIntegerUntilCharWithCheck(offset, endptr, 16, ' ', &endptr)) + return false; + + if (!StringToIntegerUntilCharWithCheck(major, endptr, 16, ':', &endptr)) + return false; + + if (!StringToIntegerUntilCharWithCheck(minor, endptr, 16, ' ', &endptr)) + return false; + + if (!StringToIntegerUntilCharWithCheck(inode, endptr, 10, ' ', &endptr)) + return false; + + *filename_offset = (endptr - text); + return true; +#else + return false; +#endif +} + +ProcMapsIterator::ProcMapsIterator(pid_t pid) { + Init(pid, NULL, false); +} + +ProcMapsIterator::ProcMapsIterator(pid_t pid, Buffer *buffer) { + Init(pid, buffer, false); +} + +ProcMapsIterator::ProcMapsIterator(pid_t pid, Buffer *buffer, + bool use_maps_backing) { + Init(pid, buffer, use_maps_backing); +} + +void ProcMapsIterator::Init(pid_t pid, Buffer *buffer, + bool use_maps_backing) { + pid_ = pid; + using_maps_backing_ = use_maps_backing; + dynamic_buffer_ = NULL; + if (!buffer) { + // 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. + buffer = dynamic_buffer_ = new Buffer; + } else { + dynamic_buffer_ = NULL; + } + + ibuf_ = buffer->buf_; + + stext_ = etext_ = nextline_ = ibuf_; + ebuf_ = ibuf_ + Buffer::kBufSize - 1; + nextline_ = ibuf_; + +#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__) + 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); + } + // No error logging since this can be called from the crash dump + // handler at awkward moments. Users should call Valid() before + // using. + 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__) + current_image_ = _dyld_image_count(); // count down from the top + current_load_cmd_ = -1; +#elif defined(PLATFORM_WINDOWS) + snapshot_ = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | + TH32CS_SNAPMODULE32, + GetCurrentProcessId()); + memset(&module_, 0, sizeof(module_)); +#else + fd_ = -1; // so Valid() is always false +#endif + +} + +ProcMapsIterator::~ProcMapsIterator() { +#if defined(PLATFORM_WINDOWS) + 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(PLATFORM_WINDOWS) + return snapshot_ != INVALID_HANDLE_VALUE; +#elif defined(__MACH__) + return 1; +#else + return fd_ != -1; +#endif +} + +bool ProcMapsIterator::Next(uint64 *start, uint64 *end, char **flags, + uint64 *offset, int64 *inode, char **filename) { + return NextExt(start, end, flags, offset, inode, filename, NULL, NULL, + NULL, NULL, NULL); +} + +// This has too many arguments. It should really be building +// a map object and returning it. The problem is that this is called +// when the memory allocator state is undefined, hence the arguments. +bool ProcMapsIterator::NextExt(uint64 *start, uint64 *end, char **flags, + uint64 *offset, int64 *inode, char **filename, + uint64 *file_mapping, uint64 *file_pages, + uint64 *anon_mapping, uint64 *anon_pages, + dev_t *dev) { + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__CYGWIN32__) + do { + // Advance to the start of the next line + stext_ = nextline_; + + // See if we have a complete line in the buffer already + nextline_ = static_cast(memchr (stext_, '\n', etext_ - stext_)); + if (!nextline_) { + // Shift/fill the buffer so we do have a line + int count = etext_ - stext_; + + // Move the current text to the start of the buffer + memmove(ibuf_, stext_, count); + stext_ = ibuf_; + etext_ = ibuf_ + count; + + int nread = 0; // fill up buffer with text + 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 + // garbage from subsequent calls. + if (etext_ != ebuf_ && nread == 0) { + memset(etext_, 0, ebuf_ - etext_); + } + *etext_ = '\n'; // sentinel; safe because ibuf extends 1 char beyond ebuf + nextline_ = static_cast(memchr (stext_, '\n', etext_ + 1 - stext_)); + } + *nextline_ = 0; // turn newline into nul + nextline_ += ((nextline_ < etext_)? 1 : 0); // skip nul if not end of text + // stext_ now points at a nul-terminated line + uint64 tmpstart, tmpend, tmpoffset; + int64 tmpinode; + int major, minor; + unsigned filename_offset = 0; +#if defined(__linux__) + // for now, assume all linuxes have the same format + if (!ParseProcMapsLine( + stext_, + start ? start : &tmpstart, + end ? end : &tmpend, + flags_, + offset ? offset : &tmpoffset, + &major, &minor, + inode ? inode : &tmpinode, &filename_offset)) continue; +#elif defined(__CYGWIN__) || defined(__CYGWIN32__) + // cygwin is like linux, except the third field is the "entry point" + // rather than the offset (see format_process_maps at + // http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/fhandler_process.cc?rev=1.89&content-type=text/x-cvsweb-markup&cvsroot=src + // Offset is always be 0 on cygwin: cygwin implements an mmap + // by loading the whole file and then calling NtMapViewOfSection. + // Cygwin also seems to set its flags kinda randomly; use windows default. + char tmpflags[5]; + if (offset) + *offset = 0; + strcpy(flags_, "r-xp"); + if (sscanf(stext_, "%llx-%llx %4s %llx %x:%x %lld %n", + start ? start : &tmpstart, + end ? end : &tmpend, + tmpflags, + &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 + + // Depending on the Linux kernel being used, there may or may not be a space + // after the inode if there is no filename. sscanf will in such situations + // nondeterministically either fill in filename_offset or not (the results + // differ on multiple calls in the same run even with identical arguments). + // We don't want to wander off somewhere beyond the end of the string. + size_t stext_length = strlen(stext_); + if (filename_offset == 0 || filename_offset > stext_length) + filename_offset = stext_length; + + // We found an entry + if (flags) *flags = flags_; + if (filename) *filename = stext_ + filename_offset; + if (dev) *dev = minor | (major << 8); + + if (using_maps_backing_) { + // Extract and parse physical page backing info. + char *backing_ptr = stext_ + filename_offset + + strlen(stext_+filename_offset); + + // find the second '(' + int paren_count = 0; + while (--backing_ptr > stext_) { + if (*backing_ptr == '(') { + ++paren_count; + if (paren_count >= 2) { + uint64 tmp_file_mapping; + uint64 tmp_file_pages; + uint64 tmp_anon_mapping; + uint64 tmp_anon_pages; + + 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, + anon_pages ? anon_pages : &tmp_anon_pages); + // null terminate the file name (there is a space + // before the first (. + backing_ptr[-1] = 0; + break; + } + } + } + } + + 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); + Buffer object_path; + 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(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 (pid_ == 0) { + CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize, + "/proc/self/path/%s", mapinfo->pr_mapname), + Buffer::kBufSize); + } else { + CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize, + "/proc/%d/path/%s", + static_cast(pid_), mapinfo->pr_mapname), + Buffer::kBufSize); + } + ssize_t len = readlink(object_path.buf_, current_filename_, PATH_MAX); + CHECK_LT(len, PATH_MAX); + if (len < 0) + len = 0; + current_filename_[len] = '\0'; + + 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; + if (filename) *filename = current_filename_; + 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__) + // 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_--) { +#ifdef MH_MAGIC_64 + if (NextExtMachHelper( + hdr, current_image_, current_load_cmd_, + start, end, flags, offset, inode, filename, + file_mapping, file_pages, anon_mapping, + anon_pages, dev)) { + return true; + } +#endif + if (NextExtMachHelper( + hdr, current_image_, current_load_cmd_, + start, end, flags, offset, inode, filename, + file_mapping, file_pages, anon_mapping, + anon_pages, dev)) { + 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(PLATFORM_WINDOWS) + 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(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(dev/256), static_cast(dev%256), + inode, filename); + return (rc < 0 || rc >= bufsize) ? 0 : rc; +} + +namespace tcmalloc { + +// Helper to add the list of mapped shared libraries to a profile. +// Fill formatted "/proc/self/maps" contents into buffer 'buf' of size 'size' +// and return the actual size occupied in 'buf'. We fill wrote_all to true +// if we successfully wrote all proc lines to buf, false else. +// We do not provision for 0-terminating 'buf'. +int FillProcSelfMaps(char buf[], int size, bool* wrote_all) { + ProcMapsIterator::Buffer iterbuf; + ProcMapsIterator it(0, &iterbuf); // 0 means "current pid" + + uint64 start, end, offset; + int64 inode; + char *flags, *filename; + int bytes_written = 0; + *wrote_all = true; + while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) { + const int line_length = it.FormatLine(buf + bytes_written, + size - bytes_written, + start, end, flags, offset, + inode, filename, 0); + if (line_length == 0) + *wrote_all = false; // failed to write this line out + else + bytes_written += line_length; + + } + 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. +void DumpProcSelfMaps(RawFD 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); + RawWrite(fd, linebuf.buf_, written); + } +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.h b/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.h new file mode 100644 index 000000000..77d956ea3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/sysinfo.h @@ -0,0 +1,230 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2006, 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. + +// All functions here are thread-hostile due to file caching unless +// commented otherwise. + +#ifndef _SYSINFO_H_ +#define _SYSINFO_H_ + +#include + +#include +#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__)) +#include // for DWORD +#include // for CreateToolhelp32Snapshot +#endif +#ifdef HAVE_UNISTD_H +#include // for pid_t +#endif +#include // for size_t +#include // for PATH_MAX +#include "base/basictypes.h" +#include "base/logging.h" // for RawFD + +// This getenv function is safe to call before the C runtime is initialized. +// On Windows, it utilizes GetEnvironmentVariable() and on unix it uses +// /proc/self/environ instead calling getenv(). It's intended to be used in +// routines that run before main(), when the state required for getenv() may +// not be set up yet. In particular, errno isn't set up until relatively late +// (after the pthreads library has a chance to make it threadsafe), and +// getenv() doesn't work until then. +// On some platforms, this call will utilize the same, static buffer for +// repeated GetenvBeforeMain() calls. Callers should not expect pointers from +// this routine to be long lived. +// Note that on unix, /proc only has the environment at the time the +// application was started, so this routine ignores setenv() calls/etc. Also +// note it only reads the first 16K of the environment. +extern const char* GetenvBeforeMain(const char* name); + +// 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. Non-trivial for surprising +// reasons, as documented in sysinfo.cc. path must have space PATH_MAX. +extern bool GetUniquePathFromEnv(const char* env_name, char* path); + +extern int GetSystemCPUsCount(); + +// Return true if we're running POSIX (e.g., NPTL on Linux) threads, +// as opposed to a non-POSIX thread library. The thing that we care +// about is whether a thread's pid is the same as the thread that +// spawned it. If so, this function returns true. +// Thread-safe. +// Note: We consider false negatives to be OK. +bool HasPosixThreads(); + +#ifndef SWIG // SWIG doesn't like struct Buffer and variable arguments. + +// 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, 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. pid can be 0 for "self". + explicit ProcMapsIterator(pid_t pid); + + // Create an iterator with specified storage (for use in signal + // handler). "buffer" should point to a ProcMapsIterator::Buffer + // buffer can be NULL in which case a bufer will be allocated. + ProcMapsIterator(pid_t pid, Buffer *buffer); + + // Iterate through maps_backing instead of maps if use_maps_backing + // is true. Otherwise the same as above. buffer can be NULL and + // it will allocate a buffer itself. + ProcMapsIterator(pid_t pid, Buffer *buffer, + bool use_maps_backing); + + // Returns true if the iterator successfully initialized; + 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. 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): + // - + + // : 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. + // + // Any of the result pointers can be NULL if you're not interested + // in those values. + // + // If "flags" and "filename" are passed, they end up pointing to + // storage within the ProcMapsIterator that is valid only until the + // iterator is destroyed or Next() is called again. The caller may + // modify the contents of these strings (up as far as the first NUL, + // and only until the subsequent call to Next()) if desired. + + // 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); + + bool NextExt(uint64 *start, uint64 *end, char **flags, + uint64 *offset, int64 *inode, char **filename, + uint64 *file_mapping, uint64 *file_pages, + uint64 *anon_mapping, uint64 *anon_pages, + dev_t *dev); + + ~ProcMapsIterator(); + + private: + void Init(pid_t pid, Buffer *buffer, bool use_maps_backing); + + char *ibuf_; // input buffer + char *stext_; // start of text + char *etext_; // end of text + char *nextline_; // start of next line + char *ebuf_; // end of buffer (1 char for a nul) +#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__)) + 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 +#elif defined(__sun__) // Solaris + int fd_; + char current_filename_[PATH_MAX]; +#else + int fd_; // filehandle on /proc/*/maps +#endif + pid_t pid_; + char flags_[10]; + Buffer* dynamic_buffer_; // dynamically-allocated Buffer + bool using_maps_backing_; // true if we are looking at maps_backing instead of maps. +}; + +#endif /* #ifndef SWIG */ + +// Helper routines + +namespace tcmalloc { +int FillProcSelfMaps(char buf[], int size, bool* wrote_all); +void DumpProcSelfMaps(RawFD fd); +} + +#endif /* #ifndef _SYSINFO_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/thread_annotations.h b/trunk/3rdparty/gperftools-2-fit/src/base/thread_annotations.h new file mode 100644 index 000000000..b68e7562a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/thread_annotations.h @@ -0,0 +1,133 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Le-Chun Wu +// +// This header file contains the macro definitions for thread safety +// annotations that allow the developers to document the locking policies +// of their multi-threaded code. The annotations can also help program +// analysis tools to identify potential thread safety issues. +// +// The annotations are implemented using clang's "attributes" extension. +// Using the macros defined here instead of the raw clang attributes allows +// for portability and future compatibility. +// +// This functionality is not yet fully implemented in perftools, +// but may be one day. + +#ifndef BASE_THREAD_ANNOTATIONS_H_ +#define BASE_THREAD_ANNOTATIONS_H_ + + +#if defined(__clang__) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + + +// Document if a shared variable/field needs to be protected by a lock. +// GUARDED_BY allows the user to specify a particular lock that should be +// held when accessing the annotated variable, while GUARDED_VAR only +// indicates a shared variable should be guarded (by any lock). GUARDED_VAR +// is primarily used when the client cannot express the name of the lock. +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) +#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded) + +// Document if the memory location pointed to by a pointer should be guarded +// by a lock when dereferencing the pointer. Similar to GUARDED_VAR, +// PT_GUARDED_VAR is primarily used when the client cannot express the name +// of the lock. Note that a pointer variable to a shared memory location +// could itself be a shared variable. For example, if a shared global pointer +// q, which is guarded by mu1, points to a shared memory location that is +// guarded by mu2, q should be annotated as follows: +// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x)) +#define PT_GUARDED_VAR \ + THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded) + +// Document the acquisition order between locks that can be held +// simultaneously by a thread. For any two locks that need to be annotated +// to establish an acquisition order, only one of them needs the annotation. +// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER +// and ACQUIRED_BEFORE.) +#define ACQUIRED_AFTER(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x)) +#define ACQUIRED_BEFORE(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x)) + +// The following three annotations document the lock requirements for +// functions/methods. + +// Document if a function expects certain locks to be held before it is called +#define EXCLUSIVE_LOCKS_REQUIRED(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) + +#define SHARED_LOCKS_REQUIRED(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(x)) + +// Document the locks acquired in the body of the function. These locks +// cannot be held when calling this function (as google3's Mutex locks are +// non-reentrant). +#define LOCKS_EXCLUDED(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x)) + +// Document the lock the annotated function returns without acquiring it. +#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +// Document if a class/type is a lockable type (such as the Mutex class). +#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable) + +// Document if a class is a scoped lockable type (such as the MutexLock class). +#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +// The following annotations specify lock and unlock primitives. +#define EXCLUSIVE_LOCK_FUNCTION(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(x)) + +#define SHARED_LOCK_FUNCTION(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(x)) + +#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(x)) + +#define SHARED_TRYLOCK_FUNCTION(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(x)) + +#define UNLOCK_FUNCTION(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(x)) + +// An escape hatch for thread safety analysis to ignore the annotated function. +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // BASE_THREAD_ANNOTATIONS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.c b/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.c new file mode 100644 index 000000000..2d7beb309 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.c @@ -0,0 +1,84 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2005-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: Markus Gutschke + */ + +#include "config.h" + +#include "base/thread_lister.h" + +#include /* needed for NULL on some powerpc platforms (?!) */ +#include +#include /* for getpid */ + +#ifdef HAVE_SYS_PRCTL +# include +#endif + +#include "base/linuxthreads.h" +/* Include other thread listers here that define THREADS macro + * only when they can provide a good implementation. + */ + +#ifndef THREADS + +/* Default trivial thread lister for single-threaded applications, + * or if the multi-threading code has not been ported, yet. + */ + +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...) { + int rc; + va_list ap; + pid_t pid; + +#ifdef HAVE_SYS_PRCTL + int dumpable = prctl(PR_GET_DUMPABLE, 0); + if (!dumpable) + prctl(PR_SET_DUMPABLE, 1); +#endif + va_start(ap, callback); + 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; +} + +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { + return 1; +} + +#endif /* ifndef THREADS */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.h b/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.h new file mode 100644 index 000000000..6e70b89fe --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/thread_lister.h @@ -0,0 +1,83 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2005-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: Markus Gutschke + */ + +#ifndef _THREAD_LISTER_H +#define _THREAD_LISTER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*ListAllProcessThreadsCallBack)(void *parameter, + int num_threads, + pid_t *thread_pids, + va_list ap); + +/* This function gets the list of all linux threads of the current process + * passes them to the 'callback' along with the 'parameter' pointer; at the + * call back call time all the threads are paused via + * PTRACE_ATTACH. + * The callback is executed from a separate thread which shares only the + * address space, the filesystem, and the filehandles with the caller. Most + * notably, it does not share the same pid and ppid; and if it terminates, + * the rest of the application is still there. 'callback' is supposed to do + * or arrange for TCMalloc_ResumeAllProcessThreads. This happens automatically, if + * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous + * signals are blocked. If the 'callback' decides to unblock them, it must + * ensure that they cannot terminate the application, or that + * TCMalloc_ResumeAllProcessThreads will get called. + * It is an error for the 'callback' to make any library calls that could + * acquire locks. Most notably, this means that most system calls have to + * avoid going through libc. Also, this means that it is not legal to call + * exit() or abort(). + * We return -1 on error and the return value of 'callback' on success. + */ +int TCMalloc_ListAllProcessThreads(void *parameter, + ListAllProcessThreadsCallBack callback, ...); + +/* This function resumes the list of all linux threads that + * TCMalloc_ListAllProcessThreads pauses before giving to its + * callback. The function returns non-zero if at least one thread was + * suspended and has now been resumed. + */ +int TCMalloc_ResumeAllProcessThreads(int num_threads, pid_t *thread_pids); + +#ifdef __cplusplus +} +#endif + +#endif /* _THREAD_LISTER_H */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.cc b/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.cc new file mode 100644 index 000000000..e4805e9e4 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.cc @@ -0,0 +1,143 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Paul Pluzhnikov +// +// Allow dynamic symbol lookup in the kernel VDSO page. +// +// VDSOSupport -- a class representing kernel VDSO (if present). +// + +#include "base/vdso_support.h" + +#ifdef HAVE_VDSO_SUPPORT // defined in vdso_support.h + +#include +#include // for ptrdiff_t + +#include "base/atomicops.h" // for MemoryBarrier +#include "base/logging.h" +#include "base/dynamic_annotations.h" +#include "base/basictypes.h" // for COMPILE_ASSERT + +using base::subtle::MemoryBarrier; + +#ifndef AT_SYSINFO_EHDR +#define AT_SYSINFO_EHDR 33 +#endif + +namespace base { + +const void *VDSOSupport::vdso_base_ = ElfMemImage::kInvalidBase; +VDSOSupport::VDSOSupport() + // If vdso_base_ is still set to kInvalidBase, we got here + // before VDSOSupport::Init has been called. Call it now. + : image_(vdso_base_ == ElfMemImage::kInvalidBase ? Init() : vdso_base_) { +} + +// NOTE: we can't use GoogleOnceInit() below, because we can be +// called by tcmalloc, and none of the *once* stuff may be functional yet. +// +// In addition, we hope that the VDSOSupportHelper constructor +// causes this code to run before there are any threads, and before +// InitGoogle() has executed any chroot or setuid calls. +// +// Finally, even if there is a race here, it is harmless, because +// the operation should be idempotent. +const void *VDSOSupport::Init() { + if (vdso_base_ == ElfMemImage::kInvalidBase) { + // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[] + // on stack, and so glibc works as if VDSO was not present. + // But going directly to kernel via /proc/self/auxv below bypasses + // Valgrind zapping. So we check for Valgrind separately. + if (RunningOnValgrind()) { + vdso_base_ = NULL; + return NULL; + } + int fd = open("/proc/self/auxv", O_RDONLY); + if (fd == -1) { + // Kernel too old to have a VDSO. + vdso_base_ = NULL; + return NULL; + } + ElfW(auxv_t) aux; + while (read(fd, &aux, sizeof(aux)) == sizeof(aux)) { + if (aux.a_type == AT_SYSINFO_EHDR) { + COMPILE_ASSERT(sizeof(vdso_base_) == sizeof(aux.a_un.a_val), + unexpected_sizeof_pointer_NE_sizeof_a_val); + vdso_base_ = reinterpret_cast(aux.a_un.a_val); + break; + } + } + close(fd); + if (vdso_base_ == ElfMemImage::kInvalidBase) { + // Didn't find AT_SYSINFO_EHDR in auxv[]. + vdso_base_ = NULL; + } + } + return vdso_base_; +} + +const void *VDSOSupport::SetBase(const void *base) { + CHECK(base != ElfMemImage::kInvalidBase); + const void *old_base = vdso_base_; + vdso_base_ = base; + image_.Init(base); + return old_base; +} + +bool VDSOSupport::LookupSymbol(const char *name, + const char *version, + int type, + SymbolInfo *info) const { + return image_.LookupSymbol(name, version, type, info); +} + +bool VDSOSupport::LookupSymbolByAddress(const void *address, + SymbolInfo *info_out) const { + return image_.LookupSymbolByAddress(address, info_out); +} + +// We need to make sure VDSOSupport::Init() is called before +// the main() runs, since it might do something like setuid or +// chroot. If VDSOSupport +// is used in any global constructor, this will happen, since +// VDSOSupport's constructor calls Init. But if not, we need to +// ensure it here, with a global constructor of our own. This +// is an allowed exception to the normal rule against non-trivial +// global constructors. +static class VDSOInitHelper { + public: + VDSOInitHelper() { VDSOSupport::Init(); } +} vdso_init_helper; +} + +#endif // HAVE_VDSO_SUPPORT diff --git a/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.h b/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.h new file mode 100644 index 000000000..073386ce2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/base/vdso_support.h @@ -0,0 +1,137 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Paul Pluzhnikov +// +// Allow dynamic symbol lookup in the kernel VDSO page. +// +// VDSO stands for "Virtual Dynamic Shared Object" -- a page of +// executable code, which looks like a shared library, but doesn't +// necessarily exist anywhere on disk, and which gets mmap()ed into +// every process by kernels which support VDSO, such as 2.6.x for 32-bit +// executables, and 2.6.24 and above for 64-bit executables. +// +// More details could be found here: +// http://www.trilithium.com/johan/2005/08/linux-gate/ +// +// VDSOSupport -- a class representing kernel VDSO (if present). +// +// Example usage: +// VDSOSupport vdso; +// VDSOSupport::SymbolInfo info; +// typedef (*FN)(unsigned *, void *, void *); +// FN fn = NULL; +// if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) { +// fn = reinterpret_cast(info.address); +// } + +#ifndef BASE_VDSO_SUPPORT_H_ +#define BASE_VDSO_SUPPORT_H_ + +#include +#include "base/basictypes.h" +#include "base/elf_mem_image.h" + +#ifdef HAVE_ELF_MEM_IMAGE + +// Enable VDSO support only for the architectures/operating systems that +// support it. +#if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) +#define HAVE_VDSO_SUPPORT 1 +#endif + +#include // for NULL + +namespace base { + +// NOTE: this class may be used from within tcmalloc, and can not +// use any memory allocation routines. +class VDSOSupport { + public: + VDSOSupport(); + + typedef ElfMemImage::SymbolInfo SymbolInfo; + typedef ElfMemImage::SymbolIterator SymbolIterator; + + // Answers whether we have a vdso at all. + bool IsPresent() const { return image_.IsPresent(); } + + // Allow to iterate over all VDSO symbols. + SymbolIterator begin() const { return image_.begin(); } + SymbolIterator end() const { return image_.end(); } + + // Look up versioned dynamic symbol in the kernel VDSO. + // Returns false if VDSO is not present, or doesn't contain given + // symbol/version/type combination. + // If info_out != NULL, additional details are filled in. + bool LookupSymbol(const char *name, const char *version, + int symbol_type, SymbolInfo *info_out) const; + + // Find info about symbol (if any) which overlaps given address. + // Returns true if symbol was found; false if VDSO isn't present + // or doesn't have a symbol overlapping given address. + // If info_out != NULL, additional details are filled in. + bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const; + + // Used only for testing. Replace real VDSO base with a mock. + // Returns previous value of vdso_base_. After you are done testing, + // you are expected to call SetBase() with previous value, in order to + // reset state to the way it was. + const void *SetBase(const void *s); + + // Computes vdso_base_ and returns it. Should be called as early as + // possible; before any thread creation, chroot or setuid. + static const void *Init(); + + private: + // image_ represents VDSO ELF image in memory. + // image_.ehdr_ == NULL implies there is no VDSO. + ElfMemImage image_; + + // Cached value of auxv AT_SYSINFO_EHDR, computed once. + // This is a tri-state: + // kInvalidBase => value hasn't been determined yet. + // 0 => there is no VDSO. + // else => vma of VDSO Elf{32,64}_Ehdr. + // + // When testing with mock VDSO, low bit is set. + // The low bit is always available because vdso_base_ is + // page-aligned. + static const void *vdso_base_; + + DISALLOW_COPY_AND_ASSIGN(VDSOSupport); +}; + +} // namespace base + +#endif // HAVE_ELF_MEM_IMAGE + +#endif // BASE_VDSO_SUPPORT_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/central_freelist.cc b/trunk/3rdparty/gperftools-2-fit/src/central_freelist.cc new file mode 100644 index 000000000..d064c2fcb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/central_freelist.cc @@ -0,0 +1,384 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#include "config.h" +#include +#include "central_freelist.h" +#include "internal_logging.h" // for ASSERT, MESSAGE +#include "linked_list.h" // for SLL_Next, SLL_Push, etc +#include "page_heap.h" // for PageHeap +#include "static_vars.h" // for Static + +using std::min; +using std::max; + +namespace tcmalloc { + +void CentralFreeList::Init(size_t cl) { + size_class_ = cl; + tcmalloc::DLL_Init(&empty_); + tcmalloc::DLL_Init(&nonempty_); + num_spans_ = 0; + counter_ = 0; + + max_cache_size_ = kMaxNumTransferEntries; +#ifdef TCMALLOC_SMALL_BUT_SLOW + // Disable the transfer cache for the small footprint case. + cache_size_ = 0; +#else + cache_size_ = 16; +#endif + if (cl > 0) { + // Limit the maximum size of the cache based on the size class. If this + // is not done, large size class objects will consume a lot of memory if + // they just sit in the transfer cache. + int32_t bytes = Static::sizemap()->ByteSizeForClass(cl); + int32_t objs_to_move = Static::sizemap()->num_objects_to_move(cl); + + ASSERT(objs_to_move > 0 && bytes > 0); + // Limit each size class cache to at most 1MB of objects or one entry, + // whichever is greater. Total transfer cache memory used across all + // size classes then can't be greater than approximately + // 1MB * kMaxNumTransferEntries. + // min and max are in parens to avoid macro-expansion on windows. + max_cache_size_ = (min)(max_cache_size_, + (max)(1, (1024 * 1024) / (bytes * objs_to_move))); + cache_size_ = (min)(cache_size_, max_cache_size_); + } + used_slots_ = 0; + ASSERT(cache_size_ <= max_cache_size_); +} + +void CentralFreeList::ReleaseListToSpans(void* start) { + while (start) { + void *next = SLL_Next(start); + ReleaseToSpans(start); + start = next; + } +} + +// MapObjectToSpan should logically be part of ReleaseToSpans. But +// this triggers an optimization bug in gcc 4.5.0. Moving to a +// separate function, and making sure that function isn't inlined, +// seems to fix the problem. It also should be fixed for gcc 4.5.1. +static +#if __GNUC__ == 4 && __GNUC_MINOR__ == 5 && __GNUC_PATCHLEVEL__ == 0 +__attribute__ ((noinline)) +#endif +Span* MapObjectToSpan(void* object) { + const PageID p = reinterpret_cast(object) >> kPageShift; + Span* span = Static::pageheap()->GetDescriptor(p); + return span; +} + +void CentralFreeList::ReleaseToSpans(void* object) { + Span* span = MapObjectToSpan(object); + ASSERT(span != NULL); + ASSERT(span->refcount > 0); + + // If span is empty, move it to non-empty list + if (span->objects == NULL) { + tcmalloc::DLL_Remove(span); + tcmalloc::DLL_Prepend(&nonempty_, span); + } + + // The following check is expensive, so it is disabled by default + if (false) { + // Check that object does not occur in list + int got = 0; + for (void* p = span->objects; p != NULL; p = *((void**) p)) { + ASSERT(p != object); + got++; + } + ASSERT(got + span->refcount == + (span->length<ByteSizeForClass(span->sizeclass)); + } + + counter_++; + span->refcount--; + if (span->refcount == 0) { + counter_ -= ((span->length<ByteSizeForClass(span->sizeclass)); + tcmalloc::DLL_Remove(span); + --num_spans_; + + // Release central list lock while operating on pageheap + lock_.Unlock(); + { + SpinLockHolder h(Static::pageheap_lock()); + Static::pageheap()->Delete(span); + } + lock_.Lock(); + } else { + *(reinterpret_cast(object)) = span->objects; + span->objects = object; + } +} + +bool CentralFreeList::EvictRandomSizeClass( + int locked_size_class, bool force) { + static int race_counter = 0; + int t = race_counter++; // Updated without a lock, but who cares. + if (t >= Static::num_size_classes()) { + while (t >= Static::num_size_classes()) { + t -= Static::num_size_classes(); + } + race_counter = t; + } + ASSERT(t >= 0); + ASSERT(t < Static::num_size_classes()); + if (t == locked_size_class) return false; + return Static::central_cache()[t].ShrinkCache(locked_size_class, force); +} + +bool CentralFreeList::MakeCacheSpace() { + // Is there room in the cache? + if (used_slots_ < cache_size_) return true; + // Check if we can expand this cache? + if (cache_size_ == max_cache_size_) return false; + // Ok, we'll try to grab an entry from some other size class. + if (EvictRandomSizeClass(size_class_, false) || + EvictRandomSizeClass(size_class_, true)) { + // Succeeded in evicting, we're going to make our cache larger. + // However, we may have dropped and re-acquired the lock in + // EvictRandomSizeClass (via ShrinkCache and the LockInverter), so the + // cache_size may have changed. Therefore, check and verify that it is + // still OK to increase the cache_size. + if (cache_size_ < max_cache_size_) { + cache_size_++; + return true; + } + } + return false; +} + + +namespace { +class LockInverter { + private: + SpinLock *held_, *temp_; + public: + inline explicit LockInverter(SpinLock* held, SpinLock *temp) + : held_(held), temp_(temp) { held_->Unlock(); temp_->Lock(); } + inline ~LockInverter() { temp_->Unlock(); held_->Lock(); } +}; +} + +// This function is marked as NO_THREAD_SAFETY_ANALYSIS because it uses +// LockInverter to release one lock and acquire another in scoped-lock +// style, which our current annotation/analysis does not support. +bool CentralFreeList::ShrinkCache(int locked_size_class, bool force) + NO_THREAD_SAFETY_ANALYSIS { + // Start with a quick check without taking a lock. + if (cache_size_ == 0) return false; + // We don't evict from a full cache unless we are 'forcing'. + if (force == false && used_slots_ == cache_size_) return false; + + // Grab lock, but first release the other lock held by this thread. We use + // the lock inverter to ensure that we never hold two size class locks + // concurrently. That can create a deadlock because there is no well + // defined nesting order. + LockInverter li(&Static::central_cache()[locked_size_class].lock_, &lock_); + ASSERT(used_slots_ <= cache_size_); + ASSERT(0 <= cache_size_); + if (cache_size_ == 0) return false; + if (used_slots_ == cache_size_) { + if (force == false) return false; + // ReleaseListToSpans releases the lock, so we have to make all the + // updates to the central list before calling it. + cache_size_--; + used_slots_--; + ReleaseListToSpans(tc_slots_[used_slots_].head); + return true; + } + cache_size_--; + return true; +} + +void CentralFreeList::InsertRange(void *start, void *end, int N) { + SpinLockHolder h(&lock_); + if (N == Static::sizemap()->num_objects_to_move(size_class_) && + MakeCacheSpace()) { + int slot = used_slots_++; + ASSERT(slot >=0); + ASSERT(slot < max_cache_size_); + TCEntry *entry = &tc_slots_[slot]; + entry->head = start; + entry->tail = end; + return; + } + ReleaseListToSpans(start); +} + +int CentralFreeList::RemoveRange(void **start, void **end, int N) { + ASSERT(N > 0); + lock_.Lock(); + if (N == Static::sizemap()->num_objects_to_move(size_class_) && + used_slots_ > 0) { + int slot = --used_slots_; + ASSERT(slot >= 0); + TCEntry *entry = &tc_slots_[slot]; + *start = entry->head; + *end = entry->tail; + lock_.Unlock(); + return N; + } + + int result = 0; + *start = NULL; + *end = NULL; + // TODO: Prefetch multiple TCEntries? + result = FetchFromOneSpansSafe(N, start, end); + if (result != 0) { + while (result < N) { + int n; + void* head = NULL; + void* tail = NULL; + n = FetchFromOneSpans(N - result, &head, &tail); + if (!n) break; + result += n; + SLL_PushRange(start, head, tail); + } + } + lock_.Unlock(); + return result; +} + + +int CentralFreeList::FetchFromOneSpansSafe(int N, void **start, void **end) { + int result = FetchFromOneSpans(N, start, end); + if (!result) { + Populate(); + result = FetchFromOneSpans(N, start, end); + } + return result; +} + +int CentralFreeList::FetchFromOneSpans(int N, void **start, void **end) { + if (tcmalloc::DLL_IsEmpty(&nonempty_)) return 0; + Span* span = nonempty_.next; + + ASSERT(span->objects != NULL); + + int result = 0; + void *prev, *curr; + curr = span->objects; + do { + prev = curr; + curr = *(reinterpret_cast(curr)); + } while (++result < N && curr != NULL); + + if (curr == NULL) { + // Move to empty list + tcmalloc::DLL_Remove(span); + tcmalloc::DLL_Prepend(&empty_, span); + } + + *start = span->objects; + *end = prev; + span->objects = curr; + SLL_SetNext(*end, NULL); + span->refcount += result; + counter_ -= result; + return result; +} + +// Fetch memory from the system and add to the central cache freelist. +void CentralFreeList::Populate() { + // Release central list lock while operating on pageheap + lock_.Unlock(); + const size_t npages = Static::sizemap()->class_to_pages(size_class_); + + Span* span; + { + SpinLockHolder h(Static::pageheap_lock()); + span = Static::pageheap()->New(npages); + if (span) Static::pageheap()->RegisterSizeClass(span, size_class_); + } + if (span == NULL) { + Log(kLog, __FILE__, __LINE__, + "tcmalloc: allocation failed", npages << kPageShift); + lock_.Lock(); + return; + } + ASSERT(span->length == npages); + // Cache sizeclass info eagerly. Locking is not necessary. + // (Instead of being eager, we could just replace any stale info + // about this span, but that seems to be no better in practice.) + for (int i = 0; i < npages; i++) { + Static::pageheap()->SetCachedSizeClass(span->start + i, size_class_); + } + + // Split the block into pieces and add to the free-list + // TODO: coloring of objects to avoid cache conflicts? + void** tail = &span->objects; + char* ptr = reinterpret_cast(span->start << kPageShift); + char* limit = ptr + (npages << kPageShift); + const size_t size = Static::sizemap()->ByteSizeForClass(size_class_); + int num = 0; + while (ptr + size <= limit) { + *tail = ptr; + tail = reinterpret_cast(ptr); + ptr += size; + num++; + } + ASSERT(ptr <= limit); + *tail = NULL; + span->refcount = 0; // No sub-object in use yet + + // Add span to list of non-empty spans + lock_.Lock(); + tcmalloc::DLL_Prepend(&nonempty_, span); + ++num_spans_; + counter_ += num; +} + +int CentralFreeList::tc_length() { + SpinLockHolder h(&lock_); + return used_slots_ * Static::sizemap()->num_objects_to_move(size_class_); +} + +size_t CentralFreeList::OverheadBytes() { + SpinLockHolder h(&lock_); + if (size_class_ == 0) { // 0 holds the 0-sized allocations + return 0; + } + const size_t pages_per_span = Static::sizemap()->class_to_pages(size_class_); + const size_t object_size = Static::sizemap()->class_to_size(size_class_); + ASSERT(object_size > 0); + const size_t overhead_per_span = (pages_per_span * kPageSize) % object_size; + return num_spans_ * overhead_per_span; +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/central_freelist.h b/trunk/3rdparty/gperftools-2-fit/src/central_freelist.h new file mode 100644 index 000000000..0f66e0cc0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/central_freelist.h @@ -0,0 +1,211 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#ifndef TCMALLOC_CENTRAL_FREELIST_H_ +#define TCMALLOC_CENTRAL_FREELIST_H_ + +#include "config.h" +#include // for size_t +#ifdef HAVE_STDINT_H +#include // for int32_t +#endif +#include "base/spinlock.h" +#include "base/thread_annotations.h" +#include "common.h" +#include "span.h" + +namespace tcmalloc { + +// Data kept per size-class in central cache. +class CentralFreeList { + public: + // A CentralFreeList may be used before its constructor runs. + // So we prevent lock_'s constructor from doing anything to the + // lock_ state. + CentralFreeList() : lock_(base::LINKER_INITIALIZED) { } + + void Init(size_t cl); + + // These methods all do internal locking. + + // Insert the specified range into the central freelist. N is the number of + // elements in the range. RemoveRange() is the opposite operation. + void InsertRange(void *start, void *end, int N); + + // Returns the actual number of fetched elements and sets *start and *end. + int RemoveRange(void **start, void **end, int N); + + // Returns the number of free objects in cache. + int length() { + SpinLockHolder h(&lock_); + return counter_; + } + + // Returns the number of free objects in the transfer cache. + int tc_length(); + + // Returns the memory overhead (internal fragmentation) attributable + // to the freelist. This is memory lost when the size of elements + // in a freelist doesn't exactly divide the page-size (an 8192-byte + // page full of 5-byte objects would have 2 bytes memory overhead). + size_t OverheadBytes(); + + // Lock/Unlock the internal SpinLock. Used on the pthread_atfork call + // to set the lock in a consistent state before the fork. + void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_) { + lock_.Lock(); + } + + void Unlock() UNLOCK_FUNCTION(lock_) { + lock_.Unlock(); + } + + private: + // TransferCache is used to cache transfers of + // sizemap.num_objects_to_move(size_class) back and forth between + // thread caches and the central cache for a given size class. + struct TCEntry { + void *head; // Head of chain of objects. + void *tail; // Tail of chain of objects. + }; + + // A central cache freelist can have anywhere from 0 to kMaxNumTransferEntries + // slots to put link list chains into. +#ifdef TCMALLOC_SMALL_BUT_SLOW + // For the small memory model, the transfer cache is not used. + static const int kMaxNumTransferEntries = 0; +#else + // Starting point for the the maximum number of entries in the transfer cache. + // This actual maximum for a given size class may be lower than this + // maximum value. + static const int kMaxNumTransferEntries = 64; +#endif + + // REQUIRES: lock_ is held + // Remove object from cache and return. + // Return NULL if no free entries in cache. + int FetchFromOneSpans(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock_ is held + // Remove object from cache and return. Fetches + // from pageheap if cache is empty. Only returns + // NULL on allocation failure. + int FetchFromOneSpansSafe(int N, void **start, void **end) EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock_ is held + // Release a linked list of objects to spans. + // May temporarily release lock_. + void ReleaseListToSpans(void *start) EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock_ is held + // Release an object to spans. + // May temporarily release lock_. + void ReleaseToSpans(void* object) EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock_ is held + // Populate cache by fetching from the page heap. + // May temporarily release lock_. + void Populate() EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock is held. + // Tries to make room for a TCEntry. If the cache is full it will try to + // expand it at the cost of some other cache size. Return false if there is + // no space. + bool MakeCacheSpace() EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // REQUIRES: lock_ for locked_size_class is held. + // Picks a "random" size class to steal TCEntry slot from. In reality it + // just iterates over the sizeclasses but does so without taking a lock. + // Returns true on success. + // May temporarily lock a "random" size class. + static bool EvictRandomSizeClass(int locked_size_class, bool force); + + // REQUIRES: lock_ is *not* held. + // Tries to shrink the Cache. If force is true it will relase objects to + // spans if it allows it to shrink the cache. Return false if it failed to + // shrink the cache. Decrements cache_size_ on succeess. + // May temporarily take lock_. If it takes lock_, the locked_size_class + // lock is released to keep the thread from holding two size class locks + // concurrently which could lead to a deadlock. + bool ShrinkCache(int locked_size_class, bool force) LOCKS_EXCLUDED(lock_); + + // This lock protects all the data members. cached_entries and cache_size_ + // may be looked at without holding the lock. + SpinLock lock_; + + // We keep linked lists of empty and non-empty spans. + size_t size_class_; // My size class + Span empty_; // Dummy header for list of empty spans + Span nonempty_; // Dummy header for list of non-empty spans + size_t num_spans_; // Number of spans in empty_ plus nonempty_ + size_t counter_; // Number of free objects in cache entry + + // Here we reserve space for TCEntry cache slots. Space is preallocated + // for the largest possible number of entries than any one size class may + // accumulate. Not all size classes are allowed to accumulate + // kMaxNumTransferEntries, so there is some wasted space for those size + // classes. + TCEntry tc_slots_[kMaxNumTransferEntries]; + + // Number of currently used cached entries in tc_slots_. This variable is + // updated under a lock but can be read without one. + int32_t used_slots_; + // The current number of slots for this size class. This is an + // adaptive value that is increased if there is lots of traffic + // on a given size class. + int32_t cache_size_; + // Maximum size of the cache for a given size class. + int32_t max_cache_size_; +}; + +// Pads each CentralCache object to multiple of 64 bytes. Since some +// compilers (such as MSVC) don't like it when the padding is 0, I use +// template specialization to remove the padding entirely when +// sizeof(CentralFreeList) is a multiple of 64. +template +class CentralFreeListPaddedTo : public CentralFreeList { + private: + char pad_[64 - kFreeListSizeMod64]; +}; + +template<> +class CentralFreeListPaddedTo<0> : public CentralFreeList { +}; + +class CentralFreeListPadded : public CentralFreeListPaddedTo< + sizeof(CentralFreeList) % 64> { +}; + +} // namespace tcmalloc + +#endif // TCMALLOC_CENTRAL_FREELIST_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/common.cc b/trunk/3rdparty/gperftools-2-fit/src/common.cc new file mode 100644 index 000000000..5e9e11ee5 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/common.cc @@ -0,0 +1,291 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#include // for getenv and strtol +#include "config.h" +#include "common.h" +#include "system-alloc.h" +#include "base/spinlock.h" +#include "getenv_safe.h" // TCMallocGetenvSafe + +namespace tcmalloc { + +// Define the maximum number of object per classe type to transfer between +// thread and central caches. +static int32 FLAGS_tcmalloc_transfer_num_objects; + +static const int32 kDefaultTransferNumObjecs = 32; + +// The init function is provided to explicit initialize the variable value +// from the env. var to avoid C++ global construction that might defer its +// initialization after a malloc/new call. +static inline void InitTCMallocTransferNumObjects() +{ + if (FLAGS_tcmalloc_transfer_num_objects == 0) { + const char *envval = TCMallocGetenvSafe("TCMALLOC_TRANSFER_NUM_OBJ"); + FLAGS_tcmalloc_transfer_num_objects = !envval ? kDefaultTransferNumObjecs : + strtol(envval, NULL, 10); + } +} + +// Note: the following only works for "n"s that fit in 32-bits, but +// that is fine since we only use it for small sizes. +static inline int LgFloor(size_t n) { + int log = 0; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + size_t x = n >> shift; + if (x != 0) { + n = x; + log += shift; + } + } + ASSERT(n == 1); + return log; +} + +int AlignmentForSize(size_t size) { + int alignment = kAlignment; + if (size > kMaxSize) { + // Cap alignment at kPageSize for large sizes. + alignment = kPageSize; + } else if (size >= 128) { + // Space wasted due to alignment is at most 1/8, i.e., 12.5%. + alignment = (1 << LgFloor(size)) / 8; + } else if (size >= kMinAlign) { + // We need an alignment of at least 16 bytes to satisfy + // requirements for some SSE types. + alignment = kMinAlign; + } + // Maximum alignment allowed is page size alignment. + if (alignment > kPageSize) { + alignment = kPageSize; + } + CHECK_CONDITION(size < kMinAlign || alignment >= kMinAlign); + CHECK_CONDITION((alignment & (alignment - 1)) == 0); + return alignment; +} + +int SizeMap::NumMoveSize(size_t size) { + if (size == 0) return 0; + // Use approx 64k transfers between thread and central caches. + int num = static_cast(64.0 * 1024.0 / size); + if (num < 2) num = 2; + + // Avoid bringing too many objects into small object free lists. + // If this value is too large: + // - We waste memory with extra objects sitting in the thread caches. + // - The central freelist holds its lock for too long while + // building a linked list of objects, slowing down the allocations + // of other threads. + // If this value is too small: + // - We go to the central freelist too often and we have to acquire + // its lock each time. + // This value strikes a balance between the constraints above. + if (num > FLAGS_tcmalloc_transfer_num_objects) + num = FLAGS_tcmalloc_transfer_num_objects; + + return num; +} + +// Initialize the mapping arrays +void SizeMap::Init() { + InitTCMallocTransferNumObjects(); + + // Do some sanity checking on add_amount[]/shift_amount[]/class_array[] + if (ClassIndex(0) != 0) { + Log(kCrash, __FILE__, __LINE__, + "Invalid class index for size 0", ClassIndex(0)); + } + if (ClassIndex(kMaxSize) >= sizeof(class_array_)) { + Log(kCrash, __FILE__, __LINE__, + "Invalid class index for kMaxSize", ClassIndex(kMaxSize)); + } + + // Compute the size classes we want to use + int sc = 1; // Next size class to assign + int alignment = kAlignment; + CHECK_CONDITION(kAlignment <= kMinAlign); + for (size_t size = kAlignment; size <= kMaxSize; size += alignment) { + alignment = AlignmentForSize(size); + CHECK_CONDITION((size % alignment) == 0); + + int blocks_to_move = NumMoveSize(size) / 4; + size_t psize = 0; + do { + psize += kPageSize; + // Allocate enough pages so leftover is less than 1/8 of total. + // This bounds wasted space to at most 12.5%. + while ((psize % size) > (psize >> 3)) { + psize += kPageSize; + } + // Continue to add pages until there are at least as many objects in + // the span as are needed when moving objects from the central + // freelists and spans to the thread caches. + } while ((psize / size) < (blocks_to_move)); + const size_t my_pages = psize >> kPageShift; + + if (sc > 1 && my_pages == class_to_pages_[sc-1]) { + // See if we can merge this into the previous class without + // increasing the fragmentation of the previous class. + const size_t my_objects = (my_pages << kPageShift) / size; + const size_t prev_objects = (class_to_pages_[sc-1] << kPageShift) + / class_to_size_[sc-1]; + if (my_objects == prev_objects) { + // Adjust last class to include this size + class_to_size_[sc-1] = size; + continue; + } + } + + // Add new class + class_to_pages_[sc] = my_pages; + class_to_size_[sc] = size; + sc++; + } + num_size_classes = sc; + if (sc > kClassSizesMax) { + Log(kCrash, __FILE__, __LINE__, + "too many size classes: (found vs. max)", sc, kClassSizesMax); + } + + // Initialize the mapping arrays + int next_size = 0; + for (int c = 1; c < num_size_classes; c++) { + const int max_size_in_class = class_to_size_[c]; + for (int s = next_size; s <= max_size_in_class; s += kAlignment) { + class_array_[ClassIndex(s)] = c; + } + next_size = max_size_in_class + kAlignment; + } + + // Double-check sizes just to be safe + for (size_t size = 0; size <= kMaxSize;) { + const int sc = SizeClass(size); + if (sc <= 0 || sc >= num_size_classes) { + Log(kCrash, __FILE__, __LINE__, + "Bad size class (class, size)", sc, size); + } + if (sc > 1 && size <= class_to_size_[sc-1]) { + Log(kCrash, __FILE__, __LINE__, + "Allocating unnecessarily large class (class, size)", sc, size); + } + const size_t s = class_to_size_[sc]; + if (size > s || s == 0) { + Log(kCrash, __FILE__, __LINE__, + "Bad (class, size, requested)", sc, s, size); + } + if (size <= kMaxSmallSize) { + size += 8; + } else { + size += 128; + } + } + + // Our fast-path aligned allocation functions rely on 'naturally + // aligned' sizes to produce aligned addresses. Lets check if that + // holds for size classes that we produced. + // + // I.e. we're checking that + // + // align = (1 << shift), malloc(i * align) % align == 0, + // + // for all align values up to kPageSize. + for (size_t align = kMinAlign; align <= kPageSize; align <<= 1) { + for (size_t size = align; size < kPageSize; size += align) { + CHECK_CONDITION(class_to_size_[SizeClass(size)] % align == 0); + } + } + + // Initialize the num_objects_to_move array. + for (size_t cl = 1; cl < num_size_classes; ++cl) { + num_objects_to_move_[cl] = NumMoveSize(ByteSizeForClass(cl)); + } +} + +// Metadata allocator -- keeps stats about how many bytes allocated. +static uint64_t metadata_system_bytes_ = 0; +static const size_t kMetadataAllocChunkSize = 8*1024*1024; +// As ThreadCache objects are allocated with MetaDataAlloc, and also +// CACHELINE_ALIGNED, we must use the same alignment as TCMalloc_SystemAlloc. +static const size_t kMetadataAllignment = sizeof(MemoryAligner); + +static char *metadata_chunk_alloc_; +static size_t metadata_chunk_avail_; + +static SpinLock metadata_alloc_lock(SpinLock::LINKER_INITIALIZED); + +void* MetaDataAlloc(size_t bytes) { + if (bytes >= kMetadataAllocChunkSize) { + void *rv = TCMalloc_SystemAlloc(bytes, + NULL, kMetadataAllignment); + if (rv != NULL) { + metadata_system_bytes_ += bytes; + } + return rv; + } + + SpinLockHolder h(&metadata_alloc_lock); + + // the following works by essentially turning address to integer of + // log_2 kMetadataAllignment size and negating it. I.e. negated + // value + original value gets 0 and that's what we want modulo + // kMetadataAllignment. Note, we negate before masking higher bits + // off, otherwise we'd have to mask them off after negation anyways. + intptr_t alignment = -reinterpret_cast(metadata_chunk_alloc_) & (kMetadataAllignment-1); + + if (metadata_chunk_avail_ < bytes + alignment) { + size_t real_size; + void *ptr = TCMalloc_SystemAlloc(kMetadataAllocChunkSize, + &real_size, kMetadataAllignment); + if (ptr == NULL) { + return NULL; + } + + metadata_chunk_alloc_ = static_cast(ptr); + metadata_chunk_avail_ = real_size; + + alignment = 0; + } + + void *rv = static_cast(metadata_chunk_alloc_ + alignment); + bytes += alignment; + metadata_chunk_alloc_ += bytes; + metadata_chunk_avail_ -= bytes; + metadata_system_bytes_ += bytes; + return rv; +} + +uint64_t metadata_system_bytes() { return metadata_system_bytes_; } + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/common.h b/trunk/3rdparty/gperftools-2-fit/src/common.h new file mode 100644 index 000000000..caa3e4a2a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/common.h @@ -0,0 +1,309 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat +// +// Common definitions for tcmalloc code. + +#ifndef TCMALLOC_COMMON_H_ +#define TCMALLOC_COMMON_H_ + +#include "config.h" +#include // for size_t +#ifdef HAVE_STDINT_H +#include // for uintptr_t, uint64_t +#endif +#include "internal_logging.h" // for ASSERT, etc +#include "base/basictypes.h" // for LIKELY, etc + +// Type that can hold a page number +typedef uintptr_t PageID; + +// Type that can hold the length of a run of pages +typedef uintptr_t Length; + +//------------------------------------------------------------------- +// Configuration +//------------------------------------------------------------------- + +#if defined(TCMALLOC_ALIGN_8BYTES) +// Unless we force to use 8 bytes alignment we use an alignment of +// at least 16 bytes to statisfy requirements for some SSE types. +// Keep in mind when using the 16 bytes alignment you can have a space +// waste due alignment of 25%. (eg malloc of 24 bytes will get 32 bytes) +static const size_t kMinAlign = 8; +#else +static const size_t kMinAlign = 16; +#endif + +// Using large pages speeds up the execution at a cost of larger memory use. +// Deallocation may speed up by a factor as the page map gets 8x smaller, so +// lookups in the page map result in fewer L2 cache misses, which translates to +// speedup for application/platform combinations with high L2 cache pressure. +// As the number of size classes increases with large pages, we increase +// the thread cache allowance to avoid passing more free ranges to and from +// central lists. Also, larger pages are less likely to get freed. +// These two factors cause a bounded increase in memory use. +#if defined(TCMALLOC_PAGE_SIZE_SHIFT) +static const size_t kPageShift = TCMALLOC_PAGE_SIZE_SHIFT; +#else +static const size_t kPageShift = 13; +#endif + +static const size_t kClassSizesMax = 128; + +static const size_t kMaxThreadCacheSize = 4 << 20; + +static const size_t kPageSize = 1 << kPageShift; +static const size_t kMaxSize = 256 * 1024; +static const size_t kAlignment = 8; +// For all span-lengths <= kMaxPages we keep an exact-size list in PageHeap. +static const size_t kMaxPages = 1 << (20 - kPageShift); + +// Default bound on the total amount of thread caches. +#ifdef TCMALLOC_SMALL_BUT_SLOW +// Make the overall thread cache no bigger than that of a single thread +// for the small memory footprint case. +static const size_t kDefaultOverallThreadCacheSize = kMaxThreadCacheSize; +#else +static const size_t kDefaultOverallThreadCacheSize = 8u * kMaxThreadCacheSize; +#endif + +// Lower bound on the per-thread cache sizes +static const size_t kMinThreadCacheSize = kMaxSize * 2; + +// The number of bytes one ThreadCache will steal from another when +// the first ThreadCache is forced to Scavenge(), delaying the +// next call to Scavenge for this thread. +static const size_t kStealAmount = 1 << 16; + +// The number of times that a deallocation can cause a freelist to +// go over its max_length() before shrinking max_length(). +static const int kMaxOverages = 3; + +// Maximum length we allow a per-thread free-list to have before we +// move objects from it into the corresponding central free-list. We +// want this big to avoid locking the central free-list too often. It +// should not hurt to make this list somewhat big because the +// scavenging code will shrink it down when its contents are not in use. +static const int kMaxDynamicFreeListLength = 8192; + +static const Length kMaxValidPages = (~static_cast(0)) >> kPageShift; + +#if __aarch64__ || __x86_64__ || _M_AMD64 || _M_ARM64 +// All current x86_64 processors only look at the lower 48 bits in +// virtual to physical address translation. The top 16 are all same as +// bit 47. And bit 47 value 1 reserved for kernel-space addresses in +// practice. So it is actually 47 usable bits from malloc +// perspective. This lets us use faster two level page maps on this +// architecture. +// +// There is very similar story on 64-bit arms except it has full 48 +// bits for user-space. Because of that, and because in principle OSes +// can start giving some of highest-bit-set addresses to user-space, +// we don't bother to limit x86 to 47 bits. +// +// As of now there are published plans to add more bits to x86-64 +// virtual address space, but since 48 bits has been norm for long +// time and lots of software is relying on it, it will be opt-in from +// OS perspective. So we can keep doing "48 bits" at least for now. +static const int kAddressBits = (sizeof(void*) < 8 ? (8 * sizeof(void*)) : 48); +#else +// mipsen and ppcs have more general hardware so we have to support +// full 64-bits of addresses. +static const int kAddressBits = 8 * sizeof(void*); +#endif + +namespace tcmalloc { + +// Convert byte size into pages. This won't overflow, but may return +// an unreasonably large value if bytes is huge enough. +inline Length pages(size_t bytes) { + return (bytes >> kPageShift) + + ((bytes & (kPageSize - 1)) > 0 ? 1 : 0); +} + +// For larger allocation sizes, we use larger memory alignments to +// reduce the number of size classes. +int AlignmentForSize(size_t size); + +// Size-class information + mapping +class SizeMap { + private: + //------------------------------------------------------------------- + // Mapping from size to size_class and vice versa + //------------------------------------------------------------------- + + // Sizes <= 1024 have an alignment >= 8. So for such sizes we have an + // array indexed by ceil(size/8). Sizes > 1024 have an alignment >= 128. + // So for these larger sizes we have an array indexed by ceil(size/128). + // + // We flatten both logical arrays into one physical array and use + // arithmetic to compute an appropriate index. The constants used by + // ClassIndex() were selected to make the flattening work. + // + // Examples: + // Size Expression Index + // ------------------------------------------------------- + // 0 (0 + 7) / 8 0 + // 1 (1 + 7) / 8 1 + // ... + // 1024 (1024 + 7) / 8 128 + // 1025 (1025 + 127 + (120<<7)) / 128 129 + // ... + // 32768 (32768 + 127 + (120<<7)) / 128 376 + static const int kMaxSmallSize = 1024; + static const size_t kClassArraySize = + ((kMaxSize + 127 + (120 << 7)) >> 7) + 1; + unsigned char class_array_[kClassArraySize]; + + static inline size_t SmallSizeClass(size_t s) { + return (static_cast(s) + 7) >> 3; + } + + static inline size_t LargeSizeClass(size_t s) { + return (static_cast(s) + 127 + (120 << 7)) >> 7; + } + + // If size is no more than kMaxSize, compute index of the + // class_array[] entry for it, putting the class index in output + // parameter idx and returning true. Otherwise return false. + static inline bool ATTRIBUTE_ALWAYS_INLINE ClassIndexMaybe(size_t s, + uint32* idx) { + if (PREDICT_TRUE(s <= kMaxSmallSize)) { + *idx = (static_cast(s) + 7) >> 3; + return true; + } else if (s <= kMaxSize) { + *idx = (static_cast(s) + 127 + (120 << 7)) >> 7; + return true; + } + return false; + } + + // Compute index of the class_array[] entry for a given size + static inline size_t ClassIndex(size_t s) { + // Use unsigned arithmetic to avoid unnecessary sign extensions. + ASSERT(0 <= s); + ASSERT(s <= kMaxSize); + if (PREDICT_TRUE(s <= kMaxSmallSize)) { + return SmallSizeClass(s); + } else { + return LargeSizeClass(s); + } + } + + // Number of objects to move between a per-thread list and a central + // list in one shot. We want this to be not too small so we can + // amortize the lock overhead for accessing the central list. Making + // it too big may temporarily cause unnecessary memory wastage in the + // per-thread free list until the scavenger cleans up the list. + int num_objects_to_move_[kClassSizesMax]; + + int NumMoveSize(size_t size); + + // Mapping from size class to max size storable in that class + int32 class_to_size_[kClassSizesMax]; + + // Mapping from size class to number of pages to allocate at a time + size_t class_to_pages_[kClassSizesMax]; + + public: + size_t num_size_classes; + + // Constructor should do nothing since we rely on explicit Init() + // call, which may or may not be called before the constructor runs. + SizeMap() { } + + // Initialize the mapping arrays + void Init(); + + inline int SizeClass(size_t size) { + return class_array_[ClassIndex(size)]; + } + + // Check if size is small enough to be representable by a size + // class, and if it is, put matching size class into *cl. Returns + // true iff matching size class was found. + inline bool ATTRIBUTE_ALWAYS_INLINE GetSizeClass(size_t size, uint32* cl) { + uint32 idx; + if (!ClassIndexMaybe(size, &idx)) { + return false; + } + *cl = class_array_[idx]; + return true; + } + + // Get the byte-size for a specified class + inline int32 ATTRIBUTE_ALWAYS_INLINE ByteSizeForClass(uint32 cl) { + return class_to_size_[cl]; + } + + // Mapping from size class to max size storable in that class + inline int32 class_to_size(uint32 cl) { + return class_to_size_[cl]; + } + + // Mapping from size class to number of pages to allocate at a time + inline size_t class_to_pages(uint32 cl) { + return class_to_pages_[cl]; + } + + // Number of objects to move between a per-thread list and a central + // list in one shot. We want this to be not too small so we can + // amortize the lock overhead for accessing the central list. Making + // it too big may temporarily cause unnecessary memory wastage in the + // per-thread free list until the scavenger cleans up the list. + inline int num_objects_to_move(uint32 cl) { + return num_objects_to_move_[cl]; + } +}; + +// Allocates "bytes" worth of memory and returns it. Increments +// metadata_system_bytes appropriately. May return NULL if allocation +// fails. Requires pageheap_lock is held. +void* MetaDataAlloc(size_t bytes); + +// Returns the total number of bytes allocated from the system. +// Requires pageheap_lock is held. +uint64_t metadata_system_bytes(); + +// size/depth are made the same size as a pointer so that some generic +// code below can conveniently cast them back and forth to void*. +static const int kMaxStackDepth = 31; +struct StackTrace { + uintptr_t size; // Size of object + uintptr_t depth; // Number of PC values stored in array below + void* stack[kMaxStackDepth]; +}; + +} // namespace tcmalloc + +#endif // TCMALLOC_COMMON_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/config.h.in b/trunk/3rdparty/gperftools-2-fit/src/config.h.in new file mode 100644 index 000000000..31d57ab8d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/config.h.in @@ -0,0 +1,279 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + + +#ifndef GPERFTOOLS_CONFIG_H_ +#define GPERFTOOLS_CONFIG_H_ + + +/* enable aggressive decommit by default */ +#undef ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT + +/* Build new/delete operators for overaligned types */ +#undef ENABLE_ALIGNED_NEW_DELETE + +/* Build runtime detection for sized delete */ +#undef ENABLE_DYNAMIC_SIZED_DELETE + +/* report large allocation */ +#undef ENABLE_LARGE_ALLOC_REPORT + +/* Build sized deletion operators */ +#undef ENABLE_SIZED_DELETE + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASM_PTRACE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CONFLICT_SIGNAL_H + +/* define if the compiler supports basic C++11 syntax */ +#undef HAVE_CXX11 + +/* Define to 1 if you have the header file. */ +#undef HAVE_CYGWIN_SIGNAL_H + +/* Define to 1 if you have the declaration of `backtrace', and to 0 if you + don't. */ +#undef HAVE_DECL_BACKTRACE + +/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't. + */ +#undef HAVE_DECL_CFREE + +/* Define to 1 if you have the declaration of `memalign', and to 0 if you + don't. */ +#undef HAVE_DECL_MEMALIGN + +/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you + don't. */ +#undef HAVE_DECL_NANOSLEEP + +/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if + you don't. */ +#undef HAVE_DECL_POSIX_MEMALIGN + +/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you + don't. */ +#undef HAVE_DECL_PVALLOC + +/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't. + */ +#undef HAVE_DECL_SLEEP + +/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't. + */ +#undef HAVE_DECL_VALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if the system has the type `Elf32_Versym'. */ +#undef HAVE_ELF32_VERSYM + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FEATURES_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the header file. */ +#undef HAVE_GLOB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBUNWIND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_PTRACE_H + +/* Define if this is Linux that has SIGEV_THREAD_ID */ +#undef HAVE_LINUX_SIGEV_THREAD_ID + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* define if libc has program_invocation_name */ +#undef HAVE_PROGRAM_INVOCATION_NAME + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* defined to 1 if pthread symbols are exposed even without include pthread.h + */ +#undef HAVE_PTHREAD_DESPITE_ASKING_FOR + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the header file. */ +#undef HAVE_SCHED_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if the system has the type `struct mallinfo'. */ +#undef HAVE_STRUCT_MALLINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PRCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCALL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UCONTEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if compiler supports __thread */ +#undef HAVE_TLS + +/* Define to 1 if you have the header file. */ +#undef HAVE_UCONTEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Whether contains _Unwind_Backtrace */ +#undef HAVE_UNWIND_BACKTRACE + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNWIND_H + +/* define if your compiler has __attribute__ */ +#undef HAVE___ATTRIBUTE__ + +/* define if your compiler supports alignment of functions */ +#undef HAVE___ATTRIBUTE__ALIGNED_FN + +/* Define to 1 if compiler supports __environ */ +#undef HAVE___ENVIRON + +/* Define to 1 if you have the `__sbrk' function. */ +#undef HAVE___SBRK + +/* prefix where we look for installed files */ +#undef INSTALL_PREFIX + +/* Define to 1 if int32_t is equivalent to intptr_t */ +#undef INT32_EQUALS_INTPTR + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* 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. */ +#undef PERFTOOLS_DLL_DECL + +/* Mark the systems where we know it's bad if pthreads runs too + early before main (before threads are initialized, presumably). */ +#ifdef __FreeBSD__ +#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 +#endif + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define 8 bytes of allocation alignment for tcmalloc */ +#undef TCMALLOC_ALIGN_8BYTES + +/* Define internal page size for tcmalloc as number of left bitshift */ +#undef TCMALLOC_PAGE_SIZE_SHIFT + +/* 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 + + +#ifdef __MINGW32__ +#include "windows/mingw.h" +#endif + +#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */ + diff --git a/trunk/3rdparty/gperftools-2-fit/src/config_for_unittests.h b/trunk/3rdparty/gperftools-2-fit/src/config_for_unittests.h new file mode 100644 index 000000000..12bf61493 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/config_for_unittests.h @@ -0,0 +1,65 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// All Rights Reserved. +// +// Author: Craig Silverstein +// +// This file is needed for windows -- unittests are not part of the +// perftools dll, but still want to include config.h just like the +// dll does, so they can use internal tools and APIs for testing. +// +// The problem is that config.h declares PERFTOOLS_DLL_DECL to be +// for exporting symbols, but the unittest needs to *import* symbols +// (since it's not the dll). +// +// The solution is to have this file, which is just like config.h but +// sets PERFTOOLS_DLL_DECL to do a dllimport instead of a dllexport. +// +// 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" + +#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/trunk/3rdparty/gperftools-2-fit/src/debugallocation.cc b/trunk/3rdparty/gperftools-2-fit/src/debugallocation.cc new file mode 100644 index 000000000..17cd452fa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/debugallocation.cc @@ -0,0 +1,1583 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2000, 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: Urs Holzle + +#include "config.h" +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif +// We only need malloc.h for struct mallinfo. +#ifdef HAVE_STRUCT_MALLINFO +// Malloc can be in several places on older versions of OS X. +# if defined(HAVE_MALLOC_H) +# include +# elif defined(HAVE_MALLOC_MALLOC_H) +# include +# elif defined(HAVE_SYS_MALLOC_H) +# include +# endif +#endif +#ifdef HAVE_PTHREAD +#include +#endif +#include +#include +#include +#ifdef HAVE_MMAP +#include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include "addressmap-inl.h" +#include "base/commandlineflags.h" +#include "base/googleinit.h" +#include "base/logging.h" +#include "base/spinlock.h" +#include "malloc_hook-inl.h" +#include "symbolize.h" + +// NOTE: due to #define below, tcmalloc.cc will omit tc_XXX +// definitions. So that debug implementations can be defined +// instead. We're going to use do_malloc, do_free and other do_XXX +// functions that are defined in tcmalloc.cc for actual memory +// management +#define TCMALLOC_USING_DEBUGALLOCATION +#include "tcmalloc.cc" + +// __THROW is defined in glibc systems. It means, counter-intuitively, +// "This function will never throw an exception." It's an optional +// optimization tool, but we may need to use it to match glibc prototypes. +#ifndef __THROW // I guess we're not on a glibc system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +// 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_bool(malloctrace, + EnvToBool("TCMALLOC_TRACE", false), + "Enables memory (de)allocation tracing to /tmp/google.alloc."); +#ifdef HAVE_MMAP +DEFINE_bool(malloc_page_fence, + EnvToBool("TCMALLOC_PAGE_FENCE", false), + "Enables putting of memory allocations at page boundaries " + "with a guard page following the allocation (to catch buffer " + "overruns right when they happen)."); +DEFINE_bool(malloc_page_fence_never_reclaim, + EnvToBool("TCMALLOC_PAGE_FENCE_NEVER_RECLAIM", false), + "Enables making the virtual address space inaccessible " + "upon a deallocation instead of returning it and reusing later."); +#else +DEFINE_bool(malloc_page_fence, false, "Not usable (requires mmap)"); +DEFINE_bool(malloc_page_fence_never_reclaim, false, "Not usable (required mmap)"); +#endif +DEFINE_bool(malloc_reclaim_memory, + EnvToBool("TCMALLOC_RECLAIM_MEMORY", true), + "If set to false, we never return memory to malloc " + "when an object is deallocated. This ensures that all " + "heap object addresses are unique."); +DEFINE_int32(max_free_queue_size, + EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024), + "If greater than 0, keep freed blocks in a queue instead of " + "releasing them to the allocator immediately. Release them when " + "the total size of all blocks in the queue would otherwise exceed " + "this limit."); + +DEFINE_bool(symbolize_stacktrace, + EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true), + "Symbolize the stack trace when provided (on some error exits)"); + +// If we are LD_PRELOAD-ed against a non-pthreads app, then +// pthread_once won't be defined. We declare it here, for that +// case (with weak linkage) which will cause the non-definition to +// resolve to NULL. We can then check for NULL or not in Instance. +extern "C" int pthread_once(pthread_once_t *, void (*)(void)) + ATTRIBUTE_WEAK; + +// ========================================================================= // + +// A safe version of printf() that does not do any allocation and +// uses very little stack space. +static void TracePrintf(int fd, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + +// Round "value" up to next "alignment" boundary. +// Requires that "alignment" be a power of two. +static intptr_t RoundUp(intptr_t value, intptr_t alignment) { + return (value + alignment - 1) & ~(alignment - 1); +} + +// ========================================================================= // + +class MallocBlock; + +// A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate +// (below) pushes blocks into this queue instead of returning them to the +// underlying allocator immediately. See MallocBlock::Deallocate for more +// information. +// +// We can't use an STL class for this because we need to be careful not to +// perform any heap de-allocations in any of the code in this class, since the +// code in MallocBlock::Deallocate is not re-entrant. +template +class FreeQueue { + public: + FreeQueue() : q_front_(0), q_back_(0) {} + + bool Full() { + return (q_front_ + 1) % kFreeQueueSize == q_back_; + } + + void Push(const QueueEntry& block) { + q_[q_front_] = block; + q_front_ = (q_front_ + 1) % kFreeQueueSize; + } + + QueueEntry Pop() { + RAW_CHECK(q_back_ != q_front_, "Queue is empty"); + const QueueEntry& ret = q_[q_back_]; + q_back_ = (q_back_ + 1) % kFreeQueueSize; + return ret; + } + + size_t size() const { + return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize; + } + + private: + // Maximum number of blocks kept in the free queue before being freed. + static const int kFreeQueueSize = 1024; + + QueueEntry q_[kFreeQueueSize]; + int q_front_; + int q_back_; +}; + +struct MallocBlockQueueEntry { + MallocBlockQueueEntry() : block(NULL), size(0), + num_deleter_pcs(0), deleter_threadid(0) {} + MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) { + if (FLAGS_max_free_queue_size != 0 && b != NULL) { + // Adjust the number of frames to skip (4) if you change the + // location of this call. + num_deleter_pcs = + MallocHook::GetCallerStackTrace( + deleter_pcs, + sizeof(deleter_pcs) / sizeof(deleter_pcs[0]), + 4); + deleter_threadid = pthread_self(); + } else { + num_deleter_pcs = 0; + // Zero is an illegal pthread id by my reading of the pthread + // implementation: + deleter_threadid = 0; + } + } + + MallocBlock* block; + size_t size; + + // When deleted and put in the free queue, we (flag-controlled) + // record the stack so that if corruption is later found, we can + // print the deleter's stack. (These three vars add 144 bytes of + // overhead under the LP64 data model.) + void* deleter_pcs[16]; + int num_deleter_pcs; + pthread_t deleter_threadid; +}; + +class MallocBlock { + public: // allocation type constants + + // Different allocation types we distinguish. + // Note: The lower 4 bits are not random: we index kAllocName array + // by these values masked with kAllocTypeMask; + // the rest are "random" magic bits to help catch memory corruption. + static const int kMallocType = 0xEFCDAB90; + static const int kNewType = 0xFEBADC81; + static const int kArrayNewType = 0xBCEADF72; + + private: // constants + + // A mask used on alloc types above to get to 0, 1, 2 + static const int kAllocTypeMask = 0x3; + // An additional bit to set in AllocType constants + // to mark now deallocated regions. + static const int kDeallocatedTypeBit = 0x4; + + // For better memory debugging, we initialize all storage to known + // values, and overwrite the storage when it's deallocated: + // Byte that fills uninitialized storage. + static const int kMagicUninitializedByte = 0xAB; + // Byte that fills deallocated storage. + // NOTE: tcmalloc.cc depends on the value of kMagicDeletedByte + // to work around a bug in the pthread library. + static const int kMagicDeletedByte = 0xCD; + // A size_t (type of alloc_type_ below) in a deallocated storage + // filled with kMagicDeletedByte. + static const size_t kMagicDeletedSizeT = + 0xCDCDCDCD | (((size_t)0xCDCDCDCD << 16) << 16); + // Initializer works for 32 and 64 bit size_ts; + // "<< 16 << 16" is to fool gcc from issuing a warning + // when size_ts are 32 bits. + + // NOTE: on Linux, you can enable malloc debugging support in libc by + // setting the environment variable MALLOC_CHECK_ to 1 before you + // start the program (see man malloc). + + // We use either do_malloc or mmap to make the actual allocation. In + // order to remember which one of the two was used for any block, we store an + // appropriate magic word next to the block. + static const size_t kMagicMalloc = 0xDEADBEEF; + static const size_t kMagicMMap = 0xABCDEFAB; + + // This array will be filled with 0xCD, for use with memcmp. + static unsigned char kMagicDeletedBuffer[1024]; + static pthread_once_t deleted_buffer_initialized_; + static bool deleted_buffer_initialized_no_pthreads_; + + private: // data layout + + // The four fields size1_,offset_,magic1_,alloc_type_ + // should together occupy a multiple of 16 bytes. (At the + // moment, sizeof(size_t) == 4 or 8 depending on piii vs + // k8, and 4 of those sum to 16 or 32 bytes). + // This, combined with do_malloc's alignment guarantees, + // ensures that SSE types can be stored into the returned + // block, at &size2_. + size_t size1_; + size_t offset_; // normally 0 unless memaligned memory + // see comments in memalign() and FromRawPointer(). + size_t magic1_; + size_t alloc_type_; + // here comes the actual data (variable length) + // ... + // then come the size2_ and magic2_, or a full page of mprotect-ed memory + // if the malloc_page_fence feature is enabled. + size_t size2_; + size_t magic2_; + + private: // static data and helpers + + // Allocation map: stores the allocation type for each allocated object, + // or the type or'ed with kDeallocatedTypeBit + // for each formerly allocated object. + typedef AddressMap AllocMap; + static AllocMap* alloc_map_; + // This protects alloc_map_ and consistent state of metadata + // for each still-allocated object in it. + // We use spin locks instead of pthread_mutex_t locks + // to prevent crashes via calls to pthread_mutex_(un)lock + // for the (de)allocations coming from pthreads initialization itself. + static SpinLock alloc_map_lock_; + + // A queue of freed blocks. Instead of releasing blocks to the allocator + // immediately, we put them in a queue, freeing them only when necessary + // to keep the total size of all the freed blocks below the limit set by + // FLAGS_max_free_queue_size. + static FreeQueue* free_queue_; + + static size_t free_queue_size_; // total size of blocks in free_queue_ + // protects free_queue_ and free_queue_size_ + static SpinLock free_queue_lock_; + + // Names of allocation types (kMallocType, kNewType, kArrayNewType) + static const char* const kAllocName[]; + // Names of corresponding deallocation types + static const char* const kDeallocName[]; + + static const char* AllocName(int type) { + return kAllocName[type & kAllocTypeMask]; + } + + static const char* DeallocName(int type) { + return kDeallocName[type & kAllocTypeMask]; + } + + private: // helper accessors + + bool IsMMapped() const { return kMagicMMap == magic1_; } + + bool IsValidMagicValue(size_t value) const { + return kMagicMMap == value || kMagicMalloc == value; + } + + static size_t real_malloced_size(size_t size) { + return size + sizeof(MallocBlock); + } + + /* + * Here we assume size of page is kMinAlign aligned, + * so if size is MALLOC_ALIGNMENT aligned too, then we could + * guarantee return address is also kMinAlign aligned, because + * mmap return address at nearby page boundary on Linux. + */ + static size_t real_mmapped_size(size_t size) { + size_t tmp = size + MallocBlock::data_offset(); + tmp = RoundUp(tmp, kMinAlign); + return tmp; + } + + size_t real_size() { + return IsMMapped() ? real_mmapped_size(size1_) : real_malloced_size(size1_); + } + + // NOTE: if the block is mmapped (that is, we're using the + // malloc_page_fence option) then there's no size2 or magic2 + // (instead, the guard page begins where size2 would be). + + size_t* size2_addr() { return (size_t*)((char*)&size2_ + size1_); } + const size_t* size2_addr() const { + return (const size_t*)((char*)&size2_ + size1_); + } + + size_t* magic2_addr() { return (size_t*)(size2_addr() + 1); } + const size_t* magic2_addr() const { return (const size_t*)(size2_addr() + 1); } + + private: // other helpers + + void Initialize(size_t size, int type) { + RAW_CHECK(IsValidMagicValue(magic1_), ""); + // record us as allocated in the map + alloc_map_lock_.Lock(); + if (!alloc_map_) { + void* p = do_malloc(sizeof(AllocMap)); + alloc_map_ = new(p) AllocMap(do_malloc, do_free); + } + alloc_map_->Insert(data_addr(), type); + // initialize us + size1_ = size; + offset_ = 0; + alloc_type_ = type; + if (!IsMMapped()) { + bit_store(magic2_addr(), &magic1_); + bit_store(size2_addr(), &size); + } + alloc_map_lock_.Unlock(); + memset(data_addr(), kMagicUninitializedByte, size); + if (!IsMMapped()) { + RAW_CHECK(memcmp(&size1_, size2_addr(), sizeof(size1_)) == 0, "should hold"); + RAW_CHECK(memcmp(&magic1_, magic2_addr(), sizeof(magic1_)) == 0, "should hold"); + } + } + + size_t CheckAndClear(int type, size_t given_size) { + alloc_map_lock_.Lock(); + CheckLocked(type); + if (!IsMMapped()) { + RAW_CHECK(memcmp(&size1_, size2_addr(), sizeof(size1_)) == 0, "should hold"); + } + // record us as deallocated in the map + alloc_map_->Insert(data_addr(), type | kDeallocatedTypeBit); + alloc_map_lock_.Unlock(); + // clear us + const size_t size = real_size(); + RAW_CHECK(!given_size || given_size == size1_, + "right size must be passed to sized delete"); + memset(this, kMagicDeletedByte, size); + return size; + } + + void CheckLocked(int type) const { + int map_type = 0; + const int* found_type = + alloc_map_ != NULL ? alloc_map_->Find(data_addr()) : NULL; + if (found_type == NULL) { + RAW_LOG(FATAL, "memory allocation bug: object at %p " + "has never been allocated", data_addr()); + } else { + map_type = *found_type; + } + if ((map_type & kDeallocatedTypeBit) != 0) { + RAW_LOG(FATAL, "memory allocation bug: object at %p " + "has been already deallocated (it was allocated with %s)", + data_addr(), AllocName(map_type & ~kDeallocatedTypeBit)); + } + if (alloc_type_ == kMagicDeletedSizeT) { + RAW_LOG(FATAL, "memory stomping bug: a word before object at %p " + "has been corrupted; or else the object has been already " + "deallocated and our memory map has been corrupted", + data_addr()); + } + if (!IsValidMagicValue(magic1_)) { + RAW_LOG(FATAL, "memory stomping bug: a word before object at %p " + "has been corrupted; " + "or else our memory map has been corrupted and this is a " + "deallocation for not (currently) heap-allocated object", + data_addr()); + } + if (!IsMMapped()) { + if (memcmp(&size1_, size2_addr(), sizeof(size1_))) { + RAW_LOG(FATAL, "memory stomping bug: a word after object at %p " + "has been corrupted", data_addr()); + } + size_t addr; + bit_store(&addr, magic2_addr()); + if (!IsValidMagicValue(addr)) { + RAW_LOG(FATAL, "memory stomping bug: a word after object at %p " + "has been corrupted", data_addr()); + } + } + if (alloc_type_ != type) { + if ((alloc_type_ != MallocBlock::kMallocType) && + (alloc_type_ != MallocBlock::kNewType) && + (alloc_type_ != MallocBlock::kArrayNewType)) { + RAW_LOG(FATAL, "memory stomping bug: a word before object at %p " + "has been corrupted", data_addr()); + } + RAW_LOG(FATAL, "memory allocation/deallocation mismatch at %p: " + "allocated with %s being deallocated with %s", + data_addr(), AllocName(alloc_type_), DeallocName(type)); + } + if (alloc_type_ != map_type) { + RAW_LOG(FATAL, "memory stomping bug: our memory map has been corrupted : " + "allocation at %p made with %s " + "is recorded in the map to be made with %s", + data_addr(), AllocName(alloc_type_), AllocName(map_type)); + } + } + + public: // public accessors + + void* data_addr() { return (void*)&size2_; } + const void* data_addr() const { return (const void*)&size2_; } + + static size_t data_offset() { return OFFSETOF_MEMBER(MallocBlock, size2_); } + + size_t data_size() const { return size1_; } + + void set_offset(int offset) { this->offset_ = offset; } + + public: // our main interface + + static MallocBlock* Allocate(size_t size, int type) { + // Prevent an integer overflow / crash with large allocation sizes. + // TODO - Note that for a e.g. 64-bit size_t, max_size_t may not actually + // be the maximum value, depending on how the compiler treats ~0. The worst + // practical effect is that allocations are limited to 4Gb or so, even if + // the address space could take more. + static size_t max_size_t = ~0; + if (size > max_size_t - sizeof(MallocBlock)) { + RAW_LOG(ERROR, "Massive size passed to malloc: %zu", size); + return NULL; + } + MallocBlock* b = NULL; + const bool use_malloc_page_fence = FLAGS_malloc_page_fence; +#ifdef HAVE_MMAP + if (use_malloc_page_fence) { + // Put the block towards the end of the page and make the next page + // inaccessible. This will catch buffer overrun right when it happens. + size_t sz = real_mmapped_size(size); + int pagesize = getpagesize(); + int num_pages = (sz + pagesize - 1) / pagesize + 1; + char* p = (char*) mmap(NULL, num_pages * pagesize, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) { + // If the allocation fails, abort rather than returning NULL to + // malloc. This is because in most cases, the program will run out + // of memory in this mode due to tremendous amount of wastage. There + // is no point in propagating the error elsewhere. + RAW_LOG(FATAL, "Out of memory: possibly due to page fence overhead: %s", + strerror(errno)); + } + // Mark the page after the block inaccessible + if (mprotect(p + (num_pages - 1) * pagesize, pagesize, PROT_NONE)) { + RAW_LOG(FATAL, "Guard page setup failed: %s", strerror(errno)); + } + b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz); + } else { + b = (MallocBlock*) do_malloc(real_malloced_size(size)); + } +#else + b = (MallocBlock*) do_malloc(real_malloced_size(size)); +#endif + + // It would be nice to output a diagnostic on allocation failure + // here, but logging (other than FATAL) requires allocating + // memory, which could trigger a nasty recursion. Instead, preserve + // malloc semantics and return NULL on failure. + if (b != NULL) { + b->magic1_ = use_malloc_page_fence ? kMagicMMap : kMagicMalloc; + b->Initialize(size, type); + } + return b; + } + + void Deallocate(int type, size_t given_size) { + if (IsMMapped()) { // have to do this before CheckAndClear +#ifdef HAVE_MMAP + int size = CheckAndClear(type, given_size); + int pagesize = getpagesize(); + int num_pages = (size + pagesize - 1) / pagesize + 1; + char* p = (char*) this; + if (FLAGS_malloc_page_fence_never_reclaim || + !FLAGS_malloc_reclaim_memory) { + mprotect(p - (num_pages - 1) * pagesize + size, + num_pages * pagesize, PROT_NONE); + } else { + munmap(p - (num_pages - 1) * pagesize + size, num_pages * pagesize); + } +#endif + } else { + const size_t size = CheckAndClear(type, given_size); + if (FLAGS_malloc_reclaim_memory) { + // Instead of freeing the block immediately, push it onto a queue of + // recently freed blocks. Free only enough blocks to keep from + // exceeding the capacity of the queue or causing the total amount of + // un-released memory in the queue from exceeding + // FLAGS_max_free_queue_size. + ProcessFreeQueue(this, size, FLAGS_max_free_queue_size); + } + } + } + + static size_t FreeQueueSize() { + SpinLockHolder l(&free_queue_lock_); + return free_queue_size_; + } + + static void ProcessFreeQueue(MallocBlock* b, size_t size, + int max_free_queue_size) { + // MallocBlockQueueEntry are about 144 in size, so we can only + // use a small array of them on the stack. + MallocBlockQueueEntry entries[4]; + int num_entries = 0; + MallocBlockQueueEntry new_entry(b, size); + free_queue_lock_.Lock(); + if (free_queue_ == NULL) + free_queue_ = new FreeQueue; + RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!"); + + if (b != NULL) { + free_queue_size_ += size + sizeof(MallocBlockQueueEntry); + free_queue_->Push(new_entry); + } + + // Free blocks until the total size of unfreed blocks no longer exceeds + // max_free_queue_size, and the free queue has at least one free + // space in it. + while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) { + RAW_CHECK(num_entries < arraysize(entries), "entries array overflow"); + entries[num_entries] = free_queue_->Pop(); + free_queue_size_ -= + entries[num_entries].size + sizeof(MallocBlockQueueEntry); + num_entries++; + if (num_entries == arraysize(entries)) { + // The queue will not be full at this point, so it is ok to + // release the lock. The queue may still contain more than + // max_free_queue_size, but this is not a strict invariant. + free_queue_lock_.Unlock(); + for (int i = 0; i < num_entries; i++) { + CheckForDanglingWrites(entries[i]); + do_free(entries[i].block); + } + num_entries = 0; + free_queue_lock_.Lock(); + } + } + free_queue_lock_.Unlock(); + for (int i = 0; i < num_entries; i++) { + CheckForDanglingWrites(entries[i]); + do_free(entries[i].block); + } + } + + static void InitDeletedBuffer() { + memset(kMagicDeletedBuffer, kMagicDeletedByte, sizeof(kMagicDeletedBuffer)); + deleted_buffer_initialized_no_pthreads_ = true; + } + + static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) { + // Initialize the buffer if necessary. + if (pthread_once) + pthread_once(&deleted_buffer_initialized_, &InitDeletedBuffer); + if (!deleted_buffer_initialized_no_pthreads_) { + // This will be the case on systems that don't link in pthreads, + // including on FreeBSD where pthread_once has a non-zero address + // (but doesn't do anything) even when pthreads isn't linked in. + InitDeletedBuffer(); + } + + const unsigned char* p = + reinterpret_cast(queue_entry.block); + + static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer); + const size_t size = queue_entry.size; + const size_t buffers = size / size_of_buffer; + const size_t remainder = size % size_of_buffer; + size_t buffer_idx; + for (buffer_idx = 0; buffer_idx < buffers; ++buffer_idx) { + CheckForCorruptedBuffer(queue_entry, buffer_idx, p, size_of_buffer); + p += size_of_buffer; + } + CheckForCorruptedBuffer(queue_entry, buffer_idx, p, remainder); + } + + static void CheckForCorruptedBuffer(const MallocBlockQueueEntry& queue_entry, + size_t buffer_idx, + const unsigned char* buffer, + size_t size_of_buffer) { + if (memcmp(buffer, kMagicDeletedBuffer, size_of_buffer) == 0) { + return; + } + + RAW_LOG(ERROR, + "Found a corrupted memory buffer in MallocBlock (may be offset " + "from user ptr): buffer index: %zd, buffer ptr: %p, size of " + "buffer: %zd", buffer_idx, buffer, size_of_buffer); + + // The magic deleted buffer should only be 1024 bytes, but in case + // this changes, let's put an upper limit on the number of debug + // lines we'll output: + if (size_of_buffer <= 1024) { + for (int i = 0; i < size_of_buffer; ++i) { + if (buffer[i] != kMagicDeletedByte) { + RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0x%02x).", + i, buffer[i], kMagicDeletedByte); + } + } + } else { + RAW_LOG(ERROR, "Buffer too large to print corruption."); + } + + const MallocBlock* b = queue_entry.block; + const size_t size = queue_entry.size; + if (queue_entry.num_deleter_pcs > 0) { + TracePrintf(STDERR_FILENO, "Deleted by thread %p\n", + reinterpret_cast( + PRINTABLE_PTHREAD(queue_entry.deleter_threadid))); + + // We don't want to allocate or deallocate memory here, so we use + // placement-new. It's ok that we don't destroy this, since we're + // just going to error-exit below anyway. Union is for alignment. + union { void* alignment; char buf[sizeof(SymbolTable)]; } tablebuf; + SymbolTable* symbolization_table = new (tablebuf.buf) SymbolTable; + for (int i = 0; i < queue_entry.num_deleter_pcs; i++) { + // Symbolizes the previous address of pc because pc may be in the + // next function. This may happen when the function ends with + // a call to a function annotated noreturn (e.g. CHECK). + char *pc = reinterpret_cast(queue_entry.deleter_pcs[i]); + symbolization_table->Add(pc - 1); + } + if (FLAGS_symbolize_stacktrace) + symbolization_table->Symbolize(); + for (int i = 0; i < queue_entry.num_deleter_pcs; i++) { + char *pc = reinterpret_cast(queue_entry.deleter_pcs[i]); + TracePrintf(STDERR_FILENO, " @ %p %s\n", + pc, symbolization_table->GetSymbol(pc - 1)); + } + } else { + RAW_LOG(ERROR, + "Skipping the printing of the deleter's stack! Its stack was " + "not found; either the corruption occurred too early in " + "execution to obtain a stack trace or --max_free_queue_size was " + "set to 0."); + } + + RAW_LOG(FATAL, + "Memory was written to after being freed. MallocBlock: %p, user " + "ptr: %p, size: %zd. If you can't find the source of the error, " + "try using ASan (http://code.google.com/p/address-sanitizer/), " + "Valgrind, or Purify, or study the " + "output of the deleter's stack printed above.", + b, b->data_addr(), size); + } + + static MallocBlock* FromRawPointer(void* p) { + const size_t data_offset = MallocBlock::data_offset(); + // Find the header just before client's memory. + MallocBlock *mb = reinterpret_cast( + reinterpret_cast(p) - data_offset); + // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer. + if (mb->alloc_type_ == kMagicDeletedSizeT) { + RAW_LOG(FATAL, "memory allocation bug: object at %p has been already" + " deallocated; or else a word before the object has been" + " corrupted (memory stomping bug)", p); + } + // If mb->offset_ is zero (common case), mb is the real header. + // If mb->offset_ is non-zero, this block was allocated by debug + // memallign implementation, and mb->offset_ is the distance + // backwards to the real header from mb, which is a fake header. + if (mb->offset_ == 0) { + return mb; + } + + MallocBlock *main_block = reinterpret_cast( + reinterpret_cast(mb) - mb->offset_); + + if (main_block->offset_ != 0) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Need 0 but got %x", + (unsigned)(main_block->offset_)); + } + if (main_block >= p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Detected main_block address overflow: %x", + (unsigned)(mb->offset_)); + } + if (main_block->size2_addr() < p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " It points below it's own main_block: %x", + (unsigned)(mb->offset_)); + } + + return main_block; + } + + static const MallocBlock* FromRawPointer(const void* p) { + // const-safe version: we just cast about + return FromRawPointer(const_cast(p)); + } + + void Check(int type) const { + alloc_map_lock_.Lock(); + CheckLocked(type); + alloc_map_lock_.Unlock(); + } + + static bool CheckEverything() { + alloc_map_lock_.Lock(); + if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0); + alloc_map_lock_.Unlock(); + return true; // if we get here, we're okay + } + + static bool MemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]) { + memset(histogram, 0, kMallocHistogramSize * sizeof(int)); + alloc_map_lock_.Lock(); + stats_blocks_ = 0; + stats_total_ = 0; + stats_histogram_ = histogram; + if (alloc_map_ != NULL) alloc_map_->Iterate(StatsCallback, 0); + *blocks = stats_blocks_; + *total = stats_total_; + alloc_map_lock_.Unlock(); + return true; + } + + private: // helpers for CheckEverything and MemoryStats + + static void CheckCallback(const void* ptr, int* type, int dummy) { + if ((*type & kDeallocatedTypeBit) == 0) { + FromRawPointer(ptr)->CheckLocked(*type); + } + } + + // Accumulation variables for StatsCallback protected by alloc_map_lock_ + static int stats_blocks_; + static size_t stats_total_; + static int* stats_histogram_; + + static void StatsCallback(const void* ptr, int* type, int dummy) { + if ((*type & kDeallocatedTypeBit) == 0) { + const MallocBlock* b = FromRawPointer(ptr); + b->CheckLocked(*type); + ++stats_blocks_; + size_t mysize = b->size1_; + int entry = 0; + stats_total_ += mysize; + while (mysize) { + ++entry; + mysize >>= 1; + } + RAW_CHECK(entry < kMallocHistogramSize, + "kMallocHistogramSize should be at least as large as log2 " + "of the maximum process memory size"); + stats_histogram_[entry] += 1; + } + } +}; + +void DanglingWriteChecker() { + // Clear out the remaining free queue to check for dangling writes. + MallocBlock::ProcessFreeQueue(NULL, 0, 0); +} + +// ========================================================================= // + +const size_t MallocBlock::kMagicMalloc; +const size_t MallocBlock::kMagicMMap; + +MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL; +SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED); + +FreeQueue* MallocBlock::free_queue_ = NULL; +size_t MallocBlock::free_queue_size_ = 0; +SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED); + +unsigned char MallocBlock::kMagicDeletedBuffer[1024]; +pthread_once_t MallocBlock::deleted_buffer_initialized_ = PTHREAD_ONCE_INIT; +bool MallocBlock::deleted_buffer_initialized_no_pthreads_ = false; + +const char* const MallocBlock::kAllocName[] = { + "malloc", + "new", + "new []", + NULL, +}; + +const char* const MallocBlock::kDeallocName[] = { + "free", + "delete", + "delete []", + NULL, +}; + +int MallocBlock::stats_blocks_; +size_t MallocBlock::stats_total_; +int* MallocBlock::stats_histogram_; + +// ========================================================================= // + +// The following cut-down version of printf() avoids +// using stdio or ostreams. +// This is to guarantee no recursive calls into +// the allocator and to bound the stack space consumed. (The pthread +// manager thread in linuxthreads has a very small stack, +// so fprintf can't be called.) +static void TracePrintf(int fd, const char *fmt, ...) { + char buf[64]; + int i = 0; + va_list ap; + va_start(ap, fmt); + const char *p = fmt; + char numbuf[25]; + if (fd < 0) { + va_end(ap); + return; + } + numbuf[sizeof(numbuf)-1] = 0; + while (*p != '\0') { // until end of format string + char *s = &numbuf[sizeof(numbuf)-1]; + if (p[0] == '%' && p[1] != 0) { // handle % formats + int64 l = 0; + unsigned long base = 0; + if (*++p == 's') { // %s + s = va_arg(ap, char *); + } else if (*p == 'l' && p[1] == 'd') { // %ld + l = va_arg(ap, long); + base = 10; + p++; + } else if (*p == 'l' && p[1] == 'u') { // %lu + l = va_arg(ap, unsigned long); + base = 10; + p++; + } else if (*p == 'z' && p[1] == 'u') { // %zu + l = va_arg(ap, size_t); + base = 10; + p++; + } else if (*p == 'u') { // %u + l = va_arg(ap, unsigned int); + base = 10; + } else if (*p == 'd') { // %d + l = va_arg(ap, int); + base = 10; + } else if (*p == 'p') { // %p + l = va_arg(ap, intptr_t); + base = 16; + } else { + write(STDERR_FILENO, "Unimplemented TracePrintf format\n", 33); + write(STDERR_FILENO, p, 2); + write(STDERR_FILENO, "\n", 1); + abort(); + } + p++; + if (base != 0) { + bool minus = (l < 0 && base == 10); + uint64 ul = minus? -l : l; + do { + *--s = "0123456789abcdef"[ul % base]; + ul /= base; + } while (ul != 0); + if (base == 16) { + *--s = 'x'; + *--s = '0'; + } else if (minus) { + *--s = '-'; + } + } + } else { // handle normal characters + *--s = *p++; + } + while (*s != 0) { + if (i == sizeof(buf)) { + write(fd, buf, i); + i = 0; + } + buf[i++] = *s++; + } + } + if (i != 0) { + write(fd, buf, i); + } + va_end(ap); +} + +// Return the file descriptor we're writing a log to +static int TraceFd() { + static int trace_fd = -1; + if (trace_fd == -1) { // Open the trace file on the first call + const char *val = getenv("TCMALLOC_TRACE_FILE"); + bool fallback_to_stderr = false; + if (!val) { + val = "/tmp/google.alloc"; + fallback_to_stderr = true; + } + trace_fd = open(val, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (trace_fd == -1) { + if (fallback_to_stderr) { + trace_fd = 2; + TracePrintf(trace_fd, "Can't open %s. Logging to stderr.\n", val); + } else { + TracePrintf(2, "Can't open %s. Logging disabled.\n", val); + } + } + // Add a header to the log. + TracePrintf(trace_fd, "Trace started: %lu\n", + static_cast(time(NULL))); + TracePrintf(trace_fd, + "func\tsize\tptr\tthread_id\tstack pcs for tools/symbolize\n"); + } + return trace_fd; +} + +// Print the hex stack dump on a single line. PCs are separated by tabs. +static void TraceStack(void) { + void *pcs[16]; + int n = GetStackTrace(pcs, sizeof(pcs)/sizeof(pcs[0]), 0); + for (int i = 0; i != n; i++) { + TracePrintf(TraceFd(), "\t%p", pcs[i]); + } +} + +// This protects MALLOC_TRACE, to make sure its info is atomically written. +static SpinLock malloc_trace_lock(SpinLock::LINKER_INITIALIZED); + +#define MALLOC_TRACE(name, size, addr) \ + do { \ + if (FLAGS_malloctrace) { \ + SpinLockHolder l(&malloc_trace_lock); \ + TracePrintf(TraceFd(), "%s\t%zu\t%p\t%" GPRIuPTHREAD, \ + name, size, addr, PRINTABLE_PTHREAD(pthread_self())); \ + TraceStack(); \ + TracePrintf(TraceFd(), "\n"); \ + } \ + } while (0) + +// ========================================================================= // + +// Write the characters buf[0, ..., size-1] to +// the malloc trace buffer. +// This function is intended for debugging, +// and is not declared in any header file. +// You must insert a declaration of it by hand when you need +// to use it. +void __malloctrace_write(const char *buf, size_t size) { + if (FLAGS_malloctrace) { + write(TraceFd(), buf, size); + } +} + +// ========================================================================= // + +// General debug allocation/deallocation + +static inline void* DebugAllocate(size_t size, int type) { + MallocBlock* ptr = MallocBlock::Allocate(size, type); + if (ptr == NULL) return NULL; + MALLOC_TRACE("malloc", size, ptr->data_addr()); + return ptr->data_addr(); +} + +static inline void DebugDeallocate(void* ptr, int type, size_t given_size) { + MALLOC_TRACE("free", + (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0), + ptr); + if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type, given_size); +} + +// ========================================================================= // + +// The following functions may be called via MallocExtension::instance() +// for memory verification and statistics. +class DebugMallocImplementation : public TCMallocImplementation { + public: + virtual bool GetNumericProperty(const char* name, size_t* value) { + bool result = TCMallocImplementation::GetNumericProperty(name, value); + if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) { + // Subtract bytes kept in the free queue + size_t qsize = MallocBlock::FreeQueueSize(); + if (*value >= qsize) { + *value -= qsize; + } + } + return result; + } + + virtual bool VerifyNewMemory(const void* p) { + if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType); + return true; + } + + virtual bool VerifyArrayNewMemory(const void* p) { + if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType); + return true; + } + + virtual bool VerifyMallocMemory(const void* p) { + if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType); + return true; + } + + virtual bool VerifyAllMemory() { + return MallocBlock::CheckEverything(); + } + + virtual bool MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]) { + return MallocBlock::MemoryStats(blocks, total, histogram); + } + + virtual size_t GetEstimatedAllocatedSize(size_t size) { + return size; + } + + virtual size_t GetAllocatedSize(const void* p) { + if (p) { + RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned, + "ptr not allocated by tcmalloc"); + return MallocBlock::FromRawPointer(p)->data_size(); + } + return 0; + } + + virtual MallocExtension::Ownership GetOwnership(const void* p) { + if (!p) { + // nobody owns NULL + return MallocExtension::kNotOwned; + } + + // FIXME: note that correct GetOwnership should not touch memory + // that is not owned by tcmalloc. Main implementation is using + // pagemap to discover if page in question is owned by us or + // not. But pagemap only has marks for first and last page of + // spans. Note that if p was returned out of our memalign with + // big alignment, then it will point outside of marked pages. Also + // note that FromRawPointer call below requires touching memory + // before pointer in order to handle memalign-ed chunks + // (offset_). This leaves us with two options: + // + // * do FromRawPointer first and have possibility of crashing if + // we're given not owned pointer + // + // * return incorrect ownership for those large memalign chunks + // + // I've decided to choose later, which appears to happen rarer and + // therefore is arguably a lesser evil + + MallocExtension::Ownership rv = TCMallocImplementation::GetOwnership(p); + if (rv != MallocExtension::kOwned) { + return rv; + } + + const MallocBlock* mb = MallocBlock::FromRawPointer(p); + return TCMallocImplementation::GetOwnership(mb); + } + + virtual void GetFreeListSizes(vector* v) { + static const char* kDebugFreeQueue = "debug.free_queue"; + + TCMallocImplementation::GetFreeListSizes(v); + + MallocExtension::FreeListInfo i; + i.type = kDebugFreeQueue; + i.min_object_size = 0; + i.max_object_size = numeric_limits::max(); + i.total_bytes_free = MallocBlock::FreeQueueSize(); + v->push_back(i); + } + + }; + +static union { + char chars[sizeof(DebugMallocImplementation)]; + void *ptr; +} debug_malloc_implementation_space; + +REGISTER_MODULE_INITIALIZER(debugallocation, { +#if (__cplusplus >= 201103L) + static_assert(alignof(decltype(debug_malloc_implementation_space)) >= alignof(DebugMallocImplementation), + "DebugMallocImplementation is expected to need just word alignment"); +#endif + // Either we or valgrind will control memory management. We + // register our extension if we're the winner. Otherwise let + // Valgrind use its own malloc (so don't register our extension). + if (!RunningOnValgrind()) { + DebugMallocImplementation *impl = new (debug_malloc_implementation_space.chars) DebugMallocImplementation(); + MallocExtension::Register(impl); + } +}); + +REGISTER_MODULE_DESTRUCTOR(debugallocation, { + if (!RunningOnValgrind()) { + // When the program exits, check all blocks still in the free + // queue for corruption. + DanglingWriteChecker(); + } +}); + +// ========================================================================= // + +struct debug_alloc_retry_data { + size_t size; + int new_type; +}; + +static void *retry_debug_allocate(void *arg) { + debug_alloc_retry_data *data = static_cast(arg); + return DebugAllocate(data->size, data->new_type); +} + +// This is mostly the same a cpp_alloc in tcmalloc.cc. +// TODO(csilvers): change Allocate() above to call cpp_alloc, so we +// don't have to reproduce the logic here. To make tc_new_mode work +// properly, I think we'll need to separate out the logic of throwing +// from the logic of calling the new-handler. +inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) { + void* p = DebugAllocate(size, new_type); + if (p != NULL) { + return p; + } + struct debug_alloc_retry_data data; + data.size = size; + data.new_type = new_type; + return handle_oom(retry_debug_allocate, &data, + true, nothrow); +} + +inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) { + void* p = DebugAllocate(size, MallocBlock::kMallocType); + if (p != NULL) { + return p; + } + struct debug_alloc_retry_data data; + data.size = size; + data.new_type = MallocBlock::kMallocType; + return handle_oom(retry_debug_allocate, &data, + false, true); +} + +// Exported routines + +// frame forcer and force_frame exist only to prevent tail calls to +// DebugDeallocate to be actually implemented as tail calls. This is +// important because stack trace capturing in MallocBlockQueueEntry +// relies on google_malloc section being on stack and tc_XXX functions +// are in that section. So they must not jump to DebugDeallocate but +// have to do call. frame_forcer call at the end of such functions +// prevents tail calls to DebugDeallocate. +static int frame_forcer; +static void force_frame() { + int dummy = *(int volatile *)&frame_forcer; + (void)dummy; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_NOTHROW { + if (ThreadCache::IsUseEmergencyMalloc()) { + return tcmalloc::EmergencyMalloc(size); + } + void* ptr = do_debug_malloc_or_debug_cpp_alloc(size); + MallocHook::InvokeNewHook(ptr, size); + return ptr; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_NOTHROW { + if (tcmalloc::IsEmergencyPtr(ptr)) { + return tcmalloc::EmergencyFree(ptr); + } + MallocHook::InvokeDeleteHook(ptr); + DebugDeallocate(ptr, MallocBlock::kMallocType, 0); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(ptr); + DebugDeallocate(ptr, MallocBlock::kMallocType, size); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) PERFTOOLS_NOTHROW { + if (ThreadCache::IsUseEmergencyMalloc()) { + return tcmalloc::EmergencyCalloc(count, size); + } + // Overflow check + const size_t total_size = count * size; + if (size != 0 && total_size / size != count) return NULL; + + void* block = do_debug_malloc_or_debug_cpp_alloc(total_size); + MallocHook::InvokeNewHook(block, total_size); + if (block) memset(block, 0, total_size); + return block; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW { + if (tcmalloc::IsEmergencyPtr(ptr)) { + return tcmalloc::EmergencyFree(ptr); + } + MallocHook::InvokeDeleteHook(ptr); + DebugDeallocate(ptr, MallocBlock::kMallocType, 0); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW { + if (tcmalloc::IsEmergencyPtr(ptr)) { + return tcmalloc::EmergencyRealloc(ptr, size); + } + if (ptr == NULL) { + ptr = do_debug_malloc_or_debug_cpp_alloc(size); + MallocHook::InvokeNewHook(ptr, size); + return ptr; + } + if (size == 0) { + MallocHook::InvokeDeleteHook(ptr); + DebugDeallocate(ptr, MallocBlock::kMallocType, 0); + return NULL; + } + MallocBlock* old = MallocBlock::FromRawPointer(ptr); + old->Check(MallocBlock::kMallocType); + MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType); + + // If realloc fails we are to leave the old block untouched and + // return null + if (p == NULL) return NULL; + + // if ptr was allocated via memalign, then old->data_size() is not + // start of user data. So we must be careful to copy only user-data + char *old_begin = (char *)old->data_addr(); + char *old_end = old_begin + old->data_size(); + + ssize_t old_ssize = old_end - (char *)ptr; + CHECK_CONDITION(old_ssize >= 0); + + size_t old_size = (size_t)old_ssize; + CHECK_CONDITION(old_size <= old->data_size()); + + memcpy(p->data_addr(), ptr, (old_size < size) ? old_size : size); + MallocHook::InvokeDeleteHook(ptr); + MallocHook::InvokeNewHook(p->data_addr(), size); + DebugDeallocate(ptr, MallocBlock::kMallocType, 0); + MALLOC_TRACE("realloc", p->data_size(), p->data_addr()); + return p->data_addr(); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) { + void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, false); + MallocHook::InvokeNewHook(ptr, size); + if (ptr == NULL) { + RAW_LOG(FATAL, "Unable to allocate %zu bytes: new failed.", size); + } + return ptr; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_NOTHROW { + void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, true); + MallocHook::InvokeNewHook(ptr, size); + return ptr; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kNewType, 0); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kNewType, size); + force_frame(); +} + +// Some STL implementations explicitly invoke this. +// It is completely equivalent to a normal delete (delete never throws). +extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kNewType, 0); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) { + void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, false); + MallocHook::InvokeNewHook(ptr, size); + if (ptr == NULL) { + RAW_LOG(FATAL, "Unable to allocate %zu bytes: new[] failed.", size); + } + return ptr; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) + PERFTOOLS_NOTHROW { + void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, true); + MallocHook::InvokeNewHook(ptr, size); + return ptr; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kArrayNewType, 0); + force_frame(); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kArrayNewType, size); + force_frame(); +} + +// Some STL implementations explicitly invoke this. +// It is completely equivalent to a normal delete (delete never throws). +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_NOTHROW { + MallocHook::InvokeDeleteHook(p); + DebugDeallocate(p, MallocBlock::kArrayNewType, 0); + force_frame(); +} + +// This is mostly the same as do_memalign in tcmalloc.cc. +static void *do_debug_memalign(size_t alignment, size_t size, int type) { + // Allocate >= size bytes aligned on "alignment" boundary + // "alignment" is a power of two. + void *p = 0; + RAW_CHECK((alignment & (alignment-1)) == 0, "must be power of two"); + const size_t data_offset = MallocBlock::data_offset(); + // Allocate "alignment-1" extra bytes to ensure alignment is possible, and + // a further data_offset bytes for an additional fake header. + size_t extra_bytes = data_offset + alignment - 1; + if (size + extra_bytes < size) return NULL; // Overflow + p = DebugAllocate(size + extra_bytes, type); + if (p != 0) { + intptr_t orig_p = reinterpret_cast(p); + // Leave data_offset bytes for fake header, and round up to meet + // alignment. + p = reinterpret_cast(RoundUp(orig_p + data_offset, alignment)); + // Create a fake header block with an offset_ that points back to the + // real header. FromRawPointer uses this value. + MallocBlock *fake_hdr = reinterpret_cast( + reinterpret_cast(p) - data_offset); + // offset_ is distance between real and fake headers. + // p is now end of fake header (beginning of client area), + // and orig_p is the end of the real header, so offset_ + // is their difference. + // + // Note that other fields of fake_hdr are initialized with + // kMagicUninitializedByte + fake_hdr->set_offset(reinterpret_cast(p) - orig_p); + } + return p; +} + +struct memalign_retry_data { + size_t align; + size_t size; + int type; +}; + +static void *retry_debug_memalign(void *arg) { + memalign_retry_data *data = static_cast(arg); + return do_debug_memalign(data->align, data->size, data->type); +} + +ATTRIBUTE_ALWAYS_INLINE +inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align, + size_t size, + int type, + bool from_operator, + bool nothrow) { + void* p = do_debug_memalign(align, size, type); + if (p != NULL) { + return p; + } + + struct memalign_retry_data data; + data.align = align; + data.size = size; + data.type = type; + return handle_oom(retry_debug_memalign, &data, + from_operator, nothrow); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) PERFTOOLS_NOTHROW { + void *p = do_debug_memalign_or_debug_cpp_memalign(align, size, MallocBlock::kMallocType, false, true); + MallocHook::InvokeNewHook(p, size); + return p; +} + +// Implementation taken from tcmalloc/tcmalloc.cc +extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(void** result_ptr, size_t align, size_t size) + PERFTOOLS_NOTHROW { + if (((align % sizeof(void*)) != 0) || + ((align & (align - 1)) != 0) || + (align == 0)) { + return EINVAL; + } + + void* result = do_debug_memalign_or_debug_cpp_memalign(align, size, MallocBlock::kMallocType, false, true); + MallocHook::InvokeNewHook(result, size); + if (result == NULL) { + return ENOMEM; + } else { + *result_ptr = result; + return 0; + } +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) PERFTOOLS_NOTHROW { + // Allocate >= size bytes starting on a page boundary + void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size, MallocBlock::kMallocType, false, true); + MallocHook::InvokeNewHook(p, size); + return p; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) PERFTOOLS_NOTHROW { + // Round size up to a multiple of pages + // then allocate memory on a page boundary + int pagesize = getpagesize(); + size = RoundUp(size, pagesize); + if (size == 0) { // pvalloc(0) should allocate one page, according to + size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html + } + void *p = do_debug_memalign_or_debug_cpp_memalign(pagesize, size, MallocBlock::kMallocType, false, true); + MallocHook::InvokeNewHook(p, size); + return p; +} + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + +extern "C" PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t align) { + void* result = do_debug_memalign_or_debug_cpp_memalign(static_cast(align), size, MallocBlock::kNewType, true, false); + MallocHook::InvokeNewHook(result, size); + return result; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t align, const std::nothrow_t&) PERFTOOLS_NOTHROW { + void* result = do_debug_memalign_or_debug_cpp_memalign(static_cast(align), size, MallocBlock::kNewType, true, true); + MallocHook::InvokeNewHook(result, size); + return result; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t) PERFTOOLS_NOTHROW { + tc_delete(p); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t align) PERFTOOLS_NOTHROW { + // Reproduce actual size calculation done by do_debug_memalign + const size_t alignment = static_cast(align); + const size_t data_offset = MallocBlock::data_offset(); + const size_t extra_bytes = data_offset + alignment - 1; + + tc_delete_sized(p, size + extra_bytes); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t, const std::nothrow_t&) PERFTOOLS_NOTHROW { + tc_delete(p); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t align) { + void* result = do_debug_memalign_or_debug_cpp_memalign(static_cast(align), size, MallocBlock::kArrayNewType, true, false); + MallocHook::InvokeNewHook(result, size); + return result; +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t align, const std::nothrow_t& nt) PERFTOOLS_NOTHROW { + void* result = do_debug_memalign_or_debug_cpp_memalign(static_cast(align), size, MallocBlock::kArrayNewType, true, true); + MallocHook::InvokeNewHook(result, size); + return result; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t) PERFTOOLS_NOTHROW { + tc_deletearray(p); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t align) PERFTOOLS_NOTHROW { + // Reproduce actual size calculation done by do_debug_memalign + const size_t alignment = static_cast(align); + const size_t data_offset = MallocBlock::data_offset(); + const size_t extra_bytes = data_offset + alignment - 1; + + tc_deletearray_sized(p, size + extra_bytes); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t, const std::nothrow_t&) PERFTOOLS_NOTHROW { + tc_deletearray(p); +} + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + +// malloc_stats just falls through to the base implementation. +extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW { + do_malloc_stats(); +} + +extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW { + return do_mallopt(cmd, value); +} + +#ifdef HAVE_STRUCT_MALLINFO +extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW { + return do_mallinfo(); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW { + return MallocExtension::instance()->GetAllocatedSize(ptr); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW { + void* result = DebugAllocate(size, MallocBlock::kMallocType); + MallocHook::InvokeNewHook(result, size); + return result; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.cc b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.cc new file mode 100644 index 000000000..6c0946a62 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.cc @@ -0,0 +1,169 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, gperftools Contributors +// 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. +// + +#include "config.h" + +#include "emergency_malloc.h" + +#include // for ENOMEM, errno +#include // for memset + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/low_level_alloc.h" +#include "base/spinlock.h" +#include "internal_logging.h" + + +namespace tcmalloc { + __attribute__ ((visibility("internal"))) char *emergency_arena_start; + __attribute__ ((visibility("internal"))) uintptr_t emergency_arena_start_shifted; + + static CACHELINE_ALIGNED SpinLock emergency_malloc_lock(base::LINKER_INITIALIZED); + static char *emergency_arena_end; + static LowLevelAlloc::Arena *emergency_arena; + + class EmergencyArenaPagesAllocator : public LowLevelAlloc::PagesAllocator { + ~EmergencyArenaPagesAllocator() {} + void *MapPages(int32 flags, size_t size) { + char *new_end = emergency_arena_end + size; + if (new_end > emergency_arena_start + kEmergencyArenaSize) { + RAW_LOG(FATAL, "Unable to allocate %zu bytes in emergency zone.", size); + } + char *rv = emergency_arena_end; + emergency_arena_end = new_end; + return static_cast(rv); + } + void UnMapPages(int32 flags, void *addr, size_t size) { + RAW_LOG(FATAL, "UnMapPages is not implemented for emergency arena"); + } + }; + + static union { + char bytes[sizeof(EmergencyArenaPagesAllocator)]; + void *ptr; + } pages_allocator_place; + + static void InitEmergencyMalloc(void) { + const int32 flags = LowLevelAlloc::kAsyncSignalSafe; + + void *arena = LowLevelAlloc::GetDefaultPagesAllocator()->MapPages(flags, kEmergencyArenaSize * 2); + + uintptr_t arena_ptr = reinterpret_cast(arena); + uintptr_t ptr = (arena_ptr + kEmergencyArenaSize - 1) & ~(kEmergencyArenaSize-1); + + emergency_arena_end = emergency_arena_start = reinterpret_cast(ptr); + EmergencyArenaPagesAllocator *allocator = new (pages_allocator_place.bytes) EmergencyArenaPagesAllocator(); + emergency_arena = LowLevelAlloc::NewArenaWithCustomAlloc(0, LowLevelAlloc::DefaultArena(), allocator); + + emergency_arena_start_shifted = reinterpret_cast(emergency_arena_start) >> kEmergencyArenaShift; + + uintptr_t head_unmap_size = ptr - arena_ptr; + CHECK_CONDITION(head_unmap_size < kEmergencyArenaSize); + if (head_unmap_size != 0) { + LowLevelAlloc::GetDefaultPagesAllocator()->UnMapPages(flags, arena, ptr - arena_ptr); + } + + uintptr_t tail_unmap_size = kEmergencyArenaSize - head_unmap_size; + void *tail_start = reinterpret_cast(arena_ptr + head_unmap_size + kEmergencyArenaSize); + LowLevelAlloc::GetDefaultPagesAllocator()->UnMapPages(flags, tail_start, tail_unmap_size); + } + + PERFTOOLS_DLL_DECL void *EmergencyMalloc(size_t size) { + SpinLockHolder l(&emergency_malloc_lock); + + if (emergency_arena_start == NULL) { + InitEmergencyMalloc(); + CHECK_CONDITION(emergency_arena_start != NULL); + } + + void *rv = LowLevelAlloc::AllocWithArena(size, emergency_arena); + if (rv == NULL) { + errno = ENOMEM; + } + return rv; + } + + PERFTOOLS_DLL_DECL void EmergencyFree(void *p) { + SpinLockHolder l(&emergency_malloc_lock); + if (emergency_arena_start == NULL) { + InitEmergencyMalloc(); + CHECK_CONDITION(emergency_arena_start != NULL); + free(p); + return; + } + CHECK_CONDITION(emergency_arena_start); + LowLevelAlloc::Free(p); + } + + PERFTOOLS_DLL_DECL void *EmergencyRealloc(void *_old_ptr, size_t new_size) { + if (_old_ptr == NULL) { + return EmergencyMalloc(new_size); + } + if (new_size == 0) { + EmergencyFree(_old_ptr); + return NULL; + } + SpinLockHolder l(&emergency_malloc_lock); + CHECK_CONDITION(emergency_arena_start); + + char *old_ptr = static_cast(_old_ptr); + CHECK_CONDITION(old_ptr <= emergency_arena_end); + CHECK_CONDITION(emergency_arena_start <= old_ptr); + + // NOTE: we don't know previous size of old_ptr chunk. So instead + // of trying to figure out right size of copied memory, we just + // copy largest possible size. We don't care about being slow. + size_t old_ptr_size = emergency_arena_end - old_ptr; + size_t copy_size = (new_size < old_ptr_size) ? new_size : old_ptr_size; + + void *new_ptr = LowLevelAlloc::AllocWithArena(new_size, emergency_arena); + if (new_ptr == NULL) { + errno = ENOMEM; + return NULL; + } + memcpy(new_ptr, old_ptr, copy_size); + + LowLevelAlloc::Free(old_ptr); + return new_ptr; + } + + PERFTOOLS_DLL_DECL void *EmergencyCalloc(size_t n, size_t elem_size) { + // Overflow check + const size_t size = n * elem_size; + if (elem_size != 0 && size / elem_size != n) return NULL; + void *rv = EmergencyMalloc(size); + if (rv != NULL) { + memset(rv, 0, size); + } + return rv; + } +}; diff --git a/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.h b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.h new file mode 100644 index 000000000..8a82cfc8d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc.h @@ -0,0 +1,60 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, gperftools Contributors +// 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 EMERGENCY_MALLOC_H +#define EMERGENCY_MALLOC_H +#include "config.h" + +#include + +#include "base/basictypes.h" +#include "common.h" + +namespace tcmalloc { + static const uintptr_t kEmergencyArenaShift = 20+4; // 16 megs + static const uintptr_t kEmergencyArenaSize = 1 << kEmergencyArenaShift; + + extern __attribute__ ((visibility("internal"))) char *emergency_arena_start; + extern __attribute__ ((visibility("internal"))) uintptr_t emergency_arena_start_shifted;; + + PERFTOOLS_DLL_DECL void *EmergencyMalloc(size_t size); + PERFTOOLS_DLL_DECL void EmergencyFree(void *p); + PERFTOOLS_DLL_DECL void *EmergencyCalloc(size_t n, size_t elem_size); + PERFTOOLS_DLL_DECL void *EmergencyRealloc(void *old_ptr, size_t new_size); + + static inline bool IsEmergencyPtr(const void *_ptr) { + uintptr_t ptr = reinterpret_cast(_ptr); + return PREDICT_FALSE((ptr >> kEmergencyArenaShift) == emergency_arena_start_shifted) + && emergency_arena_start_shifted; + } + +} // namespace tcmalloc + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc_for_stacktrace.cc b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc_for_stacktrace.cc new file mode 100644 index 000000000..f1dc35e76 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/emergency_malloc_for_stacktrace.cc @@ -0,0 +1,48 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, gperftools Contributors +// 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. +#include "emergency_malloc.h" +#include "thread_cache.h" + +namespace tcmalloc { + bool EnterStacktraceScope(void); + void LeaveStacktraceScope(void); +} + +bool tcmalloc::EnterStacktraceScope(void) { + if (ThreadCache::IsUseEmergencyMalloc()) { + return false; + } + ThreadCache::SetUseEmergencyMalloc(); + return true; +} + +void tcmalloc::LeaveStacktraceScope(void) { + ThreadCache::ResetUseEmergencyMalloc(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/fake_stacktrace_scope.cc b/trunk/3rdparty/gperftools-2-fit/src/fake_stacktrace_scope.cc new file mode 100644 index 000000000..ee35a0412 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/fake_stacktrace_scope.cc @@ -0,0 +1,39 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, gperftools Contributors +// 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. + +#include "base/basictypes.h" + +namespace tcmalloc { + ATTRIBUTE_WEAK bool EnterStacktraceScope(void) { + return true; + } + ATTRIBUTE_WEAK void LeaveStacktraceScope(void) { + } +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/getenv_safe.h b/trunk/3rdparty/gperftools-2-fit/src/getenv_safe.h new file mode 100644 index 000000000..59094b1cf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/getenv_safe.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- + * Copyright (c) 2014, gperftools Contributors + * 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 GETENV_SAFE_H +#define GETENV_SAFE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This getenv function is safe to call before the C runtime is initialized. + * On Windows, it utilizes GetEnvironmentVariable() and on unix it uses + * /proc/self/environ instead calling getenv(). It's intended to be used in + * routines that run before main(), when the state required for getenv() may + * not be set up yet. In particular, errno isn't set up until relatively late + * (after the pthreads library has a chance to make it threadsafe), and + * getenv() doesn't work until then. + * On some platforms, this call will utilize the same, static buffer for + * repeated GetenvBeforeMain() calls. Callers should not expect pointers from + * this routine to be long lived. + * Note that on unix, /proc only has the environment at the time the + * application was started, so this routine ignores setenv() calls/etc. Also + * note it only reads the first 16K of the environment. + * + * NOTE: this is version of GetenvBeforeMain that's usable from + * C. Implementation is in sysinfo.cc + */ +const char* TCMallocGetenvSafe(const char* name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/getpc.h b/trunk/3rdparty/gperftools-2-fit/src/getpc.h new file mode 100644 index 000000000..9605363bb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/getpc.h @@ -0,0 +1,195 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 // for memcmp +#ifdef HAVE_ASM_PTRACE_H +#include +#endif +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include // for ucontext_t (and also mcontext_t) +#elif defined(HAVE_CYGWIN_SIGNAL_H) +#include +typedef ucontext ucontext_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. + unsigned 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(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) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) +// 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 + +#include "base/logging.h" // for RAW_LOG +#ifndef HAVE_CYGWIN_SIGNAL_H +typedef int ucontext_t; +#endif + +inline void* GetPC(const struct 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) { +#if defined(__s390__) && !defined(__s390x__) + // Mask out the AMODE31 bit from the PC recorded in the context. + return (void*)((unsigned long)signal_ucontext.PC_FROM_UCONTEXT & 0x7fffffffUL); +#else + return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h +#endif +} + +#endif + +#endif // BASE_GETPC_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/heap-checker.h b/trunk/3rdparty/gperftools-2-fit/src/google/heap-checker.h new file mode 100644 index 000000000..6b9ffe5a2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/heap-checker.h @@ -0,0 +1,36 @@ +// 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. + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/heap-checker.h is deprecated. Use gperftools/heap-checker.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/heap-profiler.h b/trunk/3rdparty/gperftools-2-fit/src/google/heap-profiler.h new file mode 100644 index 000000000..0c46f6344 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/heap-profiler.h @@ -0,0 +1,37 @@ +/* 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. + */ + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/heap-profiler.h is deprecated. Use gperftools/heap-profiler.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension.h b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension.h new file mode 100644 index 000000000..ad34decd8 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension.h @@ -0,0 +1,36 @@ +// 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. + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/malloc_extension.h is deprecated. Use gperftools/malloc_extension.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension_c.h b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension_c.h new file mode 100644 index 000000000..91418059a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_extension_c.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2008, 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. + */ + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/malloc_extension_c.h is deprecated. Use gperftools/malloc_extension_c.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook.h b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook.h new file mode 100644 index 000000000..416283b6c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook.h @@ -0,0 +1,36 @@ +// 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. + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/malloc_hook.h is deprecated. Use gperftools/malloc_hook.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook_c.h b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook_c.h new file mode 100644 index 000000000..1fa1a4acd --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/malloc_hook_c.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2008, 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. + */ + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/malloc_hook_c.h is deprecated. Use gperftools/malloc_hook_c.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/profiler.h b/trunk/3rdparty/gperftools-2-fit/src/google/profiler.h new file mode 100644 index 000000000..2f9967988 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/profiler.h @@ -0,0 +1,37 @@ +/* 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. + */ + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/profiler.h is deprecated. Use gperftools/profiler.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/stacktrace.h b/trunk/3rdparty/gperftools-2-fit/src/google/stacktrace.h new file mode 100644 index 000000000..829b3033a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/stacktrace.h @@ -0,0 +1,36 @@ +// 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. + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/stacktrace.h is deprecated. Use gperftools/stacktrace.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/google/tcmalloc.h b/trunk/3rdparty/gperftools-2-fit/src/google/tcmalloc.h new file mode 100644 index 000000000..ee8bb150f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/google/tcmalloc.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2003, 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. + */ + +/* The code has moved to gperftools/. Use that include-directory for + * new code. + */ +#if defined(__GNUC__) && !defined(GPERFTOOLS_SUPPRESS_LEGACY_WARNING) +#warning "google/tcmalloc.h is deprecated. Use gperftools/tcmalloc.h instead" +#endif +#include diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-checker.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-checker.h new file mode 100644 index 000000000..edd6cc7fb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-checker.h @@ -0,0 +1,422 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Maxim Lifantsev (with design ideas by Sanjay Ghemawat) +// +// +// Module for detecing heap (memory) leaks. +// +// For full(er) information, see docs/heap_checker.html +// +// This module can be linked into programs with +// no slowdown caused by this unless you activate the leak-checker: +// +// 1. Set the environment variable HEAPCHEK to _type_ before +// running the program. +// +// _type_ is usually "normal" but can also be "minimal", "strict", or +// "draconian". (See the html file for other options, like 'local'.) +// +// After that, just run your binary. If the heap-checker detects +// a memory leak at program-exit, it will print instructions on how +// to track down the leak. + +#ifndef BASE_HEAP_CHECKER_H_ +#define BASE_HEAP_CHECKER_H_ + +#include // for size_t +// I can't #include config.h in this public API file, but I should +// really use configure (and make malloc_extension.h a .in file) to +// figure out if the system has stdint.h or not. But I'm lazy, so +// for now I'm assuming it's a problem only with MSVC. +#ifndef _MSC_VER +#include // for uintptr_t +#endif +#include // for va_list +#include + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + + +// The class is thread-safe with respect to all the provided static methods, +// as well as HeapLeakChecker objects: they can be accessed by multiple threads. +class PERFTOOLS_DLL_DECL HeapLeakChecker { + public: + + // ----------------------------------------------------------------------- // + // Static functions for working with (whole-program) leak checking. + + // If heap leak checking is currently active in some mode + // e.g. if leak checking was started (and is still active now) + // due to HEAPCHECK=... defined in the environment. + // The return value reflects iff HeapLeakChecker objects manually + // constructed right now will be doing leak checking or nothing. + // Note that we can go from active to inactive state during InitGoogle() + // if FLAGS_heap_check gets set to "" by some code before/during InitGoogle(). + static bool IsActive(); + + // Return pointer to the whole-program checker if it has been created + // and NULL otherwise. + // Once GlobalChecker() returns non-NULL that object will not disappear and + // will be returned by all later GlobalChecker calls. + // This is mainly to access BytesLeaked() and ObjectsLeaked() (see below) + // for the whole-program checker after one calls NoGlobalLeaks() + // or similar and gets false. + static HeapLeakChecker* GlobalChecker(); + + // Do whole-program leak check now (if it was activated for this binary); + // return false only if it was activated and has failed. + // The mode of the check is controlled by the command-line flags. + // This method can be called repeatedly. + // Things like GlobalChecker()->SameHeap() can also be called explicitly + // to do the desired flavor of the check. + static bool NoGlobalLeaks(); + + // If whole-program checker if active, + // cancel its automatic execution after main() exits. + // This requires that some leak check (e.g. NoGlobalLeaks()) + // has been called at least once on the whole-program checker. + static void CancelGlobalCheck(); + + // ----------------------------------------------------------------------- // + // Non-static functions for starting and doing leak checking. + + // Start checking and name the leak check performed. + // The name is used in naming dumped profiles + // and needs to be unique only within your binary. + // It must also be a string that can be a part of a file name, + // in particular not contain path expressions. + explicit HeapLeakChecker(const char *name); + + // Destructor (verifies that some *NoLeaks or *SameHeap method + // has been called at least once). + ~HeapLeakChecker(); + + // These used to be different but are all the same now: they return + // true iff all memory allocated since this HeapLeakChecker object + // was constructor is still reachable from global state. + // + // Because we fork to convert addresses to symbol-names, and forking + // is not thread-safe, and we may be called in a threaded context, + // we do not try to symbolize addresses when called manually. + bool NoLeaks() { return DoNoLeaks(DO_NOT_SYMBOLIZE); } + + // These forms are obsolete; use NoLeaks() instead. + // TODO(csilvers): mark as DEPRECATED. + bool QuickNoLeaks() { return NoLeaks(); } + bool BriefNoLeaks() { return NoLeaks(); } + bool SameHeap() { return NoLeaks(); } + bool QuickSameHeap() { return NoLeaks(); } + bool BriefSameHeap() { return NoLeaks(); } + + // Detailed information about the number of leaked bytes and objects + // (both of these can be negative as well). + // These are available only after a *SameHeap or *NoLeaks + // method has been called. + // Note that it's possible for both of these to be zero + // while SameHeap() or NoLeaks() returned false in case + // of a heap state change that is significant + // but preserves the byte and object counts. + ssize_t BytesLeaked() const; + ssize_t ObjectsLeaked() const; + + // ----------------------------------------------------------------------- // + // Static helpers to make us ignore certain leaks. + + // Scoped helper class. Should be allocated on the stack inside a + // block of code. Any heap allocations done in the code block + // covered by the scoped object (including in nested function calls + // done by the code block) will not be reported as leaks. This is + // the recommended replacement for the GetDisableChecksStart() and + // DisableChecksToHereFrom() routines below. + // + // Example: + // void Foo() { + // HeapLeakChecker::Disabler disabler; + // ... code that allocates objects whose leaks should be ignored ... + // } + // + // REQUIRES: Destructor runs in same thread as constructor + class Disabler { + public: + Disabler(); + ~Disabler(); + private: + Disabler(const Disabler&); // disallow copy + void operator=(const Disabler&); // and assign + }; + + // Ignore an object located at 'ptr' (can go at the start or into the object) + // as well as all heap objects (transitively) referenced from it for the + // purposes of heap leak checking. Returns 'ptr' so that one can write + // static T* obj = IgnoreObject(new T(...)); + // + // If 'ptr' does not point to an active allocated object at the time of this + // call, it is ignored; but if it does, the object must not get deleted from + // the heap later on. + // + // See also HiddenPointer, below, if you need to prevent a pointer from + // being traversed by the heap checker but do not wish to transitively + // whitelist objects referenced through it. + template + static T* IgnoreObject(T* ptr) { + DoIgnoreObject(static_cast(const_cast(ptr))); + return ptr; + } + + // Undo what an earlier IgnoreObject() call promised and asked to do. + // At the time of this call 'ptr' must point at or inside of an active + // allocated object which was previously registered with IgnoreObject(). + static void UnIgnoreObject(const void* ptr); + + // ----------------------------------------------------------------------- // + // Internal types defined in .cc + + class Allocator; + struct RangeValue; + + private: + + // ----------------------------------------------------------------------- // + // Various helpers + + // Create the name of the heap profile file. + // Should be deleted via Allocator::Free(). + char* MakeProfileNameLocked(); + + // Helper for constructors + void Create(const char *name, bool make_start_snapshot); + + enum ShouldSymbolize { SYMBOLIZE, DO_NOT_SYMBOLIZE }; + + // Helper for *NoLeaks and *SameHeap + bool DoNoLeaks(ShouldSymbolize should_symbolize); + + // Helper for NoGlobalLeaks, also called by the global destructor. + static bool NoGlobalLeaksMaybeSymbolize(ShouldSymbolize should_symbolize); + + // These used to be public, but they are now deprecated. + // Will remove entirely when all internal uses are fixed. + // In the meantime, use friendship so the unittest can still test them. + static void* GetDisableChecksStart(); + static void DisableChecksToHereFrom(const void* start_address); + static void DisableChecksIn(const char* pattern); + friend void RangeDisabledLeaks(); + friend void NamedTwoDisabledLeaks(); + friend void* RunNamedDisabledLeaks(void*); + friend void TestHeapLeakCheckerNamedDisabling(); + + // Actually implements IgnoreObject(). + static void DoIgnoreObject(const void* ptr); + + // Disable checks based on stack trace entry at a depth <= + // max_depth. Used to hide allocations done inside some special + // libraries. + 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(const void* self_stack_top); + + // Callback we pass to TCMalloc_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 + // thread stacks and registers for all our threads + // as well as do other global-live-data ignoring + // (via IgnoreNonThreadLiveObjectsLocked) + // during the quiet state of all threads being stopped. + // For the argument meaning see the comment by TCMalloc_ListAllProcessThreads. + // Here we only use num_threads and thread_pids, that TCMalloc_ListAllProcessThreads + // fills for us with the number and pids of all the threads of our process + // it found and attached to. + static int IgnoreLiveThreadsLocked(void* parameter, + int num_threads, + pid_t* thread_pids, + va_list ap); + + // Helper for IgnoreAllLiveObjectsLocked and IgnoreLiveThreadsLocked + // that we prefer to execute from IgnoreLiveThreadsLocked + // while all threads are stopped. + // This helper does live object discovery and ignoring + // for all objects that are reachable from everything + // not related to thread stacks and registers. + static void IgnoreNonThreadLiveObjectsLocked(); + + // Helper for IgnoreNonThreadLiveObjectsLocked and IgnoreLiveThreadsLocked + // to discover and ignore all heap objects + // reachable from currently considered live objects + // (live_objects static global variable in out .cc file). + // "name", "name2" are two strings that we print one after another + // in a debug message to describe what kind of live object sources + // are being used. + static void IgnoreLiveObjectsLocked(const char* name, const char* name2); + + // Do the overall whole-program heap leak check if needed; + // returns true when did the leak check. + static bool DoMainHeapCheck(); + + // Type of task for UseProcMapsLocked + enum ProcMapsTask { + RECORD_GLOBAL_DATA, + DISABLE_LIBRARY_ALLOCS + }; + + // Success/Error Return codes for UseProcMapsLocked. + enum ProcMapsResult { + PROC_MAPS_USED, + CANT_OPEN_PROC_MAPS, + NO_SHARED_LIBS_IN_PROC_MAPS + }; + + // Read /proc/self/maps, parse it, and do the 'proc_maps_task' for each line. + static ProcMapsResult UseProcMapsLocked(ProcMapsTask proc_maps_task); + + // A ProcMapsTask to disable allocations from 'library' + // that is mapped to [start_address..end_address) + // (only if library is a certain system library). + static void DisableLibraryAllocsLocked(const char* library, + uintptr_t start_address, + uintptr_t end_address); + + // Return true iff "*ptr" points to a heap object + // ("*ptr" can point at the start or inside of a heap object + // so that this works e.g. for pointers to C++ arrays, C++ strings, + // multiple-inherited objects, or pointers to members). + // We also fill *object_size for this object then + // and we move "*ptr" to point to the very start of the heap object. + static inline bool HaveOnHeapLocked(const void** ptr, size_t* object_size); + + // Helper to shutdown heap leak checker when it's not needed + // or can't function properly. + static void TurnItselfOffLocked(); + + // Internally-used c-tor to start whole-executable checking. + HeapLeakChecker(); + + // ----------------------------------------------------------------------- // + // Friends and externally accessed helpers. + + // Helper for VerifyHeapProfileTableStackGet in the unittest + // to get the recorded allocation caller for ptr, + // which must be a heap object. + static const void* GetAllocCaller(void* ptr); + friend void VerifyHeapProfileTableStackGet(); + + // This gets to execute before constructors for all global objects + static void BeforeConstructorsLocked(); + friend void HeapLeakChecker_BeforeConstructors(); + + // This gets to execute after destructors for all global objects + friend void HeapLeakChecker_AfterDestructors(); + + // Full starting of recommended whole-program checking. + friend void HeapLeakChecker_InternalInitStart(); + + // Runs REGISTER_HEAPCHECK_CLEANUP cleanups and potentially + // calls DoMainHeapCheck + friend void HeapLeakChecker_RunHeapCleanups(); + + // ----------------------------------------------------------------------- // + // Member data. + + class SpinLock* lock_; // to make HeapLeakChecker objects thread-safe + const char* name_; // our remembered name (we own it) + // NULL means this leak checker is a noop + + // Snapshot taken when the checker was created. May be NULL + // for the global heap checker object. We use void* instead of + // HeapProfileTable::Snapshot* to avoid including heap-profile-table.h. + void* start_snapshot_; + + bool has_checked_; // if we have done the leak check, so these are ready: + ssize_t inuse_bytes_increase_; // bytes-in-use increase for this checker + ssize_t inuse_allocs_increase_; // allocations-in-use increase + // for this checker + bool keep_profiles_; // iff we should keep the heap profiles we've made + + // ----------------------------------------------------------------------- // + + // Disallow "evil" constructors. + HeapLeakChecker(const HeapLeakChecker&); + void operator=(const HeapLeakChecker&); +}; + + +// Holds a pointer that will not be traversed by the heap checker. +// Contrast with HeapLeakChecker::IgnoreObject(o), in which o and +// all objects reachable from o are ignored by the heap checker. +template +class HiddenPointer { + public: + explicit HiddenPointer(T* t) + : masked_t_(reinterpret_cast(t) ^ kHideMask) { + } + // Returns unhidden pointer. Be careful where you save the result. + T* get() const { return reinterpret_cast(masked_t_ ^ kHideMask); } + + private: + // Arbitrary value, but not such that xor'ing with it is likely + // to map one valid pointer to another valid pointer: + static const uintptr_t kHideMask = + static_cast(0xF03A5F7BF03A5F7Bll); + uintptr_t masked_t_; +}; + +// A class that exists solely to run its destructor. This class should not be +// used directly, but instead by the REGISTER_HEAPCHECK_CLEANUP macro below. +class PERFTOOLS_DLL_DECL HeapCleaner { + public: + typedef void (*void_function)(void); + HeapCleaner(void_function f); + static void RunHeapCleanups(); + private: + static std::vector* heap_cleanups_; +}; + +// A macro to declare module heap check cleanup tasks +// (they run only if we are doing heap leak checking.) +// 'body' should be the cleanup code to run. 'name' doesn't matter, +// but must be unique amongst all REGISTER_HEAPCHECK_CLEANUP calls. +#define REGISTER_HEAPCHECK_CLEANUP(name, body) \ + namespace { \ + void heapcheck_cleanup_##name() { body; } \ + static HeapCleaner heapcheck_cleaner_##name(&heapcheck_cleanup_##name); \ + } + +#endif // BASE_HEAP_CHECKER_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-profiler.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-profiler.h new file mode 100644 index 000000000..f8076e9fe --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/heap-profiler.h @@ -0,0 +1,105 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* 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: Sanjay Ghemawat + * + * Module for heap-profiling. + * + * For full(er) information, see docs/heapprofile.html + * + * This module can be linked into your program with + * no slowdown caused by this unless you activate the profiler + * using one of the following methods: + * + * 1. Before starting the program, set the environment variable + * "HEAPPROFILE" to be the name of the file to which the profile + * data should be written. + * + * 2. Programmatically, start and stop the profiler using the + * routines "HeapProfilerStart(filename)" and "HeapProfilerStop()". + * + */ + +#ifndef BASE_HEAP_PROFILER_H_ +#define BASE_HEAP_PROFILER_H_ + +#include + +/* Annoying stuff for windows; makes sure clients can import these functions */ +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +/* All this code should be usable from within C apps. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Start profiling and arrange to write profile data to file names + * of the form: "prefix.0000", "prefix.0001", ... + */ +PERFTOOLS_DLL_DECL void HeapProfilerStart(const char* prefix); + +/* Returns non-zero if we are currently profiling the heap. (Returns + * an int rather than a bool so it's usable from C.) This is true + * between calls to HeapProfilerStart() and HeapProfilerStop(), and + * also if the program has been run with HEAPPROFILER, or some other + * way to turn on whole-program profiling. + */ +int IsHeapProfilerRunning(); + +/* Stop heap profiling. Can be restarted again with HeapProfilerStart(), + * but the currently accumulated profiling information will be cleared. + */ +PERFTOOLS_DLL_DECL void HeapProfilerStop(); + +/* Dump a profile now - can be used for dumping at a hopefully + * quiescent state in your program, in order to more easily track down + * memory leaks. Will include the reason in the logged message + */ +PERFTOOLS_DLL_DECL void HeapProfilerDump(const char *reason); + +/* Generate current heap profiling information. + * Returns an empty string when heap profiling is not active. + * The returned pointer is a '\0'-terminated string allocated using malloc() + * and should be free()-ed as soon as the caller does not need it anymore. + */ +PERFTOOLS_DLL_DECL char* GetHeapProfile(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* BASE_HEAP_PROFILER_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension.h new file mode 100644 index 000000000..d203394cd --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension.h @@ -0,0 +1,446 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Extra extensions exported by some malloc implementations. These +// extensions are accessed through a virtual base class so an +// application can link against a malloc that does not implement these +// extensions, and it will get default versions that do nothing. +// +// NOTE FOR C USERS: If you wish to use this functionality from within +// a C program, see malloc_extension_c.h. + +#ifndef BASE_MALLOC_EXTENSION_H_ +#define BASE_MALLOC_EXTENSION_H_ + +#include +// I can't #include config.h in this public API file, but I should +// really use configure (and make malloc_extension.h a .in file) to +// figure out if the system has stdint.h or not. But I'm lazy, so +// for now I'm assuming it's a problem only with MSVC. +#ifndef _MSC_VER +#include +#endif +#include +#include + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +static const int kMallocHistogramSize = 64; + +// One day, we could support other types of writers (perhaps for C?) +typedef std::string MallocExtensionWriter; + +namespace base { +struct MallocRange; +} + +// Interface to a pluggable system allocator. +class PERFTOOLS_DLL_DECL SysAllocator { + public: + SysAllocator() { + } + virtual ~SysAllocator(); + + // Allocates "size"-byte of memory from system aligned with "alignment". + // Returns NULL if failed. Otherwise, the returned pointer p up to and + // including (p + actual_size -1) have been allocated. + virtual void* Alloc(size_t size, size_t *actual_size, size_t alignment) = 0; +}; + +// The default implementations of the following routines do nothing. +// All implementations should be thread-safe; the current one +// (TCMallocImplementation) is. +class PERFTOOLS_DLL_DECL MallocExtension { + public: + virtual ~MallocExtension(); + + // Call this very early in the program execution -- say, in a global + // constructor -- to set up parameters and state needed by all + // instrumented malloc implemenatations. One example: this routine + // sets environemnt variables to tell STL to use libc's malloc() + // instead of doing its own memory management. This is safe to call + // multiple times, as long as each time is before threads start up. + static void Initialize(); + + // See "verify_memory.h" to see what these routines do + virtual bool VerifyAllMemory(); + virtual bool VerifyNewMemory(const void* p); + virtual bool VerifyArrayNewMemory(const void* p); + virtual bool VerifyMallocMemory(const void* p); + virtual bool MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]); + + // Get a human readable description of the following malloc data structures. + // - Total inuse memory by application. + // - Free memory(thread, central and page heap), + // - Freelist of central cache, each class. + // - Page heap freelist. + // The state is stored as a null-terminated string + // in a prefix of "buffer[0,buffer_length-1]". + // REQUIRES: buffer_length > 0. + virtual void GetStats(char* buffer, int buffer_length); + + // Outputs to "writer" a sample of live objects and the stack traces + // that allocated these objects. The format of the returned output + // is equivalent to the output of the heap profiler and can + // therefore be passed to "pprof". This function is equivalent to + // ReadStackTraces. The main difference is that this function returns + // serialized data appropriately formatted for use by the pprof tool. + // + // Since gperftools 2.8 heap samples are not de-duplicated by the + // library anymore. + // + // NOTE: by default, tcmalloc does not do any heap sampling, and this + // function will always return an empty sample. To get useful + // data from GetHeapSample, you must also set the environment + // variable TCMALLOC_SAMPLE_PARAMETER to a value such as 524288. + virtual void GetHeapSample(MallocExtensionWriter* writer); + + // Outputs to "writer" the stack traces that caused growth in the + // address space size. The format of the returned output is + // equivalent to the output of the heap profiler and can therefore + // be passed to "pprof". This function is equivalent to + // ReadHeapGrowthStackTraces. The main difference is that this function + // returns serialized data appropriately formatted for use by the + // pprof tool. (This does not depend on, or require, + // TCMALLOC_SAMPLE_PARAMETER.) + virtual void GetHeapGrowthStacks(MallocExtensionWriter* writer); + + // Invokes func(arg, range) for every controlled memory + // range. *range is filled in with information about the range. + // + // This is a best-effort interface useful only for performance + // analysis. The implementation may not call func at all. + typedef void (RangeFunction)(void*, const base::MallocRange*); + virtual void Ranges(void* arg, RangeFunction func); + + // ------------------------------------------------------------------- + // Control operations for getting and setting malloc implementation + // specific parameters. Some currently useful properties: + // + // generic + // ------- + // "generic.current_allocated_bytes" + // Number of bytes currently allocated by application + // This property is not writable. + // + // "generic.heap_size" + // Number of bytes in the heap == + // current_allocated_bytes + + // fragmentation + + // freed memory regions + // This property is not writable. + // + // "generic.total_physical_bytes" + // Estimate of total bytes of the physical memory usage by the + // allocator == + // current_allocated_bytes + + // fragmentation + + // metadata + // This property is not writable. + // + // tcmalloc + // -------- + // "tcmalloc.max_total_thread_cache_bytes" + // Upper limit on total number of bytes stored across all + // per-thread caches. Default: 16MB. + // + // "tcmalloc.current_total_thread_cache_bytes" + // Number of bytes used across all thread caches. + // This property is not writable. + // + // "tcmalloc.central_cache_free_bytes" + // Number of free bytes in the central cache that have been + // assigned to size classes. They always count towards virtual + // memory usage, and unless the underlying memory is swapped out + // by the OS, they also count towards physical memory usage. + // This property is not writable. + // + // "tcmalloc.transfer_cache_free_bytes" + // Number of free bytes that are waiting to be transfered between + // the central cache and a thread cache. They always count + // towards virtual memory usage, and unless the underlying memory + // is swapped out by the OS, they also count towards physical + // memory usage. This property is not writable. + // + // "tcmalloc.thread_cache_free_bytes" + // Number of free bytes in thread caches. They always count + // towards virtual memory usage, and unless the underlying memory + // is swapped out by the OS, they also count towards physical + // memory usage. This property is not writable. + // + // "tcmalloc.pageheap_free_bytes" + // Number of bytes in free, mapped pages in page heap. These + // bytes can be used to fulfill allocation requests. They + // always count towards virtual memory usage, and unless the + // underlying memory is swapped out by the OS, they also count + // towards physical memory usage. This property is not writable. + // + // "tcmalloc.pageheap_unmapped_bytes" + // Number of bytes in free, unmapped pages in page heap. + // These are bytes that have been released back to the OS, + // possibly by one of the MallocExtension "Release" calls. + // They can be used to fulfill allocation requests, but + // typically incur a page fault. They always count towards + // virtual memory usage, and depending on the OS, typically + // do not count towards physical memory usage. This property + // is not writable. + // ------------------------------------------------------------------- + + // Get the named "property"'s value. Returns true if the property + // is known. Returns false if the property is not a valid property + // name for the current malloc implementation. + // REQUIRES: property != NULL; value != NULL + virtual bool GetNumericProperty(const char* property, size_t* value); + + // Set the named "property"'s value. Returns true if the property + // is known and writable. Returns false if the property is not a + // valid property name for the current malloc implementation, or + // is not writable. + // REQUIRES: property != NULL + virtual bool SetNumericProperty(const char* property, size_t value); + + // Mark the current thread as "idle". This routine may optionally + // be called by threads as a hint to the malloc implementation that + // any thread-specific resources should be released. Note: this may + // be an expensive routine, so it should not be called too often. + // + // Also, if the code that calls this routine will go to sleep for + // a while, it should take care to not allocate anything between + // the call to this routine and the beginning of the sleep. + // + // Most malloc implementations ignore this routine. + virtual void MarkThreadIdle(); + + // Mark the current thread as "busy". This routine should be + // called after MarkThreadIdle() if the thread will now do more + // work. If this method is not called, performance may suffer. + // + // Most malloc implementations ignore this routine. + virtual void MarkThreadBusy(); + + // Gets the system allocator used by the malloc extension instance. Returns + // NULL for malloc implementations that do not support pluggable system + // allocators. + virtual SysAllocator* GetSystemAllocator(); + + // Sets the system allocator to the specified. + // + // Users could register their own system allocators for malloc implementation + // that supports pluggable system allocators, such as TCMalloc, by doing: + // alloc = new MyOwnSysAllocator(); + // MallocExtension::instance()->SetSystemAllocator(alloc); + // It's up to users whether to fall back (recommended) to the default + // system allocator (use GetSystemAllocator() above) or not. The caller is + // responsible to any necessary locking. + // See tcmalloc/system-alloc.h for the interface and + // tcmalloc/memfs_malloc.cc for the examples. + // + // It's a no-op for malloc implementations that do not support pluggable + // system allocators. + virtual void SetSystemAllocator(SysAllocator *a); + + // Try to release num_bytes of free memory back to the operating + // system for reuse. Use this extension with caution -- to get this + // memory back may require faulting pages back in by the OS, and + // that may be slow. (Currently only implemented in tcmalloc.) + virtual void ReleaseToSystem(size_t num_bytes); + + // Same as ReleaseToSystem() but release as much memory as possible. + virtual void ReleaseFreeMemory(); + + // Sets the rate at which we release unused memory to the system. + // Zero means we never release memory back to the system. Increase + // this flag to return memory faster; decrease it to return memory + // slower. Reasonable rates are in the range [0,10]. (Currently + // only implemented in tcmalloc). + virtual void SetMemoryReleaseRate(double rate); + + // Gets the release rate. Returns a value < 0 if unknown. + virtual double GetMemoryReleaseRate(); + + // Returns the estimated number of bytes that will be allocated for + // a request of "size" bytes. This is an estimate: an allocation of + // SIZE bytes may reserve more bytes, but will never reserve less. + // (Currently only implemented in tcmalloc, other implementations + // always return SIZE.) + // This is equivalent to malloc_good_size() in OS X. + virtual size_t GetEstimatedAllocatedSize(size_t size); + + // Returns the actual number N of bytes reserved by tcmalloc for the + // pointer p. The client is allowed to use the range of bytes + // [p, p+N) in any way it wishes (i.e. N is the "usable size" of this + // allocation). This number may be equal to or greater than the number + // of bytes requested when p was allocated. + // p must have been allocated by this malloc implementation, + // must not be an interior pointer -- that is, must be exactly + // the pointer returned to by malloc() et al., not some offset + // from that -- and should not have been freed yet. p may be NULL. + // (Currently only implemented in tcmalloc; other implementations + // will return 0.) + // This is equivalent to malloc_size() in OS X, malloc_usable_size() + // in glibc, and _msize() for windows. + virtual size_t GetAllocatedSize(const void* p); + + // Returns kOwned if this malloc implementation allocated the memory + // pointed to by p, or kNotOwned if some other malloc implementation + // allocated it or p is NULL. May also return kUnknownOwnership if + // the malloc implementation does not keep track of ownership. + // REQUIRES: p must be a value returned from a previous call to + // malloc(), calloc(), realloc(), memalign(), posix_memalign(), + // valloc(), pvalloc(), new, or new[], and must refer to memory that + // is currently allocated (so, for instance, you should not pass in + // a pointer after having called free() on it). + enum Ownership { + // NOTE: Enum values MUST be kept in sync with the version in + // malloc_extension_c.h + kUnknownOwnership = 0, + kOwned, + kNotOwned + }; + virtual Ownership GetOwnership(const void* p); + + // The current malloc implementation. Always non-NULL. + static MallocExtension* instance(); + + // Change the malloc implementation. Typically called by the + // malloc implementation during initialization. + static void Register(MallocExtension* implementation); + + // Returns detailed information about malloc's freelists. For each list, + // return a FreeListInfo: + struct FreeListInfo { + size_t min_object_size; + size_t max_object_size; + size_t total_bytes_free; + const char* type; + }; + // Each item in the vector refers to a different freelist. The lists + // are identified by the range of allocations that objects in the + // list can satisfy ([min_object_size, max_object_size]) and the + // type of freelist (see below). The current size of the list is + // returned in total_bytes_free (which count against a processes + // resident and virtual size). + // + // Currently supported types are: + // + // "tcmalloc.page{_unmapped}" - tcmalloc's page heap. An entry for each size + // class in the page heap is returned. Bytes in "page_unmapped" + // are no longer backed by physical memory and do not count against + // the resident size of a process. + // + // "tcmalloc.large{_unmapped}" - tcmalloc's list of objects larger + // than the largest page heap size class. Only one "large" + // entry is returned. There is no upper-bound on the size + // of objects in the large free list; this call returns + // kint64max for max_object_size. Bytes in + // "large_unmapped" are no longer backed by physical memory + // and do not count against the resident size of a process. + // + // "tcmalloc.central" - tcmalloc's central free-list. One entry per + // size-class is returned. Never unmapped. + // + // "debug.free_queue" - free objects queued by the debug allocator + // and not returned to tcmalloc. + // + // "tcmalloc.thread" - tcmalloc's per-thread caches. Never unmapped. + virtual void GetFreeListSizes(std::vector* v); + + // Get a list of stack traces of sampled allocation points. Returns + // a pointer to a "new[]-ed" result array, and stores the sample + // period in "sample_period". + // + // The state is stored as a sequence of adjacent entries + // in the returned array. Each entry has the following form: + // uintptr_t count; // Number of objects with following trace + // uintptr_t size; // Total size of objects with following trace + // uintptr_t depth; // Number of PC values in stack trace + // void* stack[depth]; // PC values that form the stack trace + // + // The list of entries is terminated by a "count" of 0. + // + // It is the responsibility of the caller to "delete[]" the returned array. + // + // May return NULL to indicate no results. + // + // This is an internal extension. Callers should use the more + // convenient "GetHeapSample(string*)" method defined above. + virtual void** ReadStackTraces(int* sample_period); + + // Like ReadStackTraces(), but returns stack traces that caused growth + // in the address space size. + virtual void** ReadHeapGrowthStackTraces(); + + // Returns the size in bytes of the calling threads cache. + virtual size_t GetThreadCacheSize(); + + // Like MarkThreadIdle, but does not destroy the internal data + // structures of the thread cache. When the thread resumes, it wil + // have an empty cache but will not need to pay to reconstruct the + // cache data structures. + virtual void MarkThreadTemporarilyIdle(); +}; + +namespace base { + +// Information passed per range. More fields may be added later. +struct MallocRange { + enum Type { + INUSE, // Application is using this range + FREE, // Range is currently free + UNMAPPED, // Backing physical memory has been returned to the OS + UNKNOWN + // More enum values may be added in the future + }; + + uintptr_t address; // Address of range + size_t length; // Byte length of range + Type type; // Type of this range + double fraction; // Fraction of range that is being used (0 if !INUSE) + + // Perhaps add the following: + // - stack trace if this range was sampled + // - heap growth stack trace if applicable to this range + // - age when allocated (for inuse) or freed (if not in use) +}; + +} // namespace base + +#endif // BASE_MALLOC_EXTENSION_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension_c.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension_c.h new file mode 100644 index 000000000..a43534f30 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_extension_c.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2008, 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 + * + * C shims for the C++ malloc_extension.h. See malloc_extension.h for + * details. Note these C shims always work on + * MallocExtension::instance(); it is not possible to have more than + * one MallocExtension object in C applications. + */ + +#ifndef _MALLOC_EXTENSION_C_H_ +#define _MALLOC_EXTENSION_C_H_ + +#include +#include + +/* Annoying stuff for windows -- makes sure clients can import these fns */ +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define kMallocExtensionHistogramSize 64 + +PERFTOOLS_DLL_DECL int MallocExtension_VerifyAllMemory(void); +PERFTOOLS_DLL_DECL int MallocExtension_VerifyNewMemory(const void* p); +PERFTOOLS_DLL_DECL int MallocExtension_VerifyArrayNewMemory(const void* p); +PERFTOOLS_DLL_DECL int MallocExtension_VerifyMallocMemory(const void* p); +PERFTOOLS_DLL_DECL int MallocExtension_MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocExtensionHistogramSize]); +PERFTOOLS_DLL_DECL void MallocExtension_GetStats(char* buffer, int buffer_length); + +/* TODO(csilvers): write a C version of these routines, that perhaps + * takes a function ptr and a void *. + */ +/* void MallocExtension_GetHeapSample(string* result); */ +/* void MallocExtension_GetHeapGrowthStacks(string* result); */ + +PERFTOOLS_DLL_DECL int MallocExtension_GetNumericProperty(const char* property, size_t* value); +PERFTOOLS_DLL_DECL int MallocExtension_SetNumericProperty(const char* property, size_t value); +PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadIdle(void); +PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadBusy(void); +PERFTOOLS_DLL_DECL void MallocExtension_ReleaseToSystem(size_t num_bytes); +PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory(void); +PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size); +PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(const void* p); +PERFTOOLS_DLL_DECL size_t MallocExtension_GetThreadCacheSize(void); +PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadTemporarilyIdle(void); + +/* + * NOTE: These enum values MUST be kept in sync with the version in + * malloc_extension.h + */ +typedef enum { + MallocExtension_kUnknownOwnership = 0, + MallocExtension_kOwned, + MallocExtension_kNotOwned +} MallocExtension_Ownership; + +PERFTOOLS_DLL_DECL MallocExtension_Ownership MallocExtension_GetOwnership(const void* p); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _MALLOC_EXTENSION_C_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook.h new file mode 100644 index 000000000..ab655f671 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook.h @@ -0,0 +1,359 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Some of our malloc implementations can invoke the following hooks whenever +// memory is allocated or deallocated. MallocHook is thread-safe, and things +// you do before calling AddFooHook(MyHook) are visible to any resulting calls +// to MyHook. Hooks must be thread-safe. If you write: +// +// CHECK(MallocHook::AddNewHook(&MyNewHook)); +// +// MyNewHook will be invoked in subsequent calls in the current thread, but +// there are no guarantees on when it might be invoked in other threads. +// +// There are a limited number of slots available for each hook type. Add*Hook +// will return false if there are no slots available. Remove*Hook will return +// false if the given hook was not already installed. +// +// The order in which individual hooks are called in Invoke*Hook is undefined. +// +// It is safe for a hook to remove itself within Invoke*Hook and add other +// hooks. Any hooks added inside a hook invocation (for the same hook type) +// will not be invoked for the current invocation. +// +// One important user of these hooks is the heap profiler. +// +// CAVEAT: If you add new MallocHook::Invoke* calls then those calls must be +// directly in the code of the (de)allocation function that is provided to the +// user and that function must have an ATTRIBUTE_SECTION(malloc_hook) attribute. +// +// Note: the Invoke*Hook() functions are defined in malloc_hook-inl.h. If you +// need to invoke a hook (which you shouldn't unless you're part of tcmalloc), +// be sure to #include malloc_hook-inl.h in addition to malloc_hook.h. +// +// NOTE FOR C USERS: If you want to use malloc_hook functionality from +// a C program, #include malloc_hook_c.h instead of this file. + +#ifndef _MALLOC_HOOK_H_ +#define _MALLOC_HOOK_H_ + +#include +#include +extern "C" { +#include "malloc_hook_c.h" // a C version of the malloc_hook interface +} + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +// The C++ methods below call the C version (MallocHook_*), and thus +// convert between an int and a bool. Windows complains about this +// (a "performance warning") which we don't care about, so we suppress. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4800) +#endif + +// Note: malloc_hook_c.h defines MallocHook_*Hook and +// MallocHook_{Add,Remove}*Hook. The version of these inside the MallocHook +// class are defined in terms of the malloc_hook_c version. See malloc_hook_c.h +// for details of these types/functions. + +class PERFTOOLS_DLL_DECL MallocHook { + public: + // The NewHook is invoked whenever an object is allocated. + // It may be passed NULL if the allocator returned NULL. + typedef MallocHook_NewHook NewHook; + inline static bool AddNewHook(NewHook hook) { + return MallocHook_AddNewHook(hook); + } + inline static bool RemoveNewHook(NewHook hook) { + return MallocHook_RemoveNewHook(hook); + } + inline static void InvokeNewHook(const void* p, size_t s); + + // The DeleteHook is invoked whenever an object is deallocated. + // It may be passed NULL if the caller is trying to delete NULL. + typedef MallocHook_DeleteHook DeleteHook; + inline static bool AddDeleteHook(DeleteHook hook) { + return MallocHook_AddDeleteHook(hook); + } + inline static bool RemoveDeleteHook(DeleteHook hook) { + return MallocHook_RemoveDeleteHook(hook); + } + inline static void InvokeDeleteHook(const void* p); + + // The PreMmapHook is invoked with mmap or mmap64 arguments just + // before the call is actually made. Such a hook may be useful + // in memory limited contexts, to catch allocations that will exceed + // a memory limit, and take outside actions to increase that limit. + typedef MallocHook_PreMmapHook PreMmapHook; + inline static bool AddPreMmapHook(PreMmapHook hook) { + return MallocHook_AddPreMmapHook(hook); + } + inline static bool RemovePreMmapHook(PreMmapHook hook) { + return MallocHook_RemovePreMmapHook(hook); + } + inline static void InvokePreMmapHook(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); + + // The MmapReplacement is invoked after the PreMmapHook but before + // the call is actually made. The MmapReplacement should return true + // if it handled the call, or false if it is still necessary to + // call mmap/mmap64. + // This should be used only by experts, and users must be be + // extremely careful to avoid recursive calls to mmap. The replacement + // should be async signal safe. + // Only one MmapReplacement is supported. After setting an MmapReplacement + // you must call RemoveMmapReplacement before calling SetMmapReplacement + // again. + typedef MallocHook_MmapReplacement MmapReplacement; + inline static bool SetMmapReplacement(MmapReplacement hook) { + return MallocHook_SetMmapReplacement(hook); + } + inline static bool RemoveMmapReplacement(MmapReplacement hook) { + return MallocHook_RemoveMmapReplacement(hook); + } + inline static bool InvokeMmapReplacement(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result); + + + // The MmapHook is invoked whenever a region of memory is mapped. + // It may be passed MAP_FAILED if the mmap failed. + typedef MallocHook_MmapHook MmapHook; + inline static bool AddMmapHook(MmapHook hook) { + return MallocHook_AddMmapHook(hook); + } + inline static bool RemoveMmapHook(MmapHook hook) { + return MallocHook_RemoveMmapHook(hook); + } + inline static void InvokeMmapHook(const void* result, + const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); + + // The MunmapReplacement is invoked with munmap arguments just before + // the call is actually made. The MunmapReplacement should return true + // if it handled the call, or false if it is still necessary to + // call munmap. + // This should be used only by experts. The replacement should be + // async signal safe. + // Only one MunmapReplacement is supported. After setting an + // MunmapReplacement you must call RemoveMunmapReplacement before + // calling SetMunmapReplacement again. + typedef MallocHook_MunmapReplacement MunmapReplacement; + inline static bool SetMunmapReplacement(MunmapReplacement hook) { + return MallocHook_SetMunmapReplacement(hook); + } + inline static bool RemoveMunmapReplacement(MunmapReplacement hook) { + return MallocHook_RemoveMunmapReplacement(hook); + } + inline static bool InvokeMunmapReplacement(const void* p, + size_t size, + int* result); + + // The MunmapHook is invoked whenever a region of memory is unmapped. + typedef MallocHook_MunmapHook MunmapHook; + inline static bool AddMunmapHook(MunmapHook hook) { + return MallocHook_AddMunmapHook(hook); + } + inline static bool RemoveMunmapHook(MunmapHook hook) { + return MallocHook_RemoveMunmapHook(hook); + } + inline static void InvokeMunmapHook(const void* p, size_t size); + + // The MremapHook is invoked whenever a region of memory is remapped. + typedef MallocHook_MremapHook MremapHook; + inline static bool AddMremapHook(MremapHook hook) { + return MallocHook_AddMremapHook(hook); + } + inline static bool RemoveMremapHook(MremapHook hook) { + return MallocHook_RemoveMremapHook(hook); + } + inline static void InvokeMremapHook(const void* result, + const void* old_addr, + size_t old_size, + size_t new_size, + int flags, + const void* new_addr); + + // The PreSbrkHook is invoked just before 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. It may be useful in memory-limited contexts, + // to catch allocations that will exceed the limit and take outside + // actions to increase such a limit. + typedef MallocHook_PreSbrkHook PreSbrkHook; + inline static bool AddPreSbrkHook(PreSbrkHook hook) { + return MallocHook_AddPreSbrkHook(hook); + } + inline static bool RemovePreSbrkHook(PreSbrkHook hook) { + return MallocHook_RemovePreSbrkHook(hook); + } + inline static void InvokePreSbrkHook(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 MallocHook_SbrkHook SbrkHook; + inline static bool AddSbrkHook(SbrkHook hook) { + return MallocHook_AddSbrkHook(hook); + } + inline static bool RemoveSbrkHook(SbrkHook hook) { + return MallocHook_RemoveSbrkHook(hook); + } + inline static void InvokeSbrkHook(const void* result, ptrdiff_t increment); + + // Get the current stack trace. Try to skip all routines up to and + // and including the caller of MallocHook::Invoke*. + // Use "skip_count" (similarly to GetStackTrace from stacktrace.h) + // as a hint about how many routines to skip if better information + // is not available. + inline static int GetCallerStackTrace(void** result, int max_depth, + int skip_count) { + return MallocHook_GetCallerStackTrace(result, max_depth, skip_count); + } + + // Unhooked versions of mmap() and munmap(). These should be used + // only by experts, since they bypass heapchecking, etc. + // Note: These do not run hooks, but they still use the MmapReplacement + // and MunmapReplacement. + static void* UnhookedMMap(void *start, size_t length, int prot, int flags, + int fd, off_t offset); + static int UnhookedMUnmap(void *start, size_t length); + + // The following are DEPRECATED. + inline static NewHook GetNewHook(); + inline static NewHook SetNewHook(NewHook hook) { + return MallocHook_SetNewHook(hook); + } + + inline static DeleteHook GetDeleteHook(); + inline static DeleteHook SetDeleteHook(DeleteHook hook) { + return MallocHook_SetDeleteHook(hook); + } + + inline static PreMmapHook GetPreMmapHook(); + inline static PreMmapHook SetPreMmapHook(PreMmapHook hook) { + return MallocHook_SetPreMmapHook(hook); + } + + inline static MmapHook GetMmapHook(); + inline static MmapHook SetMmapHook(MmapHook hook) { + return MallocHook_SetMmapHook(hook); + } + + inline static MunmapHook GetMunmapHook(); + inline static MunmapHook SetMunmapHook(MunmapHook hook) { + return MallocHook_SetMunmapHook(hook); + } + + inline static MremapHook GetMremapHook(); + inline static MremapHook SetMremapHook(MremapHook hook) { + return MallocHook_SetMremapHook(hook); + } + + inline static PreSbrkHook GetPreSbrkHook(); + inline static PreSbrkHook SetPreSbrkHook(PreSbrkHook hook) { + return MallocHook_SetPreSbrkHook(hook); + } + + inline static SbrkHook GetSbrkHook(); + inline static SbrkHook SetSbrkHook(SbrkHook hook) { + return MallocHook_SetSbrkHook(hook); + } + // End of DEPRECATED methods. + + private: + // Slow path versions of Invoke*Hook. + static void InvokeNewHookSlow(const void* p, size_t s); + static void InvokeDeleteHookSlow(const void* p); + static void InvokePreMmapHookSlow(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); + static void InvokeMmapHookSlow(const void* result, + const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); + static bool InvokeMmapReplacementSlow(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result); + static void InvokeMunmapHookSlow(const void* p, size_t size); + static bool InvokeMunmapReplacementSlow(const void* p, + size_t size, + int* result); + static void InvokeMremapHookSlow(const void* result, + const void* old_addr, + size_t old_size, + size_t new_size, + int flags, + const void* new_addr); + static void InvokePreSbrkHookSlow(ptrdiff_t increment); + static void InvokeSbrkHookSlow(const void* result, ptrdiff_t increment); +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + +#endif /* _MALLOC_HOOK_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook_c.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook_c.h new file mode 100644 index 000000000..5cee782ee --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/malloc_hook_c.h @@ -0,0 +1,173 @@ +/* Copyright (c) 2008, 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 + * + * C shims for the C++ malloc_hook.h. See malloc_hook.h for details + * on how to use these. + */ + +#ifndef _MALLOC_HOOK_C_H_ +#define _MALLOC_HOOK_C_H_ + +#include +#include + +/* Annoying stuff for windows; makes sure clients can import these functions */ +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Get the current stack trace. Try to skip all routines up to and + * and including the caller of MallocHook::Invoke*. + * Use "skip_count" (similarly to GetStackTrace from stacktrace.h) + * as a hint about how many routines to skip if better information + * is not available. + */ +PERFTOOLS_DLL_DECL +int MallocHook_GetCallerStackTrace(void** result, int max_depth, + int skip_count); + +/* The MallocHook_{Add,Remove}*Hook functions return 1 on success and 0 on + * failure. + */ + +typedef void (*MallocHook_NewHook)(const void* ptr, size_t size); +PERFTOOLS_DLL_DECL +int MallocHook_AddNewHook(MallocHook_NewHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveNewHook(MallocHook_NewHook hook); + +typedef void (*MallocHook_DeleteHook)(const void* ptr); +PERFTOOLS_DLL_DECL +int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook); + +typedef void (*MallocHook_PreMmapHook)(const void *start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); +PERFTOOLS_DLL_DECL +int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook); + +typedef void (*MallocHook_MmapHook)(const void* result, + const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset); +PERFTOOLS_DLL_DECL +int MallocHook_AddMmapHook(MallocHook_MmapHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook); + +typedef int (*MallocHook_MmapReplacement)(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result); +int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook); +int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook); + +typedef void (*MallocHook_MunmapHook)(const void* ptr, size_t size); +PERFTOOLS_DLL_DECL +int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook); + +typedef int (*MallocHook_MunmapReplacement)(const void* ptr, + size_t size, + int* result); +int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook); +int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook); + +typedef void (*MallocHook_MremapHook)(const void* result, + const void* old_addr, + size_t old_size, + size_t new_size, + int flags, + const void* new_addr); +PERFTOOLS_DLL_DECL +int MallocHook_AddMremapHook(MallocHook_MremapHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook); + +typedef void (*MallocHook_PreSbrkHook)(ptrdiff_t increment); +PERFTOOLS_DLL_DECL +int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook); + +typedef void (*MallocHook_SbrkHook)(const void* result, ptrdiff_t increment); +PERFTOOLS_DLL_DECL +int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook); +PERFTOOLS_DLL_DECL +int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook); + +/* The following are DEPRECATED. */ +PERFTOOLS_DLL_DECL +MallocHook_NewHook MallocHook_SetNewHook(MallocHook_NewHook hook); +PERFTOOLS_DLL_DECL +MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook); +PERFTOOLS_DLL_DECL +MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook); +PERFTOOLS_DLL_DECL +MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook); +PERFTOOLS_DLL_DECL +MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook); +PERFTOOLS_DLL_DECL +MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook); +PERFTOOLS_DLL_DECL +MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook); +PERFTOOLS_DLL_DECL +MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook); +/* End of DEPRECATED functions. */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _MALLOC_HOOK_C_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/nallocx.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/nallocx.h new file mode 100644 index 000000000..01f874ca2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/nallocx.h @@ -0,0 +1,37 @@ +#ifndef _NALLOCX_H_ +#define _NALLOCX_H_ +#include + +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define MALLOCX_LG_ALIGN(la) ((int)(la)) + +/* + * The nallocx function allocates no memory, but it performs the same size + * computation as the malloc function, and returns the real size of the + * allocation that would result from the equivalent malloc function call. + * nallocx is a malloc extension originally implemented by jemalloc: + * http://www.unix.com/man-page/freebsd/3/nallocx/ + * + * Note, we only support MALLOCX_LG_ALIGN flag and nothing else. + */ +PERFTOOLS_DLL_DECL size_t nallocx(size_t size, int flags); + +/* same as above but never weak */ +PERFTOOLS_DLL_DECL size_t tc_nallocx(size_t size, int flags); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _NALLOCX_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/profiler.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/profiler.h new file mode 100644 index 000000000..89e34a227 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/profiler.h @@ -0,0 +1,173 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* 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: Sanjay Ghemawat + * + * Module for CPU profiling based on periodic pc-sampling. + * + * For full(er) information, see docs/cpuprofile.html + * + * This module is linked into your program with + * no slowdown caused by this unless you activate the profiler + * using one of the following methods: + * + * 1. Before starting the program, set the environment variable + * "CPUPROFILE" to be the name of the file to which the profile + * data should be written. + * + * 2. Programmatically, start and stop the profiler using the + * routines "ProfilerStart(filename)" and "ProfilerStop()". + * + * + * (Note: if using linux 2.4 or earlier, only the main thread may be + * profiled.) + * + * Use pprof to view the resulting profile output. + * % pprof + * % pprof --gv + * + * These functions are thread-safe. + */ + +#ifndef BASE_PROFILER_H_ +#define BASE_PROFILER_H_ + +#include /* For time_t */ + +/* Annoying stuff for windows; makes sure clients can import these functions */ +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +/* All this code should be usable from within C apps. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Profiler options, for use with ProfilerStartWithOptions. To use: + * + * struct ProfilerOptions options; + * memset(&options, 0, sizeof options); + * + * then fill in fields as needed. + * + * This structure is intended to be usable from C code, so no constructor + * is provided to initialize it. (Use memset as described above). + */ +struct ProfilerOptions { + /* Filter function and argument. + * + * If filter_in_thread is not NULL, when a profiling tick is delivered + * the profiler will call: + * + * (*filter_in_thread)(filter_in_thread_arg) + * + * If it returns nonzero, the sample will be included in the profile. + * Note that filter_in_thread runs in a signal handler, so must be + * async-signal-safe. + * + * A typical use would be to set up filter results for each thread + * in the system before starting the profiler, then to make + * filter_in_thread be a very simple function which retrieves those + * results in an async-signal-safe way. Retrieval could be done + * using thread-specific data, or using a shared data structure that + * supports async-signal-safe lookups. + */ + int (*filter_in_thread)(void *arg); + void *filter_in_thread_arg; +}; + +/* Start profiling and write profile info into fname, discarding any + * existing profiling data in that file. + * + * This is equivalent to calling ProfilerStartWithOptions(fname, NULL). + */ +PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname); + +/* Start profiling and write profile into fname, discarding any + * existing profiling data in that file. + * + * The profiler is configured using the options given by 'options'. + * Options which are not specified are given default values. + * + * 'options' may be NULL, in which case all are given default values. + * + * Returns nonzero if profiling was started successfully, or zero else. + */ +PERFTOOLS_DLL_DECL int ProfilerStartWithOptions( + const char *fname, const struct ProfilerOptions *options); + +/* Stop profiling. Can be started again with ProfilerStart(), but + * the currently accumulated profiling data will be cleared. + */ +PERFTOOLS_DLL_DECL void ProfilerStop(void); + +/* Flush any currently buffered profiling state to the profile file. + * Has no effect if the profiler has not been started. + */ +PERFTOOLS_DLL_DECL void ProfilerFlush(void); + + +/* DEPRECATED: these functions were used to enable/disable profiling + * in the current thread, but no longer do anything. + */ +PERFTOOLS_DLL_DECL void ProfilerEnable(void); +PERFTOOLS_DLL_DECL void ProfilerDisable(void); + +/* Returns nonzero if profile is currently enabled, zero if it's not. */ +PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads(void); + +/* Routine for registering new threads with the profiler. + */ +PERFTOOLS_DLL_DECL void ProfilerRegisterThread(void); + +/* Stores state about profiler's current status into "*state". */ +struct ProfilerState { + int enabled; /* Is profiling currently enabled? */ + time_t start_time; /* If enabled, when was profiling started? */ + char profile_name[1024]; /* Name of profile file being written, or '\0' */ + int samples_gathered; /* Number of samples gathered so far (or 0) */ +}; +PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(struct ProfilerState* state); + +/* Returns the current stack trace, to be called from a SIGPROF handler. */ +PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( + void** result, int max_depth, int skip_count, const void *uc); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* BASE_PROFILER_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/stacktrace.h b/trunk/3rdparty/gperftools-2-fit/src/gperftools/stacktrace.h new file mode 100644 index 000000000..a0890f488 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/stacktrace.h @@ -0,0 +1,117 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Routines to extract the current stack trace. These functions are +// thread-safe. + +#ifndef GOOGLE_STACKTRACE_H_ +#define GOOGLE_STACKTRACE_H_ + +// Annoying stuff for windows -- makes sure clients can import these functions +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + + +// Skips the most recent "skip_count" stack frames (also skips the +// frame generated for the "GetStackFrames" routine itself), and then +// records the pc values for up to the next "max_depth" frames in +// "result", and the corresponding stack frame sizes in "sizes". +// Returns the number of values recorded in "result"/"sizes". +// +// Example: +// main() { foo(); } +// foo() { bar(); } +// bar() { +// void* result[10]; +// int sizes[10]; +// int depth = GetStackFrames(result, sizes, 10, 1); +// } +// +// The GetStackFrames call will skip the frame for "bar". It will +// return 2 and will produce pc values that map to the following +// procedures: +// result[0] foo +// result[1] main +// (Actually, there may be a few more entries after "main" to account for +// startup procedures.) +// And corresponding stack frame sizes will also be recorded: +// sizes[0] 16 +// sizes[1] 16 +// (Stack frame sizes of 16 above are just for illustration purposes.) +// Stack frame sizes of 0 or less indicate that those frame sizes couldn't +// be identified. +// +// This routine may return fewer stack frame entries than are +// available. Also note that "result" and "sizes" must both be non-NULL. +extern PERFTOOLS_DLL_DECL int GetStackFrames(void** result, int* sizes, int max_depth, + int skip_count); + +// Same as above, but to be used from a signal handler. The "uc" parameter +// should be the pointer to ucontext_t which was passed as the 3rd parameter +// to sa_sigaction signal handler. It may help the unwinder to get a +// better stack trace under certain conditions. The "uc" may safely be NULL. +extern PERFTOOLS_DLL_DECL int GetStackFramesWithContext(void** result, int* sizes, int max_depth, + int skip_count, const void *uc); + +// This is similar to the GetStackFrames routine, except that it returns +// the stack trace only, and not the stack frame sizes as well. +// Example: +// main() { foo(); } +// foo() { bar(); } +// bar() { +// void* result[10]; +// int depth = GetStackTrace(result, 10, 1); +// } +// +// This produces: +// result[0] foo +// result[1] main +// .... ... +// +// "result" must not be NULL. +extern PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth, + int skip_count); + +// Same as above, but to be used from a signal handler. The "uc" parameter +// should be the pointer to ucontext_t which was passed as the 3rd parameter +// to sa_sigaction signal handler. It may help the unwinder to get a +// better stack trace under certain conditions. The "uc" may safely be NULL. +extern PERFTOOLS_DLL_DECL int GetStackTraceWithContext(void** result, int max_depth, + int skip_count, const void *uc); + +#endif /* GOOGLE_STACKTRACE_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/gperftools/tcmalloc.h.in b/trunk/3rdparty/gperftools-2-fit/src/gperftools/tcmalloc.h.in new file mode 100644 index 000000000..0c8a3ddcf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/gperftools/tcmalloc.h.in @@ -0,0 +1,163 @@ +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2003, 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: Sanjay Ghemawat + * .h file by Craig Silverstein + */ + +#ifndef TCMALLOC_TCMALLOC_H_ +#define TCMALLOC_TCMALLOC_H_ + +#include /* for size_t */ +#ifdef __cplusplus +#include /* for std::nothrow_t, std::align_val_t */ +#endif + +/* Define the version number so folks can check against it */ +#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@ +#define TC_VERSION_MINOR @TC_VERSION_MINOR@ +#define TC_VERSION_PATCH "@TC_VERSION_PATCH@" +#define TC_VERSION_STRING "gperftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@" + +/* For struct mallinfo, if it's defined. */ +#if @ac_cv_have_struct_mallinfo@ +# include +#endif + +#ifndef PERFTOOLS_NOTHROW + +#if __cplusplus >= 201103L +#define PERFTOOLS_NOTHROW noexcept +#elif defined(__cplusplus) +#define PERFTOOLS_NOTHROW throw() +#else +# ifdef __GNUC__ +# define PERFTOOLS_NOTHROW __attribute__((__nothrow__)) +# else +# define PERFTOOLS_NOTHROW +# endif +#endif + +#endif + +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /* + * Returns a human-readable version string. If major, minor, + * and/or patch are not NULL, they are set to the major version, + * minor version, and patch-code (a string, usually ""). + */ + PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor, + const char** patch) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment, + size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr, + size_t align, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW; +#if @ac_cv_have_struct_mallinfo@ + PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW; +#endif + + /* + * This is an alias for MallocExtension::instance()->GetAllocatedSize(). + * It is equivalent to + * OS X: malloc_size() + * glibc: malloc_usable_size() + * Windows: _msize() + */ + PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW; + +#ifdef __cplusplus + PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_new(size_t size); + PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray(size_t size); + PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + +#if @ac_cv_have_std_align_val_t@ && __cplusplus >= 201703L + PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; +#endif +} +#endif + +/* We're only un-defining for public */ +#if !defined(GPERFTOOLS_CONFIG_H_) + +#undef PERFTOOLS_NOTHROW + +#endif /* GPERFTOOLS_CONFIG_H_ */ + +#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-checker-bcad.cc b/trunk/3rdparty/gperftools-2-fit/src/heap-checker-bcad.cc new file mode 100644 index 000000000..8b0dbe139 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-checker-bcad.cc @@ -0,0 +1,93 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// +// A file to ensure that components of heap leak checker run before +// all global object constructors and after all global object +// destructors. +// +// This file must be the last library any binary links against. +// Otherwise, the heap checker may not be able to run early enough to +// catalog all the global objects in your program. If this happens, +// and later in the program you allocate memory and have one of these +// "uncataloged" global objects point to it, the heap checker will +// consider that allocation to be a leak, even though it's not (since +// the allocated object is reachable from global data and hence "live"). + +#include // for abort() +#include + +// A dummy variable to refer from heap-checker.cc. This is to make +// sure this file is not optimized out by the linker. +bool heap_leak_checker_bcad_variable; + +extern void HeapLeakChecker_AfterDestructors(); // in heap-checker.cc + +// A helper class to ensure that some components of heap leak checking +// can happen before construction and after destruction +// of all global/static objects. +class HeapLeakCheckerGlobalPrePost { + public: + HeapLeakCheckerGlobalPrePost() { + if (count_ == 0) { + // The 'new int' will ensure that we have run an initial malloc + // hook, which will set up the heap checker via + // MallocHook_InitAtFirstAllocation_HeapLeakChecker. See malloc_hook.cc. + // This is done in this roundabout fashion in order to avoid self-deadlock + // if we directly called HeapLeakChecker_BeforeConstructors here. + delete new int; + // This needs to be called before the first allocation of an STL + // object, but after libc is done setting up threads (because it + // calls setenv, which requires a thread-aware errno). By + // putting it here, we hope it's the first bit of code executed + // after the libc global-constructor code. + MallocExtension::Initialize(); + } + ++count_; + } + ~HeapLeakCheckerGlobalPrePost() { + if (count_ <= 0) abort(); + --count_; + if (count_ == 0) HeapLeakChecker_AfterDestructors(); + } + private: + // Counter of constructions/destructions of objects of this class + // (just in case there are more than one of them). + static int count_; +}; + +int HeapLeakCheckerGlobalPrePost::count_ = 0; + +// The early-construction/late-destruction global object. +static const HeapLeakCheckerGlobalPrePost heap_leak_checker_global_pre_post; diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-checker.cc b/trunk/3rdparty/gperftools-2-fit/src/heap-checker.cc new file mode 100644 index 000000000..199fc93b0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-checker.cc @@ -0,0 +1,2388 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// + +#include "config.h" + +#include // for O_RDONLY (we use syscall to do actual reads) +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_MMAP +#include +#endif +#ifdef HAVE_PTHREAD +#include +#endif +#include +#include +#include +#include + +#if defined(HAVE_LINUX_PTRACE_H) +#include +#endif +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) +#include +#include +#undef ERROR // windows defines these as macros, which can cause trouble +#undef max +#undef min +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "base/basictypes.h" +#include "base/googleinit.h" +#include "base/logging.h" +#include +#include "base/commandlineflags.h" +#include "base/elfcore.h" // for i386_regs +#include "base/thread_lister.h" +#include "heap-profile-table.h" +#include "base/low_level_alloc.h" +#include "malloc_hook-inl.h" +#include +#include +#include "maybe_threads.h" +#include "memory_region_map.h" +#include "base/spinlock.h" +#include "base/sysinfo.h" +#include "base/stl_allocator.h" + +using std::string; +using std::basic_string; +using std::pair; +using std::map; +using std::set; +using std::vector; +using std::swap; +using std::make_pair; +using std::min; +using std::max; +using std::less; +using std::char_traits; + +// If current process is being ptrace()d, 'TracerPid' in /proc/self/status +// will be non-zero. +static bool IsDebuggerAttached(void) { // only works under linux, probably + char buf[256]; // TracerPid comes relatively earlier in status output + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) { + return false; // Can't tell for sure. + } + const int len = read(fd, buf, sizeof(buf)); + bool rc = false; + if (len > 0) { + const char *const kTracerPid = "TracerPid:\t"; + buf[len - 1] = '\0'; + const char *p = strstr(buf, kTracerPid); + if (p != NULL) { + rc = (strncmp(p + strlen(kTracerPid), "0\n", 2) != 0); + } + } + close(fd); + return rc; +} + +// This is the default if you don't link in -lprofiler +extern "C" { +ATTRIBUTE_WEAK PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads(); +int ProfilingIsEnabledForAllThreads() { return false; } +} + +//---------------------------------------------------------------------- +// Flags that control heap-checking +//---------------------------------------------------------------------- + +DEFINE_string(heap_check, + EnvToString("HEAPCHECK", ""), + "The heap leak checking to be done over the whole executable: " + "\"minimal\", \"normal\", \"strict\", " + "\"draconian\", \"as-is\", and \"local\" " + " or the empty string are the supported choices. " + "(See HeapLeakChecker_InternalInitStart for details.)"); + +DEFINE_bool(heap_check_report, true, "Obsolete"); + +DEFINE_bool(heap_check_before_constructors, + true, + "deprecated; pretty much always true now"); + +DEFINE_bool(heap_check_after_destructors, + EnvToBool("HEAP_CHECK_AFTER_DESTRUCTORS", false), + "If overall heap check is to end after global destructors " + "or right after all REGISTER_HEAPCHECK_CLEANUP's"); + +DEFINE_bool(heap_check_strict_check, true, "Obsolete"); + +DEFINE_bool(heap_check_ignore_global_live, + EnvToBool("HEAP_CHECK_IGNORE_GLOBAL_LIVE", true), + "If overall heap check is to ignore heap objects reachable " + "from the global data"); + +DEFINE_bool(heap_check_identify_leaks, + EnvToBool("HEAP_CHECK_IDENTIFY_LEAKS", false), + "If heap check should generate the addresses of the leaked " + "objects in the memory leak profiles. This may be useful " + "in tracking down leaks where only a small fraction of " + "objects allocated at the same stack trace are leaked."); + +DEFINE_bool(heap_check_ignore_thread_live, + EnvToBool("HEAP_CHECK_IGNORE_THREAD_LIVE", true), + "If set to true, objects reachable from thread stacks " + "and registers are not reported as leaks"); + +DEFINE_bool(heap_check_test_pointer_alignment, + EnvToBool("HEAP_CHECK_TEST_POINTER_ALIGNMENT", false), + "Set to true to check if the found leak can be due to " + "use of unaligned pointers"); + +// Alignment at which all pointers in memory are supposed to be located; +// use 1 if any alignment is ok. +// heap_check_test_pointer_alignment flag guides if we try the value of 1. +// The larger it can be, the lesser is the chance of missing real leaks. +static const size_t kPointerSourceAlignment = sizeof(void*); +DEFINE_int32(heap_check_pointer_source_alignment, + EnvToInt("HEAP_CHECK_POINTER_SOURCE_ALIGNMENT", + kPointerSourceAlignment), + "Alignment at which all pointers in memory are supposed to be " + "located. Use 1 if any alignment is ok."); + +// A reasonable default to handle pointers inside of typical class objects: +// Too low and we won't be able to traverse pointers to normally-used +// nested objects and base parts of multiple-inherited objects. +// Too high and it will both slow down leak checking (FindInsideAlloc +// in HaveOnHeapLocked will get slower when there are large on-heap objects) +// and make it probabilistically more likely to miss leaks +// of large-sized objects. +static const int64 kHeapCheckMaxPointerOffset = 1024; +DEFINE_int64(heap_check_max_pointer_offset, + EnvToInt("HEAP_CHECK_MAX_POINTER_OFFSET", + kHeapCheckMaxPointerOffset), + "Largest pointer offset for which we traverse " + "pointers going inside of heap allocated objects. " + "Set to -1 to use the actual largest heap object size."); + +DEFINE_bool(heap_check_run_under_gdb, + EnvToBool("HEAP_CHECK_RUN_UNDER_GDB", false), + "If false, turns off heap-checking library when running under gdb " + "(normally, set to 'true' only when debugging the heap-checker)"); + +DEFINE_int32(heap_check_delay_seconds, 0, + "Number of seconds to delay on-exit heap checking." + " If you set this flag," + " you may also want to set exit_timeout_seconds in order to" + " avoid exit timeouts.\n" + "NOTE: This flag is to be used only to help diagnose issues" + " where it is suspected that the heap checker is reporting" + " false leaks that will disappear if the heap checker delays" + " its checks. Report any such issues to the heap-checker" + " maintainer(s)."); + +//---------------------------------------------------------------------- + +DEFINE_string(heap_profile_pprof, + EnvToString("PPROF_PATH", "pprof"), + "OBSOLETE; not used"); + +DEFINE_string(heap_check_dump_directory, + EnvToString("HEAP_CHECK_DUMP_DIRECTORY", "/tmp"), + "Directory to put heap-checker leak dump information"); + + +//---------------------------------------------------------------------- +// HeapLeakChecker global data +//---------------------------------------------------------------------- + +// Global lock for all the global data of this module. +static SpinLock heap_checker_lock(SpinLock::LINKER_INITIALIZED); + +//---------------------------------------------------------------------- + +// Heap profile prefix for leak checking profiles. +// Gets assigned once when leak checking is turned on, then never modified. +static const string* profile_name_prefix = NULL; + +// Whole-program heap leak checker. +// Gets assigned once when leak checking is turned on, +// then main_heap_checker is never deleted. +static HeapLeakChecker* main_heap_checker = NULL; + +// Whether we will use main_heap_checker to do a check at program exit +// automatically. In any case user can ask for more checks on main_heap_checker +// via GlobalChecker(). +static bool do_main_heap_check = false; + +// The heap profile we use to collect info about the heap. +// This is created in HeapLeakChecker::BeforeConstructorsLocked +// together with setting heap_checker_on (below) to true +// and registering our new/delete malloc hooks; +// similarly all are unset in HeapLeakChecker::TurnItselfOffLocked. +static HeapProfileTable* heap_profile = NULL; + +// If we are doing (or going to do) any kind of heap-checking. +static bool heap_checker_on = false; + +// pid of the process that does whole-program heap leak checking +static pid_t heap_checker_pid = 0; + +// If we did heap profiling during global constructors execution +static bool constructor_heap_profiling = false; + +// RAW_VLOG level we dump key INFO messages at. If you want to turn +// off these messages, set the environment variable PERFTOOLS_VERBOSE=-1. +static const int heap_checker_info_level = 0; + +//---------------------------------------------------------------------- +// HeapLeakChecker's own memory allocator that is +// independent of the normal program allocator. +//---------------------------------------------------------------------- + +// Wrapper of LowLevelAlloc for STL_Allocator and direct use. +// We always access this class under held heap_checker_lock, +// this allows us to in particular protect the period when threads are stopped +// at random spots with TCMalloc_ListAllProcessThreads by heap_checker_lock, +// w/o worrying about the lock in LowLevelAlloc::Arena. +// We rely on the fact that we use an own arena with an own lock here. +class HeapLeakChecker::Allocator { + public: + static void Init() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + RAW_DCHECK(arena_ == NULL, ""); + arena_ = LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena()); + } + static void Shutdown() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + if (!LowLevelAlloc::DeleteArena(arena_) || alloc_count_ != 0) { + RAW_LOG(FATAL, "Internal heap checker leak of %d objects", alloc_count_); + } + } + static int alloc_count() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + return alloc_count_; + } + static void* Allocate(size_t n) { + RAW_DCHECK(arena_ && heap_checker_lock.IsHeld(), ""); + void* p = LowLevelAlloc::AllocWithArena(n, arena_); + if (p) alloc_count_ += 1; + return p; + } + static void Free(void* p) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + if (p) alloc_count_ -= 1; + LowLevelAlloc::Free(p); + } + static void Free(void* p, size_t /* n */) { + Free(p); + } + // destruct, free, and make *p to be NULL + template static void DeleteAndNull(T** p) { + (*p)->~T(); + Free(*p); + *p = NULL; + } + template static void DeleteAndNullIfNot(T** p) { + if (*p != NULL) DeleteAndNull(p); + } + private: + static LowLevelAlloc::Arena* arena_; + static int alloc_count_; +}; + +LowLevelAlloc::Arena* HeapLeakChecker::Allocator::arena_ = NULL; +int HeapLeakChecker::Allocator::alloc_count_ = 0; + +//---------------------------------------------------------------------- +// HeapLeakChecker live object tracking components +//---------------------------------------------------------------------- + +// Cases of live object placement we distinguish +enum ObjectPlacement { + MUST_BE_ON_HEAP, // Must point to a live object of the matching size in the + // heap_profile map of the heap when we get to it + IGNORED_ON_HEAP, // Is a live (ignored) object on heap + MAYBE_LIVE, // Is a piece of writable memory from /proc/self/maps + IN_GLOBAL_DATA, // Is part of global data region of the executable + THREAD_DATA, // Part of a thread stack and a thread descriptor with TLS + THREAD_REGISTERS, // Values in registers of some thread +}; + +// Information about an allocated object +struct AllocObject { + const void* ptr; // the object + uintptr_t size; // its size + ObjectPlacement place; // where ptr points to + + AllocObject(const void* p, size_t s, ObjectPlacement l) + : ptr(p), size(s), place(l) { } +}; + +// All objects (memory ranges) ignored via HeapLeakChecker::IgnoreObject +// Key is the object's address; value is its size. +typedef map, + STL_Allocator, + HeapLeakChecker::Allocator> + > IgnoredObjectsMap; +static IgnoredObjectsMap* ignored_objects = NULL; + +// All objects (memory ranges) that we consider to be the sources of pointers +// to live (not leaked) objects. +// At different times this holds (what can be reached from) global data regions +// and the objects we've been told to ignore. +// For any AllocObject::ptr "live_objects" is supposed to contain at most one +// record at any time. We maintain this by checking with the heap_profile map +// of the heap and removing the live heap objects we've handled from it. +// This vector is maintained as a stack and the frontier of reachable +// live heap objects in our flood traversal of them. +typedef vector + > LiveObjectsStack; +static LiveObjectsStack* live_objects = NULL; + +// A special string type that uses my allocator +typedef basic_string, + STL_Allocator + > HCL_string; + +// A placeholder to fill-in the starting values for live_objects +// for each library so we can keep the library-name association for logging. +typedef map, + STL_Allocator, + HeapLeakChecker::Allocator> + > LibraryLiveObjectsStacks; +static LibraryLiveObjectsStacks* library_live_objects = NULL; + +// Value stored in the map of disabled address ranges; +// its key is the end of the address range. +// We'll ignore allocations with a return address in a disabled range +// if the address occurs at 'max_depth' or less in the stack trace. +struct HeapLeakChecker::RangeValue { + uintptr_t start_address; // the start of the range + int max_depth; // the maximal stack depth to disable at +}; +typedef map, + STL_Allocator, + HeapLeakChecker::Allocator> + > DisabledRangeMap; +// The disabled program counter address ranges for profile dumping +// that are registered with HeapLeakChecker::DisableChecksFromToLocked. +static DisabledRangeMap* disabled_ranges = NULL; + +// Set of stack tops. +// These are used to consider live only appropriate chunks of the memory areas +// that are used for stacks (and maybe thread-specific data as well) +// so that we do not treat pointers from outdated stack frames as live. +typedef set, + STL_Allocator + > StackTopSet; +static StackTopSet* stack_tops = NULL; + +// A map of ranges of code addresses for the system libraries +// that can mmap/mremap/sbrk-allocate memory regions for stacks +// and thread-local storage that we want to consider as live global data. +// Maps from the end address to the start address. +typedef map, + STL_Allocator, + HeapLeakChecker::Allocator> + > GlobalRegionCallerRangeMap; +static GlobalRegionCallerRangeMap* global_region_caller_ranges = NULL; + +// TODO(maxim): make our big data structs into own modules + +// Disabler is implemented by keeping track of a per-thread count +// of active Disabler objects. Any objects allocated while the +// count > 0 are not reported. + +#ifdef HAVE_TLS + +static __thread int thread_disable_counter +// The "inital exec" model is faster than the default TLS model, at +// the cost you can't dlopen this library. But dlopen on heap-checker +// doesn't work anyway -- it must run before main -- so this is a good +// trade-off. +# ifdef HAVE___ATTRIBUTE__ + __attribute__ ((tls_model ("initial-exec"))) +# endif + ; +inline int get_thread_disable_counter() { + return thread_disable_counter; +} +inline void set_thread_disable_counter(int value) { + thread_disable_counter = value; +} + +#else // #ifdef HAVE_TLS + +static pthread_key_t thread_disable_counter_key; +static int main_thread_counter; // storage for use before main() +static bool use_main_thread_counter = true; + +// TODO(csilvers): this is called from NewHook, in the middle of malloc(). +// If perftools_pthread_getspecific calls malloc, that will lead to an +// infinite loop. I don't know how to fix that, so I hope it never happens! +inline int get_thread_disable_counter() { + if (use_main_thread_counter) // means we're running really early + return main_thread_counter; + void* p = perftools_pthread_getspecific(thread_disable_counter_key); + return (intptr_t)p; // kinda evil: store the counter directly in the void* +} + +inline void set_thread_disable_counter(int value) { + if (use_main_thread_counter) { // means we're running really early + main_thread_counter = value; + return; + } + intptr_t pointer_sized_value = value; + // kinda evil: store the counter directly in the void* + void* p = (void*)pointer_sized_value; + // NOTE: this may call malloc, which will call NewHook which will call + // get_thread_disable_counter() which will call pthread_getspecific(). I + // don't know if anything bad can happen if we call getspecific() in the + // middle of a setspecific() call. It seems to work ok in practice... + perftools_pthread_setspecific(thread_disable_counter_key, p); +} + +// The idea here is that this initializer will run pretty late: after +// pthreads have been totally set up. At this point we can call +// pthreads routines, so we set those up. +class InitThreadDisableCounter { + public: + InitThreadDisableCounter() { + perftools_pthread_key_create(&thread_disable_counter_key, NULL); + // Set up the main thread's value, which we have a special variable for. + void* p = (void*)(intptr_t)main_thread_counter; // store the counter directly + perftools_pthread_setspecific(thread_disable_counter_key, p); + use_main_thread_counter = false; + } +}; +InitThreadDisableCounter init_thread_disable_counter; + +#endif // #ifdef HAVE_TLS + +HeapLeakChecker::Disabler::Disabler() { + // It is faster to unconditionally increment the thread-local + // counter than to check whether or not heap-checking is on + // in a thread-safe manner. + int counter = get_thread_disable_counter(); + set_thread_disable_counter(counter + 1); + RAW_VLOG(10, "Increasing thread disable counter to %d", counter + 1); +} + +HeapLeakChecker::Disabler::~Disabler() { + int counter = get_thread_disable_counter(); + RAW_DCHECK(counter > 0, ""); + if (counter > 0) { + set_thread_disable_counter(counter - 1); + RAW_VLOG(10, "Decreasing thread disable counter to %d", counter); + } else { + RAW_VLOG(0, "Thread disable counter underflow : %d", counter); + } +} + +//---------------------------------------------------------------------- + +// The size of the largest heap object allocated so far. +static size_t max_heap_object_size = 0; +// The possible range of addresses that can point +// into one of the elements of heap_objects. +static uintptr_t min_heap_address = uintptr_t(-1LL); +static uintptr_t max_heap_address = 0; + +//---------------------------------------------------------------------- + +// Simple casting helpers for uintptr_t and void*: +template +inline static const void* AsPtr(T addr) { + return reinterpret_cast(addr); +} +inline static uintptr_t AsInt(const void* ptr) { + return reinterpret_cast(ptr); +} + +//---------------------------------------------------------------------- + +// We've seen reports that strstr causes heap-checker crashes in some +// libc's (?): +// http://code.google.com/p/gperftools/issues/detail?id=263 +// It's simple enough to use our own. This is not in time-critical code. +static const char* hc_strstr(const char* s1, const char* s2) { + const size_t len = strlen(s2); + RAW_CHECK(len > 0, "Unexpected empty string passed to strstr()"); + for (const char* p = strchr(s1, *s2); p != NULL; p = strchr(p+1, *s2)) { + if (strncmp(p, s2, len) == 0) { + return p; + } + } + return NULL; +} + +//---------------------------------------------------------------------- + +// Our hooks for MallocHook +static void NewHook(const void* ptr, size_t size) { + if (ptr != NULL) { + const int counter = get_thread_disable_counter(); + const bool ignore = (counter > 0); + RAW_VLOG(16, "Recording Alloc: %p of %zu; %d", ptr, size, + int(counter)); + + // Fetch the caller's stack trace before acquiring heap_checker_lock. + void* stack[HeapProfileTable::kMaxStackDepth]; + int depth = HeapProfileTable::GetCallerStackTrace(0, stack); + + { SpinLockHolder l(&heap_checker_lock); + if (size > max_heap_object_size) max_heap_object_size = size; + uintptr_t addr = AsInt(ptr); + if (addr < min_heap_address) min_heap_address = addr; + addr += size; + if (addr > max_heap_address) max_heap_address = addr; + if (heap_checker_on) { + heap_profile->RecordAlloc(ptr, size, depth, stack); + if (ignore) { + heap_profile->MarkAsIgnored(ptr); + } + } + } + RAW_VLOG(17, "Alloc Recorded: %p of %zu", ptr, size); + } +} + +static void DeleteHook(const void* ptr) { + if (ptr != NULL) { + RAW_VLOG(16, "Recording Free %p", ptr); + { SpinLockHolder l(&heap_checker_lock); + if (heap_checker_on) heap_profile->RecordFree(ptr); + } + RAW_VLOG(17, "Free Recorded: %p", ptr); + } +} + +//---------------------------------------------------------------------- + +enum StackDirection { + GROWS_TOWARDS_HIGH_ADDRESSES, + GROWS_TOWARDS_LOW_ADDRESSES, + UNKNOWN_DIRECTION +}; + +// Determine which way the stack grows: + +static StackDirection ATTRIBUTE_NOINLINE GetStackDirection( + const uintptr_t *const ptr) { + uintptr_t x; + if (&x < ptr) + return GROWS_TOWARDS_LOW_ADDRESSES; + if (ptr < &x) + return GROWS_TOWARDS_HIGH_ADDRESSES; + + RAW_CHECK(0, ""); // Couldn't determine the stack direction. + + return UNKNOWN_DIRECTION; +} + +// Direction of stack growth (will initialize via GetStackDirection()) +static StackDirection stack_direction = UNKNOWN_DIRECTION; + +// This routine is called for every thread stack we know about to register it. +static void RegisterStackLocked(const void* top_ptr) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); + RAW_VLOG(10, "Thread stack at %p", top_ptr); + uintptr_t top = AsInt(top_ptr); + stack_tops->insert(top); // add for later use + + // make sure stack_direction is initialized + if (stack_direction == UNKNOWN_DIRECTION) { + stack_direction = GetStackDirection(&top); + } + + // Find memory region with this stack + MemoryRegionMap::Region region; + if (MemoryRegionMap::FindAndMarkStackRegion(top, ®ion)) { + // Make the proper portion of the stack live: + if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) { + RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes", + top_ptr, region.end_addr - top); + live_objects->push_back(AllocObject(top_ptr, region.end_addr - top, + THREAD_DATA)); + } else { // GROWS_TOWARDS_HIGH_ADDRESSES + RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes", + AsPtr(region.start_addr), + top - region.start_addr); + live_objects->push_back(AllocObject(AsPtr(region.start_addr), + top - region.start_addr, + THREAD_DATA)); + } + // not in MemoryRegionMap, look in library_live_objects: + } else if (FLAGS_heap_check_ignore_global_live) { + for (LibraryLiveObjectsStacks::iterator lib = library_live_objects->begin(); + lib != library_live_objects->end(); ++lib) { + for (LiveObjectsStack::iterator span = lib->second.begin(); + span != lib->second.end(); ++span) { + uintptr_t start = AsInt(span->ptr); + uintptr_t end = start + span->size; + if (start <= top && top < end) { + RAW_VLOG(11, "Stack at %p is inside /proc/self/maps chunk %p..%p", + top_ptr, AsPtr(start), AsPtr(end)); + // Shrink start..end region by chopping away the memory regions in + // MemoryRegionMap that land in it to undo merging of regions + // in /proc/self/maps, so that we correctly identify what portion + // of start..end is actually the stack region. + uintptr_t stack_start = start; + uintptr_t stack_end = end; + // can optimize-away this loop, but it does not run often + RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); + for (MemoryRegionMap::RegionIterator r = + MemoryRegionMap::BeginRegionLocked(); + r != MemoryRegionMap::EndRegionLocked(); ++r) { + if (top < r->start_addr && r->start_addr < stack_end) { + stack_end = r->start_addr; + } + if (stack_start < r->end_addr && r->end_addr <= top) { + stack_start = r->end_addr; + } + } + if (stack_start != start || stack_end != end) { + RAW_VLOG(11, "Stack at %p is actually inside memory chunk %p..%p", + top_ptr, AsPtr(stack_start), AsPtr(stack_end)); + } + // Make the proper portion of the stack live: + if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) { + RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes", + top_ptr, stack_end - top); + live_objects->push_back( + AllocObject(top_ptr, stack_end - top, THREAD_DATA)); + } else { // GROWS_TOWARDS_HIGH_ADDRESSES + RAW_VLOG(11, "Live stack at %p of %" PRIuPTR " bytes", + AsPtr(stack_start), top - stack_start); + live_objects->push_back( + AllocObject(AsPtr(stack_start), top - stack_start, THREAD_DATA)); + } + lib->second.erase(span); // kill the rest of the region + // Put the non-stack part(s) of the region back: + if (stack_start != start) { + lib->second.push_back(AllocObject(AsPtr(start), stack_start - start, + MAYBE_LIVE)); + } + if (stack_end != end) { + lib->second.push_back(AllocObject(AsPtr(stack_end), end - stack_end, + MAYBE_LIVE)); + } + return; + } + } + } + RAW_LOG(ERROR, "Memory region for stack at %p not found. " + "Will likely report false leak positives.", top_ptr); + } +} + +// Iterator for heap allocation map data to make ignored objects "live" +// (i.e., treated as roots for the mark-and-sweep phase) +static void MakeIgnoredObjectsLiveCallbackLocked( + const void* ptr, const HeapProfileTable::AllocInfo& info) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + if (info.ignored) { + live_objects->push_back(AllocObject(ptr, info.object_size, + MUST_BE_ON_HEAP)); + } +} + +// Iterator for heap allocation map data to make objects allocated from +// disabled regions of code to be live. +static void MakeDisabledLiveCallbackLocked( + const void* ptr, const HeapProfileTable::AllocInfo& info) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + bool stack_disable = false; + bool range_disable = false; + for (int depth = 0; depth < info.stack_depth; depth++) { + uintptr_t addr = AsInt(info.call_stack[depth]); + if (disabled_ranges) { + DisabledRangeMap::const_iterator iter + = disabled_ranges->upper_bound(addr); + if (iter != disabled_ranges->end()) { + RAW_DCHECK(iter->first > addr, ""); + if (iter->second.start_address < addr && + iter->second.max_depth > depth) { + range_disable = true; // in range; dropping + break; + } + } + } + } + if (stack_disable || range_disable) { + uintptr_t start_address = AsInt(ptr); + uintptr_t end_address = start_address + info.object_size; + StackTopSet::const_iterator iter + = stack_tops->lower_bound(start_address); + if (iter != stack_tops->end()) { + RAW_DCHECK(*iter >= start_address, ""); + if (*iter < end_address) { + // We do not disable (treat as live) whole allocated regions + // if they are used to hold thread call stacks + // (i.e. when we find a stack inside). + // The reason is that we'll treat as live the currently used + // stack portions anyway (see RegisterStackLocked), + // and the rest of the region where the stack lives can well + // contain outdated stack variables which are not live anymore, + // hence should not be treated as such. + RAW_VLOG(11, "Not %s-disabling %zu bytes at %p" + ": have stack inside: %p", + (stack_disable ? "stack" : "range"), + info.object_size, ptr, AsPtr(*iter)); + return; + } + } + RAW_VLOG(11, "%s-disabling %zu bytes at %p", + (stack_disable ? "Stack" : "Range"), info.object_size, ptr); + live_objects->push_back(AllocObject(ptr, info.object_size, + MUST_BE_ON_HEAP)); + } +} + +static const char kUnnamedProcSelfMapEntry[] = "UNNAMED"; + +// This function takes some fields from a /proc/self/maps line: +// +// start_address start address of a memory region. +// end_address end address of a memory region +// permissions rwx + private/shared bit +// filename filename of the mapped file +// +// If the region is not writeable, then it cannot have any heap +// pointers in it, otherwise we record it as a candidate live region +// to get filtered later. +static void RecordGlobalDataLocked(uintptr_t start_address, + uintptr_t end_address, + const char* permissions, + const char* filename) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + // Ignore non-writeable regions. + if (strchr(permissions, 'w') == NULL) return; + if (filename == NULL || *filename == '\0') { + filename = kUnnamedProcSelfMapEntry; + } + RAW_VLOG(11, "Looking into %s: 0x%" PRIxPTR "..0x%" PRIxPTR, + filename, start_address, end_address); + (*library_live_objects)[filename]. + push_back(AllocObject(AsPtr(start_address), + end_address - start_address, + MAYBE_LIVE)); +} + +// See if 'library' from /proc/self/maps has base name 'library_base' +// i.e. contains it and has '.' or '-' after it. +static bool IsLibraryNamed(const char* library, const char* library_base) { + const char* p = hc_strstr(library, library_base); + size_t sz = strlen(library_base); + return p != NULL && (p[sz] == '.' || p[sz] == '-'); +} + +// static +void HeapLeakChecker::DisableLibraryAllocsLocked(const char* library, + uintptr_t start_address, + uintptr_t end_address) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + int depth = 0; + // TODO(maxim): maybe this should be extended to also use objdump + // and pick the text portion of the library more precisely. + if (IsLibraryNamed(library, "/libpthread") || + // libpthread has a lot of small "system" leaks we don't care about. + // In particular it allocates memory to store data supplied via + // pthread_setspecific (which can be the only pointer to a heap object). + IsLibraryNamed(library, "/libdl") || + // library loaders leak some "system" heap that we don't care about + IsLibraryNamed(library, "/libcrypto") || + // Sometimes libcrypto of OpenSSH is compiled with -fomit-frame-pointer + // (any library can be, of course, but this one often is because speed + // is so important for making crypto usable). We ignore all its + // allocations because we can't see the call stacks. We'd prefer + // to ignore allocations done in files/symbols that match + // "default_malloc_ex|default_realloc_ex" + // but that doesn't work when the end-result binary is stripped. + IsLibraryNamed(library, "/libjvm") || + // JVM has a lot of leaks we don't care about. + IsLibraryNamed(library, "/libzip") + // The JVM leaks java.util.zip.Inflater after loading classes. + ) { + depth = 1; // only disable allocation calls directly from the library code + } else if (IsLibraryNamed(library, "/ld") + // library loader leaks some "system" heap + // (e.g. thread-local storage) that we don't care about + ) { + depth = 2; // disable allocation calls directly from the library code + // and at depth 2 from it. + // We need depth 2 here solely because of a libc bug that + // forces us to jump through __memalign_hook and MemalignOverride hoops + // in tcmalloc.cc. + // Those buggy __libc_memalign() calls are in ld-linux.so and happen for + // thread-local storage allocations that we want to ignore here. + // We go with the depth-2 hack as a workaround for this libc bug: + // otherwise we'd need to extend MallocHook interface + // so that correct stack depth adjustment can be propagated from + // the exceptional case of MemalignOverride. + // Using depth 2 here should not mask real leaks because ld-linux.so + // does not call user code. + } + if (depth) { + RAW_VLOG(10, "Disabling allocations from %s at depth %d:", library, depth); + DisableChecksFromToLocked(AsPtr(start_address), AsPtr(end_address), depth); + if (IsLibraryNamed(library, "/libpthread") || + IsLibraryNamed(library, "/libdl") || + IsLibraryNamed(library, "/ld")) { + RAW_VLOG(10, "Global memory regions made by %s will be live data", + library); + if (global_region_caller_ranges == NULL) { + global_region_caller_ranges = + new(Allocator::Allocate(sizeof(GlobalRegionCallerRangeMap))) + GlobalRegionCallerRangeMap; + } + global_region_caller_ranges + ->insert(make_pair(end_address, start_address)); + } + } +} + +// static +HeapLeakChecker::ProcMapsResult HeapLeakChecker::UseProcMapsLocked( + ProcMapsTask proc_maps_task) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + // Need to provide own scratch memory to ProcMapsIterator: + ProcMapsIterator::Buffer buffer; + ProcMapsIterator it(0, &buffer); + if (!it.Valid()) { + int errsv = errno; + RAW_LOG(ERROR, "Could not open /proc/self/maps: errno=%d. " + "Libraries will not be handled correctly.", errsv); + return CANT_OPEN_PROC_MAPS; + } + uint64 start_address, end_address, file_offset; + int64 inode; + char *permissions, *filename; + bool saw_shared_lib = false; + bool saw_nonzero_inode = false; + bool saw_shared_lib_with_nonzero_inode = false; + while (it.Next(&start_address, &end_address, &permissions, + &file_offset, &inode, &filename)) { + if (start_address >= end_address) { + // Warn if a line we can be interested in is ill-formed: + if (inode != 0) { + RAW_LOG(ERROR, "Errors reading /proc/self/maps. " + "Some global memory regions will not " + "be handled correctly."); + } + // Silently skip other ill-formed lines: some are possible + // probably due to the interplay of how /proc/self/maps is updated + // while we read it in chunks in ProcMapsIterator and + // do things in this loop. + continue; + } + // Determine if any shared libraries are present (this is the same + // list of extensions as is found in pprof). We want to ignore + // 'fake' libraries with inode 0 when determining. However, some + // systems don't share inodes via /proc, so we turn off this check + // if we don't see any evidence that we're getting inode info. + if (inode != 0) { + saw_nonzero_inode = true; + } + if ((hc_strstr(filename, "lib") && hc_strstr(filename, ".so")) || + hc_strstr(filename, ".dll") || + // not all .dylib filenames start with lib. .dylib is big enough + // that we are unlikely to get false matches just checking that. + hc_strstr(filename, ".dylib") || hc_strstr(filename, ".bundle")) { + saw_shared_lib = true; + if (inode != 0) { + saw_shared_lib_with_nonzero_inode = true; + } + } + + switch (proc_maps_task) { + case DISABLE_LIBRARY_ALLOCS: + // All lines starting like + // "401dc000-4030f000 r??p 00132000 03:01 13991972 lib/bin" + // identify a data and code sections of a shared library or our binary + if (inode != 0 && strncmp(permissions, "r-xp", 4) == 0) { + DisableLibraryAllocsLocked(filename, start_address, end_address); + } + break; + case RECORD_GLOBAL_DATA: + RecordGlobalDataLocked(start_address, end_address, + permissions, filename); + break; + default: + RAW_CHECK(0, ""); + } + } + // If /proc/self/maps is reporting inodes properly (we saw a + // non-zero inode), then we only say we saw a shared lib if we saw a + // 'real' one, with a non-zero inode. + if (saw_nonzero_inode) { + saw_shared_lib = saw_shared_lib_with_nonzero_inode; + } + if (!saw_shared_lib) { + RAW_LOG(ERROR, "No shared libs detected. Will likely report false leak " + "positives for statically linked executables."); + return NO_SHARED_LIBS_IN_PROC_MAPS; + } + return PROC_MAPS_USED; +} + +// Total number and size of live objects dropped from the profile; +// (re)initialized in IgnoreAllLiveObjectsLocked. +static int64 live_objects_total; +static int64 live_bytes_total; + +// pid of the thread that is doing the current leak check +// (protected by our lock; IgnoreAllLiveObjectsLocked sets it) +static pid_t self_thread_pid = 0; + +// Status of our thread listing callback execution +// (protected by our lock; used from within IgnoreAllLiveObjectsLocked) +static enum { + CALLBACK_NOT_STARTED, + CALLBACK_STARTED, + CALLBACK_COMPLETED, +} thread_listing_status = CALLBACK_NOT_STARTED; + +// Ideally to avoid deadlocks this function should not result in any libc +// or other function calls that might need to lock a mutex: +// It is called when all threads of a process are stopped +// at arbitrary points thus potentially holding those locks. +// +// In practice we are calling some simple i/o and sprintf-type library functions +// for logging messages, but use only our own LowLevelAlloc::Arena allocator. +// +// This is known to be buggy: the library i/o function calls are able to cause +// deadlocks when they request a lock that a stopped thread happens to hold. +// This issue as far as we know have so far not resulted in any deadlocks +// in practice, so for now we are taking our chance that the deadlocks +// have insignificant frequency. +// +// If such deadlocks become a problem we should make the i/o calls +// into appropriately direct system calls (or eliminate them), +// in particular write() is not safe and vsnprintf() is potentially dangerous +// due to reliance on locale functions (these are called through RAW_LOG +// and in other ways). +// + +#if defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER) +# if (defined(__i386__) || defined(__x86_64)) +# define THREAD_REGS i386_regs +# elif defined(__PPC__) +# define THREAD_REGS ppc_regs +# endif +#endif + +/*static*/ int HeapLeakChecker::IgnoreLiveThreadsLocked(void* parameter, + int num_threads, + pid_t* thread_pids, + va_list /*ap*/) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + thread_listing_status = CALLBACK_STARTED; + RAW_VLOG(11, "Found %d threads (from pid %d)", num_threads, getpid()); + + if (FLAGS_heap_check_ignore_global_live) { + UseProcMapsLocked(RECORD_GLOBAL_DATA); + } + + // We put the registers from other threads here + // to make pointers stored in them live. + vector > thread_registers; + + int failures = 0; + for (int i = 0; i < num_threads; ++i) { + // the leak checking thread itself is handled + // specially via self_thread_stack, not here: + if (thread_pids[i] == self_thread_pid) continue; + RAW_VLOG(11, "Handling thread with pid %d", thread_pids[i]); +#ifdef THREAD_REGS + THREAD_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 + // because this is called from TCMalloc_ListAllProcessThreads + // when all but this thread are suspended. + if (sys_ptrace(PTRACE_GETREGS, thread_pids[i], NULL, &thread_regs) == 0) { + // Need to use SP to get all the data from the very last stack frame: + COMPILE_ASSERT(sizeof(thread_regs.SP) == sizeof(void*), + SP_register_does_not_look_like_a_pointer); + RegisterStackLocked(reinterpret_cast(thread_regs.SP)); + // Make registers live (just in case PTRACE_ATTACH resulted in some + // register pointers still being in the registers and not on the stack): + for (void** p = reinterpret_cast(&thread_regs); + p < reinterpret_cast(&thread_regs + 1); ++p) { + RAW_VLOG(12, "Thread register %p", *p); + thread_registers.push_back(*p); + } + } else { + failures += 1; + } +#else + failures += 1; +#endif + } + // Use all the collected thread (stack) liveness sources: + IgnoreLiveObjectsLocked("threads stack data", ""); + if (thread_registers.size()) { + // Make thread registers be live heap data sources. + // we rely here on the fact that vector is in one memory chunk: + RAW_VLOG(11, "Live registers at %p of %zu bytes", + &thread_registers[0], thread_registers.size() * sizeof(void*)); + live_objects->push_back(AllocObject(&thread_registers[0], + thread_registers.size() * sizeof(void*), + THREAD_REGISTERS)); + IgnoreLiveObjectsLocked("threads register data", ""); + } + // Do all other liveness walking while all threads are stopped: + IgnoreNonThreadLiveObjectsLocked(); + // Can now resume the threads: + TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids); + thread_listing_status = CALLBACK_COMPLETED; + return failures; +} + +// Stack top of the thread that is doing the current leak check +// (protected by our lock; IgnoreAllLiveObjectsLocked sets it) +static const void* self_thread_stack_top; + +// static +void HeapLeakChecker::IgnoreNonThreadLiveObjectsLocked() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); + RAW_VLOG(11, "Handling self thread with pid %d", self_thread_pid); + // Register our own stack: + + // Important that all stack ranges (including the one here) + // are known before we start looking at them + // in MakeDisabledLiveCallbackLocked: + RegisterStackLocked(self_thread_stack_top); + IgnoreLiveObjectsLocked("stack data", ""); + + // Make objects we were told to ignore live: + if (ignored_objects) { + for (IgnoredObjectsMap::const_iterator object = ignored_objects->begin(); + object != ignored_objects->end(); ++object) { + const void* ptr = AsPtr(object->first); + RAW_VLOG(11, "Ignored live object at %p of %zu bytes", + ptr, object->second); + live_objects-> + push_back(AllocObject(ptr, object->second, MUST_BE_ON_HEAP)); + // we do this liveness check for ignored_objects before doing any + // live heap walking to make sure it does not fail needlessly: + size_t object_size; + if (!(heap_profile->FindAlloc(ptr, &object_size) && + object->second == object_size)) { + RAW_LOG(FATAL, "Object at %p of %zu bytes from an" + " IgnoreObject() has disappeared", ptr, object->second); + } + } + IgnoreLiveObjectsLocked("ignored objects", ""); + } + + // Treat objects that were allocated when a Disabler was live as + // roots. I.e., if X was allocated while a Disabler was active, + // and Y is reachable from X, arrange that neither X nor Y are + // treated as leaks. + heap_profile->IterateAllocs(MakeIgnoredObjectsLiveCallbackLocked); + IgnoreLiveObjectsLocked("disabled objects", ""); + + // Make code-address-disabled objects live and ignored: + // This in particular makes all thread-specific data live + // because the basic data structure to hold pointers to thread-specific data + // is allocated from libpthreads and we have range-disabled that + // library code with UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS); + // so now we declare all thread-specific data reachable from there as live. + heap_profile->IterateAllocs(MakeDisabledLiveCallbackLocked); + IgnoreLiveObjectsLocked("disabled code", ""); + + // Actually make global data live: + if (FLAGS_heap_check_ignore_global_live) { + bool have_null_region_callers = false; + for (LibraryLiveObjectsStacks::iterator l = library_live_objects->begin(); + l != library_live_objects->end(); ++l) { + RAW_CHECK(live_objects->empty(), ""); + // Process library_live_objects in l->second + // filtering them by MemoryRegionMap: + // It's safe to iterate over MemoryRegionMap + // w/o locks here as we are inside MemoryRegionMap::Lock(): + RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); + // The only change to MemoryRegionMap possible in this loop + // is region addition as a result of allocating more memory + // for live_objects. This won't invalidate the RegionIterator + // or the intent of the loop. + // --see the comment by MemoryRegionMap::BeginRegionLocked(). + for (MemoryRegionMap::RegionIterator region = + MemoryRegionMap::BeginRegionLocked(); + region != MemoryRegionMap::EndRegionLocked(); ++region) { + // "region" from MemoryRegionMap is to be subtracted from + // (tentatively live) regions in l->second + // if it has a stack inside or it was allocated by + // a non-special caller (not one covered by a range + // in global_region_caller_ranges). + // This will in particular exclude all memory chunks used + // by the heap itself as well as what's been allocated with + // any allocator on top of mmap. + bool subtract = true; + if (!region->is_stack && global_region_caller_ranges) { + if (region->caller() == static_cast(NULL)) { + have_null_region_callers = true; + } else { + GlobalRegionCallerRangeMap::const_iterator iter + = global_region_caller_ranges->upper_bound(region->caller()); + if (iter != global_region_caller_ranges->end()) { + RAW_DCHECK(iter->first > region->caller(), ""); + if (iter->second < region->caller()) { // in special region + subtract = false; + } + } + } + } + if (subtract) { + // The loop puts the result of filtering l->second into live_objects: + for (LiveObjectsStack::const_iterator i = l->second.begin(); + i != l->second.end(); ++i) { + // subtract *region from *i + uintptr_t start = AsInt(i->ptr); + uintptr_t end = start + i->size; + if (region->start_addr <= start && end <= region->end_addr) { + // full deletion due to subsumption + } else if (start < region->start_addr && + region->end_addr < end) { // cutting-out split + live_objects->push_back(AllocObject(i->ptr, + region->start_addr - start, + IN_GLOBAL_DATA)); + live_objects->push_back(AllocObject(AsPtr(region->end_addr), + end - region->end_addr, + IN_GLOBAL_DATA)); + } else if (region->end_addr > start && + region->start_addr <= start) { // cut from start + live_objects->push_back(AllocObject(AsPtr(region->end_addr), + end - region->end_addr, + IN_GLOBAL_DATA)); + } else if (region->start_addr > start && + region->start_addr < end) { // cut from end + live_objects->push_back(AllocObject(i->ptr, + region->start_addr - start, + IN_GLOBAL_DATA)); + } else { // pass: no intersection + live_objects->push_back(AllocObject(i->ptr, i->size, + IN_GLOBAL_DATA)); + } + } + // Move live_objects back into l->second + // for filtering by the next region. + live_objects->swap(l->second); + live_objects->clear(); + } + } + // Now get and use live_objects from the final version of l->second: + if (VLOG_IS_ON(11)) { + for (LiveObjectsStack::const_iterator i = l->second.begin(); + i != l->second.end(); ++i) { + RAW_VLOG(11, "Library live region at %p of %" PRIuPTR " bytes", + i->ptr, i->size); + } + } + live_objects->swap(l->second); + IgnoreLiveObjectsLocked("in globals of\n ", l->first.c_str()); + } + if (have_null_region_callers) { + RAW_LOG(ERROR, "Have memory regions w/o callers: " + "might report false leaks"); + } + Allocator::DeleteAndNull(&library_live_objects); + } +} + +// Callback for TCMalloc_ListAllProcessThreads in IgnoreAllLiveObjectsLocked below +// to test/verify that we have just the one main thread, in which case +// we can do everything in that main thread, +// so that CPU profiler can collect all its samples. +// Returns the number of threads in the process. +static int IsOneThread(void* parameter, int num_threads, + pid_t* thread_pids, va_list ap) { + if (num_threads != 1) { + RAW_LOG(WARNING, "Have threads: Won't CPU-profile the bulk of leak " + "checking work happening in IgnoreLiveThreadsLocked!"); + } + TCMalloc_ResumeAllProcessThreads(num_threads, thread_pids); + return num_threads; +} + +// Dummy for IgnoreAllLiveObjectsLocked below. +// Making it global helps with compiler warnings. +static va_list dummy_ap; + +// static +void HeapLeakChecker::IgnoreAllLiveObjectsLocked(const void* self_stack_top) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + RAW_CHECK(live_objects == NULL, ""); + live_objects = new(Allocator::Allocate(sizeof(LiveObjectsStack))) + LiveObjectsStack; + stack_tops = new(Allocator::Allocate(sizeof(StackTopSet))) StackTopSet; + // reset the counts + live_objects_total = 0; + live_bytes_total = 0; + // Reduce max_heap_object_size to FLAGS_heap_check_max_pointer_offset + // for the time of leak check. + // FLAGS_heap_check_max_pointer_offset caps max_heap_object_size + // to manage reasonably low chances of random bytes + // appearing to be pointing into large actually leaked heap objects. + const size_t old_max_heap_object_size = max_heap_object_size; + max_heap_object_size = ( + FLAGS_heap_check_max_pointer_offset != -1 + ? min(size_t(FLAGS_heap_check_max_pointer_offset), max_heap_object_size) + : max_heap_object_size); + // Record global data as live: + if (FLAGS_heap_check_ignore_global_live) { + library_live_objects = + new(Allocator::Allocate(sizeof(LibraryLiveObjectsStacks))) + LibraryLiveObjectsStacks; + } + // Ignore all thread stacks: + thread_listing_status = CALLBACK_NOT_STARTED; + bool need_to_ignore_non_thread_objects = true; + self_thread_pid = getpid(); + self_thread_stack_top = self_stack_top; + if (FLAGS_heap_check_ignore_thread_live) { + // In case we are doing CPU profiling we'd like to do all the work + // in the main thread, not in the special thread created by + // TCMalloc_ListAllProcessThreads, so that CPU profiler can + // collect all its samples. The machinery of + // TCMalloc_ListAllProcessThreads conflicts with the CPU profiler + // by also relying on signals and ::sigaction. We can do this + // (run everything in the main thread) safely only if there's just + // the main thread itself in our process. This variable reflects + // these two conditions: + bool want_and_can_run_in_main_thread = + ProfilingIsEnabledForAllThreads() && + TCMalloc_ListAllProcessThreads(NULL, IsOneThread) == 1; + // When the normal path of TCMalloc_ListAllProcessThreads below is taken, + // we fully suspend the threads right here before any liveness checking + // and keep them suspended for the whole time of liveness checking + // inside of the IgnoreLiveThreadsLocked callback. + // (The threads can't (de)allocate due to lock on the delete hook but + // if not suspended they could still mess with the pointer + // graph while we walk it). + int r = want_and_can_run_in_main_thread + ? IgnoreLiveThreadsLocked(NULL, 1, &self_thread_pid, dummy_ap) + : TCMalloc_ListAllProcessThreads(NULL, IgnoreLiveThreadsLocked); + need_to_ignore_non_thread_objects = r < 0; + if (r < 0) { + RAW_LOG(WARNING, "Thread finding failed with %d errno=%d", r, errno); + if (thread_listing_status == CALLBACK_COMPLETED) { + RAW_LOG(INFO, "Thread finding callback " + "finished ok; hopefully everything is fine"); + need_to_ignore_non_thread_objects = false; + } else if (thread_listing_status == CALLBACK_STARTED) { + RAW_LOG(FATAL, "Thread finding callback was " + "interrupted or crashed; can't fix this"); + } else { // CALLBACK_NOT_STARTED + RAW_LOG(ERROR, "Could not find thread stacks. " + "Will likely report false leak positives."); + } + } else if (r != 0) { + RAW_LOG(ERROR, "Thread stacks not found for %d threads. " + "Will likely report false leak positives.", r); + } else { + RAW_VLOG(11, "Thread stacks appear to be found for all threads"); + } + } else { + RAW_LOG(WARNING, "Not looking for thread stacks; " + "objects reachable only from there " + "will be reported as leaks"); + } + // Do all other live data ignoring here if we did not do it + // within thread listing callback with all threads stopped. + if (need_to_ignore_non_thread_objects) { + if (FLAGS_heap_check_ignore_global_live) { + UseProcMapsLocked(RECORD_GLOBAL_DATA); + } + IgnoreNonThreadLiveObjectsLocked(); + } + if (live_objects_total) { + RAW_VLOG(10, "Ignoring %" PRId64 " reachable objects of %" PRId64 " bytes", + live_objects_total, live_bytes_total); + } + // Free these: we made them here and heap_profile never saw them + Allocator::DeleteAndNull(&live_objects); + Allocator::DeleteAndNull(&stack_tops); + max_heap_object_size = old_max_heap_object_size; // reset this var +} + +// Alignment at which we should consider pointer positions +// in IgnoreLiveObjectsLocked. Will normally use the value of +// FLAGS_heap_check_pointer_source_alignment. +static size_t pointer_source_alignment = kPointerSourceAlignment; +// Global lock for HeapLeakChecker::DoNoLeaks +// to protect pointer_source_alignment. +static SpinLock alignment_checker_lock(SpinLock::LINKER_INITIALIZED); + +// This function changes the live bits in the heap_profile-table's state: +// we only record the live objects to be skipped. +// +// When checking if a byte sequence points to a heap object we use +// HeapProfileTable::FindInsideAlloc to handle both pointers to +// the start and inside of heap-allocated objects. +// The "inside" case needs to be checked to support +// at least the following relatively common cases: +// - C++ arrays allocated with new FooClass[size] for classes +// with destructors have their size recorded in a sizeof(int) field +// before the place normal pointers point to. +// - basic_string<>-s for e.g. the C++ library of gcc 3.4 +// have the meta-info in basic_string<...>::_Rep recorded +// before the place normal pointers point to. +// - Multiple-inherited objects have their pointers when cast to +// different base classes pointing inside of the actually +// allocated object. +// - Sometimes reachability pointers point to member objects of heap objects, +// and then those member objects point to the full heap object. +// - Third party UnicodeString: it stores a 32-bit refcount +// (in both 32-bit and 64-bit binaries) as the first uint32 +// in the allocated memory and a normal pointer points at +// the second uint32 behind the refcount. +// By finding these additional objects here +// we slightly increase the chance to mistake random memory bytes +// for a pointer and miss a leak in a particular run of a binary. +// +/*static*/ void HeapLeakChecker::IgnoreLiveObjectsLocked(const char* name, + const char* name2) { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + int64 live_object_count = 0; + int64 live_byte_count = 0; + while (!live_objects->empty()) { + const char* object = + reinterpret_cast(live_objects->back().ptr); + size_t size = live_objects->back().size; + const ObjectPlacement place = live_objects->back().place; + live_objects->pop_back(); + if (place == MUST_BE_ON_HEAP && heap_profile->MarkAsLive(object)) { + live_object_count += 1; + live_byte_count += size; + } + RAW_VLOG(13, "Looking for heap pointers in %p of %zu bytes", + object, size); + const char* const whole_object = object; + size_t const whole_size = size; + // Try interpretting any byte sequence in object,size as a heap pointer: + const size_t remainder = AsInt(object) % pointer_source_alignment; + if (remainder) { + object += pointer_source_alignment - remainder; + if (size >= pointer_source_alignment - remainder) { + size -= pointer_source_alignment - remainder; + } else { + size = 0; + } + } + if (size < sizeof(void*)) continue; + +#ifdef NO_FRAME_POINTER + // Frame pointer omission requires us to use libunwind, which uses direct + // mmap and munmap system calls, and that needs special handling. + if (name2 == kUnnamedProcSelfMapEntry) { + static const uintptr_t page_mask = ~(getpagesize() - 1); + const uintptr_t addr = reinterpret_cast(object); + if ((addr & page_mask) == 0 && (size & page_mask) == 0) { + // This is an object we slurped from /proc/self/maps. + // It may or may not be readable at this point. + // + // In case all the above conditions made a mistake, and the object is + // not related to libunwind, we also verify that it's not readable + // before ignoring it. + if (msync(const_cast(object), size, MS_ASYNC) != 0) { + // Skip unreadable object, so we don't crash trying to sweep it. + RAW_VLOG(0, "Ignoring inaccessible object [%p, %p) " + "(msync error %d (%s))", + object, object + size, errno, strerror(errno)); + continue; + } + } + } +#endif + + const char* const max_object = object + size - sizeof(void*); + while (object <= max_object) { + // potentially unaligned load: + const uintptr_t addr = *reinterpret_cast(object); + // Do fast check before the more expensive HaveOnHeapLocked lookup: + // this code runs for all memory words that are potentially pointers: + const bool can_be_on_heap = + // Order tests by the likelyhood of the test failing in 64/32 bit modes. + // Yes, this matters: we either lose 5..6% speed in 32 bit mode + // (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode. + // After the alignment test got dropped the above performance figures + // must have changed; might need to revisit this. +#if defined(__x86_64__) + addr <= max_heap_address && // <= is for 0-sized object with max addr + min_heap_address <= addr; +#else + min_heap_address <= addr && + addr <= max_heap_address; // <= is for 0-sized object with max addr +#endif + if (can_be_on_heap) { + const void* ptr = reinterpret_cast(addr); + // Too expensive (inner loop): manually uncomment when debugging: + // RAW_VLOG(17, "Trying pointer to %p at %p", ptr, object); + size_t object_size; + if (HaveOnHeapLocked(&ptr, &object_size) && + heap_profile->MarkAsLive(ptr)) { + // We take the (hopefully low) risk here of encountering by accident + // a byte sequence in memory that matches an address of + // a heap object which is in fact leaked. + // I.e. in very rare and probably not repeatable/lasting cases + // we might miss some real heap memory leaks. + RAW_VLOG(14, "Found pointer to %p of %zu bytes at %p " + "inside %p of size %zu", + ptr, object_size, object, whole_object, whole_size); + if (VLOG_IS_ON(15)) { + // log call stacks to help debug how come something is not a leak + HeapProfileTable::AllocInfo alloc; + if (!heap_profile->FindAllocDetails(ptr, &alloc)) { + RAW_LOG(FATAL, "FindAllocDetails failed on ptr %p", ptr); + } + RAW_LOG(INFO, "New live %p object's alloc stack:", ptr); + for (int i = 0; i < alloc.stack_depth; ++i) { + RAW_LOG(INFO, " @ %p", alloc.call_stack[i]); + } + } + live_object_count += 1; + live_byte_count += object_size; + live_objects->push_back(AllocObject(ptr, object_size, + IGNORED_ON_HEAP)); + } + } + object += pointer_source_alignment; + } + } + live_objects_total += live_object_count; + live_bytes_total += live_byte_count; + if (live_object_count) { + RAW_VLOG(10, "Removed %" PRId64 " live heap objects of %" PRId64 " bytes: %s%s", + live_object_count, live_byte_count, name, name2); + } +} + +//---------------------------------------------------------------------- +// HeapLeakChecker leak check disabling components +//---------------------------------------------------------------------- + +// static +void HeapLeakChecker::DisableChecksIn(const char* pattern) { + RAW_LOG(WARNING, "DisableChecksIn(%s) is ignored", pattern); +} + +// static +void HeapLeakChecker::DoIgnoreObject(const void* ptr) { + SpinLockHolder l(&heap_checker_lock); + if (!heap_checker_on) return; + size_t object_size; + if (!HaveOnHeapLocked(&ptr, &object_size)) { + RAW_LOG(ERROR, "No live heap object at %p to ignore", ptr); + } else { + RAW_VLOG(10, "Going to ignore live object at %p of %zu bytes", + ptr, object_size); + if (ignored_objects == NULL) { + ignored_objects = new(Allocator::Allocate(sizeof(IgnoredObjectsMap))) + IgnoredObjectsMap; + } + if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) { + RAW_LOG(WARNING, "Object at %p is already being ignored", ptr); + } + } +} + +// static +void HeapLeakChecker::UnIgnoreObject(const void* ptr) { + SpinLockHolder l(&heap_checker_lock); + if (!heap_checker_on) return; + size_t object_size; + if (!HaveOnHeapLocked(&ptr, &object_size)) { + RAW_LOG(FATAL, "No live heap object at %p to un-ignore", ptr); + } else { + bool found = false; + if (ignored_objects) { + IgnoredObjectsMap::iterator object = ignored_objects->find(AsInt(ptr)); + if (object != ignored_objects->end() && object_size == object->second) { + ignored_objects->erase(object); + found = true; + RAW_VLOG(10, "Now not going to ignore live object " + "at %p of %zu bytes", ptr, object_size); + } + } + if (!found) RAW_LOG(FATAL, "Object at %p has not been ignored", ptr); + } +} + +//---------------------------------------------------------------------- +// HeapLeakChecker non-static functions +//---------------------------------------------------------------------- + +char* HeapLeakChecker::MakeProfileNameLocked() { + RAW_DCHECK(lock_->IsHeld(), ""); + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + const int len = profile_name_prefix->size() + strlen(name_) + 5 + + strlen(HeapProfileTable::kFileExt) + 1; + char* file_name = reinterpret_cast(Allocator::Allocate(len)); + snprintf(file_name, len, "%s.%s-end%s", + profile_name_prefix->c_str(), name_, + HeapProfileTable::kFileExt); + return file_name; +} + +void HeapLeakChecker::Create(const char *name, bool make_start_snapshot) { + SpinLockHolder l(lock_); + name_ = NULL; // checker is inactive + start_snapshot_ = NULL; + has_checked_ = false; + inuse_bytes_increase_ = 0; + inuse_allocs_increase_ = 0; + keep_profiles_ = false; + char* n = new char[strlen(name) + 1]; // do this before we lock + IgnoreObject(n); // otherwise it might be treated as live due to our stack + { // Heap activity in other threads is paused for this whole scope. + SpinLockHolder al(&alignment_checker_lock); + SpinLockHolder hl(&heap_checker_lock); + MemoryRegionMap::LockHolder ml; + if (heap_checker_on && profile_name_prefix != NULL) { + RAW_DCHECK(strchr(name, '/') == NULL, "must be a simple name"); + memcpy(n, name, strlen(name) + 1); + name_ = n; // checker is active + if (make_start_snapshot) { + start_snapshot_ = heap_profile->TakeSnapshot(); + } + + const HeapProfileTable::Stats& t = heap_profile->total(); + const size_t start_inuse_bytes = t.alloc_size - t.free_size; + const size_t start_inuse_allocs = t.allocs - t.frees; + RAW_VLOG(10, "Start check \"%s\" profile: %zu bytes " + "in %zu objects", + name_, start_inuse_bytes, start_inuse_allocs); + } else { + RAW_LOG(WARNING, "Heap checker is not active, " + "hence checker \"%s\" will do nothing!", name); + RAW_LOG(WARNING, "To activate set the HEAPCHECK environment variable.\n"); + } + } + if (name_ == NULL) { + UnIgnoreObject(n); + delete[] n; // must be done after we unlock + } +} + +HeapLeakChecker::HeapLeakChecker(const char *name) : lock_(new SpinLock) { + RAW_DCHECK(strcmp(name, "_main_") != 0, "_main_ is reserved"); + Create(name, true/*create start_snapshot_*/); +} + +HeapLeakChecker::HeapLeakChecker() : lock_(new SpinLock) { + if (FLAGS_heap_check_before_constructors) { + // We want to check for leaks of objects allocated during global + // constructors (i.e., objects allocated already). So we do not + // create a baseline snapshot and hence check for leaks of objects + // that may have already been created. + Create("_main_", false); + } else { + // We want to ignore leaks of objects allocated during global + // constructors (i.e., objects allocated already). So we snapshot + // the current heap contents and use them as a baseline that is + // not reported by the leak checker. + Create("_main_", true); + } +} + +ssize_t HeapLeakChecker::BytesLeaked() const { + SpinLockHolder l(lock_); + if (!has_checked_) { + RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call"); + } + return inuse_bytes_increase_; +} + +ssize_t HeapLeakChecker::ObjectsLeaked() const { + SpinLockHolder l(lock_); + if (!has_checked_) { + RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call"); + } + return inuse_allocs_increase_; +} + +// Save pid of main thread for using in naming dump files +static int32 main_thread_pid = getpid(); +#ifdef HAVE_PROGRAM_INVOCATION_NAME +#ifdef __UCLIBC__ +extern const char* program_invocation_name; +extern const char* program_invocation_short_name; +#else +extern char* program_invocation_name; +extern char* program_invocation_short_name; +#endif +static const char* invocation_name() { return program_invocation_short_name; } +static string invocation_path() { return program_invocation_name; } +#else +static const char* invocation_name() { return ""; } +static string invocation_path() { return ""; } +#endif + +// Prints commands that users can run to get more information +// about the reported leaks. +static void SuggestPprofCommand(const char* pprof_file_arg) { + // Extra help information to print for the user when the test is + // being run in a way where the straightforward pprof command will + // not suffice. + string extra_help; + + // Common header info to print for remote runs + const string remote_header = + "This program is being executed remotely and therefore the pprof\n" + "command printed above will not work. Either run this program\n" + "locally, or adjust the pprof command as follows to allow it to\n" + "work on your local machine:\n"; + + // Extra command for fetching remote data + string fetch_cmd; + + RAW_LOG(WARNING, + "\n\n" + "If the preceding stack traces are not enough to find " + "the leaks, try running THIS shell command:\n\n" + "%s%s %s \"%s\" --inuse_objects --lines --heapcheck " + " --edgefraction=1e-10 --nodefraction=1e-10 --gv\n" + "\n" + "%s" + "If you are still puzzled about why the leaks are " + "there, try rerunning this program with " + "HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with " + "HEAP_CHECK_MAX_POINTER_OFFSET=-1\n" + "If the leak report occurs in a small fraction of runs, " + "try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB " + "or with TCMALLOC_RECLAIM_MEMORY=false, " // only works for debugalloc + "it might help find leaks more repeatably\n", + fetch_cmd.c_str(), + "pprof", // works as long as pprof is on your path + invocation_path().c_str(), + pprof_file_arg, + extra_help.c_str() + ); +} + +bool HeapLeakChecker::DoNoLeaks(ShouldSymbolize should_symbolize) { + SpinLockHolder l(lock_); + // The locking also helps us keep the messages + // for the two checks close together. + SpinLockHolder al(&alignment_checker_lock); + + // thread-safe: protected by alignment_checker_lock + static bool have_disabled_hooks_for_symbolize = false; + // Once we've checked for leaks and symbolized the results once, it's + // not safe to do it again. This is because in order to symbolize + // safely, we had to disable all the malloc hooks here, so we no + // longer can be confident we've collected all the data we need. + if (have_disabled_hooks_for_symbolize) { + RAW_LOG(FATAL, "Must not call heap leak checker manually after " + " program-exit's automatic check."); + } + + HeapProfileTable::Snapshot* leaks = NULL; + char* pprof_file = NULL; + + { + // Heap activity in other threads is paused during this function + // (i.e. until we got all profile difference info). + SpinLockHolder hl(&heap_checker_lock); + if (heap_checker_on == false) { + if (name_ != NULL) { // leak checking enabled when created the checker + RAW_LOG(WARNING, "Heap leak checker got turned off after checker " + "\"%s\" has been created, no leak check is being done for it!", + name_); + } + return true; + } + + // Update global_region_caller_ranges. They may need to change since + // e.g. initialization because shared libraries might have been loaded or + // unloaded. + Allocator::DeleteAndNullIfNot(&global_region_caller_ranges); + ProcMapsResult pm_result = UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS); + RAW_CHECK(pm_result == PROC_MAPS_USED, ""); + + // Keep track of number of internally allocated objects so we + // can detect leaks in the heap-leak-checket itself + const int initial_allocs = Allocator::alloc_count(); + + if (name_ == NULL) { + RAW_LOG(FATAL, "Heap leak checker must not be turned on " + "after construction of a HeapLeakChecker"); + } + + MemoryRegionMap::LockHolder ml; + int a_local_var; // Use our stack ptr to make stack data live: + + // Make the heap profile, other threads are locked out. + HeapProfileTable::Snapshot* base = + reinterpret_cast(start_snapshot_); + RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, ""); + pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment; + IgnoreAllLiveObjectsLocked(&a_local_var); + leaks = heap_profile->NonLiveSnapshot(base); + + inuse_bytes_increase_ = static_cast(leaks->total().alloc_size); + inuse_allocs_increase_ = static_cast(leaks->total().allocs); + if (leaks->Empty()) { + heap_profile->ReleaseSnapshot(leaks); + leaks = NULL; + + // We can only check for internal leaks along the no-user-leak + // path since in the leak path we temporarily release + // heap_checker_lock and another thread can come in and disturb + // allocation counts. + if (Allocator::alloc_count() != initial_allocs) { + RAW_LOG(FATAL, "Internal HeapChecker leak of %d objects ; %d -> %d", + Allocator::alloc_count() - initial_allocs, + initial_allocs, Allocator::alloc_count()); + } + } else if (FLAGS_heap_check_test_pointer_alignment) { + if (pointer_source_alignment == 1) { + RAW_LOG(WARNING, "--heap_check_test_pointer_alignment has no effect: " + "--heap_check_pointer_source_alignment was already set to 1"); + } else { + // Try with reduced pointer aligment + pointer_source_alignment = 1; + IgnoreAllLiveObjectsLocked(&a_local_var); + HeapProfileTable::Snapshot* leaks_wo_align = + heap_profile->NonLiveSnapshot(base); + pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment; + if (leaks_wo_align->Empty()) { + RAW_LOG(WARNING, "Found no leaks without pointer alignment: " + "something might be placing pointers at " + "unaligned addresses! This needs to be fixed."); + } else { + RAW_LOG(INFO, "Found leaks without pointer alignment as well: " + "unaligned pointers must not be the cause of leaks."); + RAW_LOG(INFO, "--heap_check_test_pointer_alignment did not help " + "to diagnose the leaks."); + } + heap_profile->ReleaseSnapshot(leaks_wo_align); + } + } + + if (leaks != NULL) { + pprof_file = MakeProfileNameLocked(); + } + } + + has_checked_ = true; + if (leaks == NULL) { + if (FLAGS_heap_check_max_pointer_offset == -1) { + RAW_LOG(WARNING, + "Found no leaks without max_pointer_offset restriction: " + "it's possible that the default value of " + "heap_check_max_pointer_offset flag is too low. " + "Do you use pointers with larger than that offsets " + "pointing in the middle of heap-allocated objects?"); + } + const HeapProfileTable::Stats& stats = heap_profile->total(); + RAW_VLOG(heap_checker_info_level, + "No leaks found for check \"%s\" " + "(but no 100%% guarantee that there aren't any): " + "found %" PRId64 " reachable heap objects of %" PRId64 " bytes", + name_, + int64(stats.allocs - stats.frees), + int64(stats.alloc_size - stats.free_size)); + } else { + if (should_symbolize == SYMBOLIZE) { + // To turn addresses into symbols, we need to fork, which is a + // problem if both parent and child end up trying to call the + // same malloc-hooks we've set up, at the same time. To avoid + // trouble, we turn off the hooks before symbolizing. Note that + // this makes it unsafe to ever leak-report again! Luckily, we + // typically only want to report once in a program's run, at the + // very end. + if (MallocHook::GetNewHook() == NewHook) + MallocHook::SetNewHook(NULL); + if (MallocHook::GetDeleteHook() == DeleteHook) + MallocHook::SetDeleteHook(NULL); + MemoryRegionMap::Shutdown(); + // Make sure all the hooks really got unset: + RAW_CHECK(MallocHook::GetNewHook() == NULL, ""); + RAW_CHECK(MallocHook::GetDeleteHook() == NULL, ""); + RAW_CHECK(MallocHook::GetMmapHook() == NULL, ""); + RAW_CHECK(MallocHook::GetSbrkHook() == NULL, ""); + have_disabled_hooks_for_symbolize = true; + leaks->ReportLeaks(name_, pprof_file, true); // true = should_symbolize + } else { + leaks->ReportLeaks(name_, pprof_file, false); + } + if (FLAGS_heap_check_identify_leaks) { + leaks->ReportIndividualObjects(); + } + + SuggestPprofCommand(pprof_file); + + { + SpinLockHolder hl(&heap_checker_lock); + heap_profile->ReleaseSnapshot(leaks); + Allocator::Free(pprof_file); + } + } + + return (leaks == NULL); +} + +HeapLeakChecker::~HeapLeakChecker() { + if (name_ != NULL) { // had leak checking enabled when created the checker + if (!has_checked_) { + RAW_LOG(FATAL, "Some *NoLeaks|SameHeap method" + " must be called on any created HeapLeakChecker"); + } + + // Deallocate any snapshot taken at start + if (start_snapshot_ != NULL) { + SpinLockHolder l(&heap_checker_lock); + heap_profile->ReleaseSnapshot( + reinterpret_cast(start_snapshot_)); + } + + UnIgnoreObject(name_); + delete[] name_; + name_ = NULL; + } + delete lock_; +} + +//---------------------------------------------------------------------- +// HeapLeakChecker overall heap check components +//---------------------------------------------------------------------- + +// static +bool HeapLeakChecker::IsActive() { + SpinLockHolder l(&heap_checker_lock); + return heap_checker_on; +} + +vector* HeapCleaner::heap_cleanups_ = NULL; + +// When a HeapCleaner object is intialized, add its function to the static list +// of cleaners to be run before leaks checking. +HeapCleaner::HeapCleaner(void_function f) { + if (heap_cleanups_ == NULL) + heap_cleanups_ = new vector; + heap_cleanups_->push_back(f); +} + +// Run all of the cleanup functions and delete the vector. +void HeapCleaner::RunHeapCleanups() { + if (!heap_cleanups_) + return; + for (int i = 0; i < heap_cleanups_->size(); i++) { + void (*f)(void) = (*heap_cleanups_)[i]; + f(); + } + delete heap_cleanups_; + heap_cleanups_ = NULL; +} + +// Program exit heap cleanup registered as a module object destructor. +// Will not get executed when we crash on a signal. +// +void HeapLeakChecker_RunHeapCleanups() { + if (FLAGS_heap_check == "local") // don't check heap in this mode + return; + { SpinLockHolder l(&heap_checker_lock); + // can get here (via forks?) with other pids + if (heap_checker_pid != getpid()) return; + } + HeapCleaner::RunHeapCleanups(); + if (!FLAGS_heap_check_after_destructors) HeapLeakChecker::DoMainHeapCheck(); +} + +static bool internal_init_start_has_run = false; + +// Called exactly once, before main() (but hopefully just before). +// This picks a good unique name for the dumped leak checking heap profiles. +// +// Because we crash when InternalInitStart is called more than once, +// it's fine that we hold heap_checker_lock only around pieces of +// this function: this is still enough for thread-safety w.r.t. other functions +// of this module. +// We can't hold heap_checker_lock throughout because it would deadlock +// on a memory allocation since our new/delete hooks can be on. +// +void HeapLeakChecker_InternalInitStart() { + { SpinLockHolder l(&heap_checker_lock); + RAW_CHECK(!internal_init_start_has_run, + "Heap-check constructor called twice. Perhaps you both linked" + " in the heap checker, and also used LD_PRELOAD to load it?"); + internal_init_start_has_run = true; + +#ifdef ADDRESS_SANITIZER + // AddressSanitizer's custom malloc conflicts with HeapChecker. + FLAGS_heap_check = ""; +#endif + + if (FLAGS_heap_check.empty()) { + // turns out we do not need checking in the end; can stop profiling + HeapLeakChecker::TurnItselfOffLocked(); + return; + } else if (RunningOnValgrind()) { + // There is no point in trying -- we'll just fail. + RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off"); + HeapLeakChecker::TurnItselfOffLocked(); + return; + } + } + + // Changing this to false can be useful when debugging heap-checker itself: + if (!FLAGS_heap_check_run_under_gdb && IsDebuggerAttached()) { + RAW_LOG(WARNING, "Someone is ptrace()ing us; will turn itself off"); + SpinLockHolder l(&heap_checker_lock); + HeapLeakChecker::TurnItselfOffLocked(); + return; + } + + { SpinLockHolder l(&heap_checker_lock); + if (!constructor_heap_profiling) { + RAW_LOG(FATAL, "Can not start so late. You have to enable heap checking " + "with HEAPCHECK=."); + } + } + + // Set all flags + RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, ""); + if (FLAGS_heap_check == "minimal") { + // The least we can check. + FLAGS_heap_check_before_constructors = false; // from after main + // (ignore more) + FLAGS_heap_check_after_destructors = false; // to after cleanup + // (most data is live) + FLAGS_heap_check_ignore_thread_live = true; // ignore all live + FLAGS_heap_check_ignore_global_live = true; // ignore all live + } else if (FLAGS_heap_check == "normal") { + // Faster than 'minimal' and not much stricter. + FLAGS_heap_check_before_constructors = true; // from no profile (fast) + FLAGS_heap_check_after_destructors = false; // to after cleanup + // (most data is live) + FLAGS_heap_check_ignore_thread_live = true; // ignore all live + FLAGS_heap_check_ignore_global_live = true; // ignore all live + } else if (FLAGS_heap_check == "strict") { + // A bit stricter than 'normal': global destructors must fully clean up + // after themselves if they are present. + FLAGS_heap_check_before_constructors = true; // from no profile (fast) + FLAGS_heap_check_after_destructors = true; // to after destructors + // (less data live) + FLAGS_heap_check_ignore_thread_live = true; // ignore all live + FLAGS_heap_check_ignore_global_live = true; // ignore all live + } else if (FLAGS_heap_check == "draconian") { + // Drop not very portable and not very exact live heap flooding. + FLAGS_heap_check_before_constructors = true; // from no profile (fast) + FLAGS_heap_check_after_destructors = true; // to after destructors + // (need them) + FLAGS_heap_check_ignore_thread_live = false; // no live flood (stricter) + FLAGS_heap_check_ignore_global_live = false; // no live flood (stricter) + } else if (FLAGS_heap_check == "as-is") { + // do nothing: use other flags as is + } else if (FLAGS_heap_check == "local") { + // do nothing + } else { + RAW_LOG(FATAL, "Unsupported heap_check flag: %s", + FLAGS_heap_check.c_str()); + } + // FreeBSD doesn't seem to honor atexit execution order: + // http://code.google.com/p/gperftools/issues/detail?id=375 + // Since heap-checking before destructors depends on atexit running + // at the right time, on FreeBSD we always check after, even in the + // less strict modes. This just means FreeBSD is always a bit + // stricter in its checking than other OSes. + // This now appears to be the case in other OSes as well; + // so always check afterwards. + FLAGS_heap_check_after_destructors = true; + + { SpinLockHolder l(&heap_checker_lock); + RAW_DCHECK(heap_checker_pid == getpid(), ""); + heap_checker_on = true; + RAW_DCHECK(heap_profile, ""); + HeapLeakChecker::ProcMapsResult pm_result = HeapLeakChecker::UseProcMapsLocked(HeapLeakChecker::DISABLE_LIBRARY_ALLOCS); + // might neeed to do this more than once + // if one later dynamically loads libraries that we want disabled + if (pm_result != HeapLeakChecker::PROC_MAPS_USED) { // can't function + HeapLeakChecker::TurnItselfOffLocked(); + return; + } + } + + // make a good place and name for heap profile leak dumps + string* profile_prefix = + new string(FLAGS_heap_check_dump_directory + "/" + invocation_name()); + + // Finalize prefix for dumping leak checking profiles. + const int32 our_pid = getpid(); // safest to call getpid() outside lock + { SpinLockHolder l(&heap_checker_lock); + // main_thread_pid might still be 0 if this function is being called before + // global constructors. In that case, our pid *is* the main pid. + if (main_thread_pid == 0) + main_thread_pid = our_pid; + } + char pid_buf[15]; + snprintf(pid_buf, sizeof(pid_buf), ".%d", main_thread_pid); + *profile_prefix += pid_buf; + { SpinLockHolder l(&heap_checker_lock); + RAW_DCHECK(profile_name_prefix == NULL, ""); + profile_name_prefix = profile_prefix; + } + + // Make sure new/delete hooks are installed properly + // and heap profiler is indeed able to keep track + // of the objects being allocated. + // We test this to make sure we are indeed checking for leaks. + char* test_str = new char[5]; + size_t size; + { SpinLockHolder l(&heap_checker_lock); + RAW_CHECK(heap_profile->FindAlloc(test_str, &size), + "our own new/delete not linked?"); + } + delete[] test_str; + { SpinLockHolder l(&heap_checker_lock); + // This check can fail when it should not if another thread allocates + // into this same spot right this moment, + // which is unlikely since this code runs in InitGoogle. + RAW_CHECK(!heap_profile->FindAlloc(test_str, &size), + "our own new/delete not linked?"); + } + // If we crash in the above code, it probably means that + // "nm | grep new" will show that tcmalloc's new/delete + // implementation did not get linked-in into this binary + // (i.e. nm will list __builtin_new and __builtin_vec_new as undefined). + // If this happens, it is a BUILD bug to be fixed. + + RAW_VLOG(heap_checker_info_level, + "WARNING: Perftools heap leak checker is active " + "-- Performance may suffer"); + + if (FLAGS_heap_check != "local") { + HeapLeakChecker* main_hc = new HeapLeakChecker(); + SpinLockHolder l(&heap_checker_lock); + RAW_DCHECK(main_heap_checker == NULL, + "Repeated creation of main_heap_checker"); + main_heap_checker = main_hc; + do_main_heap_check = true; + } + + { SpinLockHolder l(&heap_checker_lock); + RAW_CHECK(heap_checker_on && constructor_heap_profiling, + "Leak checking is expected to be fully turned on now"); + } + + // For binaries built in debug mode, this will set release queue of + // debugallocation.cc to 100M to make it less likely for real leaks to + // be hidden due to reuse of heap memory object addresses. + // Running a test with --malloc_reclaim_memory=0 would help find leaks even + // better, but the test might run out of memory as a result. + // The scenario is that a heap object at address X is allocated and freed, + // but some other data-structure still retains a pointer to X. + // Then the same heap memory is used for another object, which is leaked, + // but the leak is not noticed due to the pointer to the original object at X. + // TODO(csilvers): support this in some manner. +#if 0 + SetCommandLineOptionWithMode("max_free_queue_size", "104857600", // 100M + SET_FLAG_IF_DEFAULT); +#endif +} + +// We want this to run early as well, but not so early as +// ::BeforeConstructors (we want flag assignments to have already +// happened, for instance). Initializer-registration does the trick. +REGISTER_MODULE_INITIALIZER(init_start, HeapLeakChecker_InternalInitStart()); +REGISTER_MODULE_DESTRUCTOR(init_start, HeapLeakChecker_RunHeapCleanups()); + +// static +bool HeapLeakChecker::NoGlobalLeaksMaybeSymbolize( + ShouldSymbolize should_symbolize) { + // we never delete or change main_heap_checker once it's set: + HeapLeakChecker* main_hc = GlobalChecker(); + if (main_hc) { + RAW_VLOG(10, "Checking for whole-program memory leaks"); + return main_hc->DoNoLeaks(should_symbolize); + } + return true; +} + +// static +bool HeapLeakChecker::DoMainHeapCheck() { + if (FLAGS_heap_check_delay_seconds > 0) { + sleep(FLAGS_heap_check_delay_seconds); + } + { SpinLockHolder l(&heap_checker_lock); + if (!do_main_heap_check) return false; + RAW_DCHECK(heap_checker_pid == getpid(), ""); + do_main_heap_check = false; // will do it now; no need to do it more + } + + // The program is over, so it's safe to symbolize addresses (which + // requires a fork) because no serious work is expected to be done + // after this. Symbolizing is really useful -- knowing what + // function has a leak is better than knowing just an address -- + // and while we can only safely symbolize once in a program run, + // now is the time (after all, there's no "later" that would be better). + if (!NoGlobalLeaksMaybeSymbolize(SYMBOLIZE)) { + if (FLAGS_heap_check_identify_leaks) { + RAW_LOG(FATAL, "Whole-program memory leaks found."); + } + RAW_LOG(ERROR, "Exiting with error code (instead of crashing) " + "because of whole-program memory leaks"); + _exit(1); // we don't want to call atexit() routines! + } + return true; +} + +// static +HeapLeakChecker* HeapLeakChecker::GlobalChecker() { + SpinLockHolder l(&heap_checker_lock); + return main_heap_checker; +} + +// static +bool HeapLeakChecker::NoGlobalLeaks() { + // symbolizing requires a fork, which isn't safe to do in general. + return NoGlobalLeaksMaybeSymbolize(DO_NOT_SYMBOLIZE); +} + +// static +void HeapLeakChecker::CancelGlobalCheck() { + SpinLockHolder l(&heap_checker_lock); + if (do_main_heap_check) { + RAW_VLOG(heap_checker_info_level, + "Canceling the automatic at-exit whole-program memory leak check"); + do_main_heap_check = false; + } +} + +// static +void HeapLeakChecker::BeforeConstructorsLocked() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + RAW_CHECK(!constructor_heap_profiling, + "BeforeConstructorsLocked called multiple times"); +#ifdef ADDRESS_SANITIZER + // AddressSanitizer's custom malloc conflicts with HeapChecker. + return; +#endif + // Set hooks early to crash if 'new' gets called before we make heap_profile, + // and make sure no other hooks existed: + RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); + RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); + constructor_heap_profiling = true; + MemoryRegionMap::Init(1, /* use_buckets */ false); + // Set up MemoryRegionMap with (at least) one caller stack frame to record + // (important that it's done before HeapProfileTable creation below). + Allocator::Init(); + RAW_CHECK(heap_profile == NULL, ""); + heap_profile = new(Allocator::Allocate(sizeof(HeapProfileTable))) + HeapProfileTable(&Allocator::Allocate, &Allocator::Free, + /* profile_mmap */ false); + RAW_VLOG(10, "Starting tracking the heap"); + heap_checker_on = true; +} + +// static +void HeapLeakChecker::TurnItselfOffLocked() { + RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + // Set FLAGS_heap_check to "", for users who test for it + if (!FLAGS_heap_check.empty()) // be a noop in the common case + FLAGS_heap_check.clear(); // because clear() could allocate memory + if (constructor_heap_profiling) { + RAW_CHECK(heap_checker_on, ""); + RAW_VLOG(heap_checker_info_level, "Turning perftools heap leak checking off"); + heap_checker_on = false; + // Unset our hooks checking they were set: + RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), ""); + RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), ""); + Allocator::DeleteAndNull(&heap_profile); + // free our optional global data: + Allocator::DeleteAndNullIfNot(&ignored_objects); + Allocator::DeleteAndNullIfNot(&disabled_ranges); + Allocator::DeleteAndNullIfNot(&global_region_caller_ranges); + Allocator::Shutdown(); + MemoryRegionMap::Shutdown(); + } + RAW_CHECK(!heap_checker_on, ""); +} + +extern bool heap_leak_checker_bcad_variable; // in heap-checker-bcad.cc + +static bool has_called_before_constructors = false; + +// TODO(maxim): inline this function with +// MallocHook_InitAtFirstAllocation_HeapLeakChecker, and also rename +// HeapLeakChecker::BeforeConstructorsLocked. +void HeapLeakChecker_BeforeConstructors() { + SpinLockHolder l(&heap_checker_lock); + // We can be called from several places: the first mmap/sbrk/alloc call + // or the first global c-tor from heap-checker-bcad.cc: + // Do not re-execute initialization: + if (has_called_before_constructors) return; + has_called_before_constructors = true; + + heap_checker_pid = getpid(); // set it always + heap_leak_checker_bcad_variable = true; + // just to reference it, so that heap-checker-bcad.o is linked in + + // This function can be called *very* early, before the normal + // global-constructor that sets FLAGS_verbose. Set it manually now, + // so the RAW_LOG messages here are controllable. + const char* verbose_str = GetenvBeforeMain("PERFTOOLS_VERBOSE"); + if (verbose_str && atoi(verbose_str)) { // different than the default of 0? + FLAGS_verbose = atoi(verbose_str); + } + + bool need_heap_check = true; + // The user indicates a desire for heap-checking via the HEAPCHECK + // environment variable. If it's not set, there's no way to do + // heap-checking. + if (!GetenvBeforeMain("HEAPCHECK")) { + need_heap_check = false; + } +#ifdef HAVE_GETEUID + if (need_heap_check && getuid() != geteuid()) { + // heap-checker writes out files. Thus, for security reasons, we don't + // recognize the env. var. to turn on heap-checking if we're setuid. + RAW_LOG(WARNING, ("HeapChecker: ignoring HEAPCHECK because " + "program seems to be setuid\n")); + need_heap_check = false; + } +#endif + if (need_heap_check) { + HeapLeakChecker::BeforeConstructorsLocked(); + } +} + +// This function overrides the weak function defined in malloc_hook.cc and +// called by one of the initial malloc hooks (malloc_hook.cc) when the very +// first memory allocation or an mmap/sbrk happens. This ensures that +// HeapLeakChecker is initialized and installs all its hooks early enough to +// track absolutely all memory allocations and all memory region acquisitions +// via mmap and sbrk. +extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() { + HeapLeakChecker_BeforeConstructors(); +} + +// This function is executed after all global object destructors run. +void HeapLeakChecker_AfterDestructors() { + { SpinLockHolder l(&heap_checker_lock); + // can get here (via forks?) with other pids + if (heap_checker_pid != getpid()) return; + } + if (FLAGS_heap_check_after_destructors) { + if (HeapLeakChecker::DoMainHeapCheck()) { + const struct timespec sleep_time = { 0, 500000000 }; // 500 ms + nanosleep(&sleep_time, NULL); + // Need this hack to wait for other pthreads to exit. + // Otherwise tcmalloc find errors + // on a free() call from pthreads. + } + } + SpinLockHolder l(&heap_checker_lock); + RAW_CHECK(!do_main_heap_check, "should have done it"); +} + +//---------------------------------------------------------------------- +// HeapLeakChecker disabling helpers +//---------------------------------------------------------------------- + +// These functions are at the end of the file to prevent their inlining: + +// static +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, ""); + if (disabled_ranges == NULL) { + disabled_ranges = new(Allocator::Allocate(sizeof(DisabledRangeMap))) + DisabledRangeMap; + } + RangeValue value; + value.start_address = AsInt(start_address); + value.max_depth = max_depth; + if (disabled_ranges->insert(make_pair(AsInt(end_address), value)).second) { + RAW_VLOG(10, "Disabling leak checking in stack traces " + "under frame addresses between %p..%p", + start_address, end_address); + } else { // check that this is just a verbatim repetition + RangeValue const& val = disabled_ranges->find(AsInt(end_address))->second; + if (val.max_depth != value.max_depth || + val.start_address != value.start_address) { + RAW_LOG(FATAL, "Two DisableChecksToHereFrom calls conflict: " + "(%p, %p, %d) vs. (%p, %p, %d)", + AsPtr(val.start_address), end_address, val.max_depth, + start_address, end_address, max_depth); + } + } +} + +// static +inline bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr, + size_t* object_size) { + // Commented-out because HaveOnHeapLocked is very performance-critical: + // RAW_DCHECK(heap_checker_lock.IsHeld(), ""); + const uintptr_t addr = AsInt(*ptr); + if (heap_profile->FindInsideAlloc( + *ptr, max_heap_object_size, ptr, object_size)) { + RAW_VLOG(16, "Got pointer into %p at +%" PRIuPTR " offset", + *ptr, addr - AsInt(*ptr)); + return true; + } + return false; +} + +// static +const void* HeapLeakChecker::GetAllocCaller(void* ptr) { + // this is used only in the unittest, so the heavy checks are fine + HeapProfileTable::AllocInfo info; + { SpinLockHolder l(&heap_checker_lock); + RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), ""); + } + RAW_CHECK(info.stack_depth >= 1, ""); + return info.call_stack[0]; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-profile-stats.h b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-stats.h new file mode 100644 index 000000000..1e0359a4d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-stats.h @@ -0,0 +1,78 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2013, 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. + +// This file defines structs to accumulate memory allocation and deallocation +// counts. These structs are commonly used for malloc (in HeapProfileTable) +// and mmap (in MemoryRegionMap). + +// A bucket is data structure for heap profiling to store a pair of a stack +// trace and counts of (de)allocation. Buckets are stored in a hash table +// which is declared as "HeapProfileBucket**". +// +// A hash value is computed from a stack trace. Collision in the hash table +// is resolved by separate chaining with linked lists. The links in the list +// are implemented with the member "HeapProfileBucket* next". +// +// A structure of a hash table HeapProfileBucket** bucket_table would be like: +// bucket_table[0] => NULL +// bucket_table[1] => HeapProfileBucket() => HeapProfileBucket() => NULL +// ... +// bucket_table[i] => HeapProfileBucket() => NULL +// ... +// bucket_table[n] => HeapProfileBucket() => NULL + +#ifndef HEAP_PROFILE_STATS_H_ +#define HEAP_PROFILE_STATS_H_ + +struct HeapProfileStats { + // Returns true if the two HeapProfileStats are semantically equal. + bool Equivalent(const HeapProfileStats& other) const { + return allocs - frees == other.allocs - other.frees && + alloc_size - free_size == other.alloc_size - other.free_size; + } + + int32 allocs; // Number of allocation calls. + int32 frees; // Number of free calls. + int64 alloc_size; // Total size of all allocated objects so far. + int64 free_size; // Total size of all freed objects so far. +}; + +// Allocation and deallocation statistics per each stack trace. +struct HeapProfileBucket : public HeapProfileStats { + // Longest stack trace we record. + static const int kMaxStackDepth = 32; + + uintptr_t hash; // Hash value of the stack trace. + int depth; // Depth of stack trace. + const void** stack; // Stack trace. + HeapProfileBucket* next; // Next entry in hash-table. +}; + +#endif // HEAP_PROFILE_STATS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.cc b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.cc new file mode 100644 index 000000000..93d592c3b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.cc @@ -0,0 +1,629 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2006, 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: Sanjay Ghemawat +// Maxim Lifantsev (refactoring) +// + +#include + +#ifdef HAVE_UNISTD_H +#include // for write() +#endif +#include // for open() +#ifdef HAVE_GLOB_H +#include +#ifndef GLOB_NOMATCH // true on some old cygwins +# define GLOB_NOMATCH 0 +#endif +#endif +#ifdef HAVE_INTTYPES_H +#include // for PRIxPTR +#endif +#ifdef HAVE_POLL_H +#include +#endif +#include +#include +#include +#include +#include // for sort(), equal(), and copy() + +#include "heap-profile-table.h" + +#include "base/logging.h" +#include "raw_printer.h" +#include "symbolize.h" +#include +#include +#include "memory_region_map.h" +#include "base/commandlineflags.h" +#include "base/logging.h" // for the RawFD I/O commands +#include "base/sysinfo.h" + +using std::sort; +using std::equal; +using std::copy; +using std::string; +using std::map; + +using tcmalloc::FillProcSelfMaps; // from sysinfo.h +using tcmalloc::DumpProcSelfMaps; // from sysinfo.h + +//---------------------------------------------------------------------- + +DEFINE_bool(cleanup_old_heap_profiles, + EnvToBool("HEAP_PROFILE_CLEANUP", true), + "At initialization time, delete old heap profiles."); + +DEFINE_int32(heap_check_max_leaks, + EnvToInt("HEAP_CHECK_MAX_LEAKS", 20), + "The maximum number of leak reports to print."); + +//---------------------------------------------------------------------- + +// header of the dumped heap profile +static const char kProfileHeader[] = "heap profile: "; +static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n"; + +//---------------------------------------------------------------------- + +const char HeapProfileTable::kFileExt[] = ".heap"; + +//---------------------------------------------------------------------- + +static const int kHashTableSize = 179999; // Size for bucket_table_. +/*static*/ const int HeapProfileTable::kMaxStackDepth; + +//---------------------------------------------------------------------- + +// We strip out different number of stack frames in debug mode +// because less inlining happens in that case +#ifdef NDEBUG +static const int kStripFrames = 2; +#else +static const int kStripFrames = 3; +#endif + +// For sorting Stats or Buckets by in-use space +static bool ByAllocatedSpace(HeapProfileTable::Stats* a, + HeapProfileTable::Stats* b) { + // Return true iff "a" has more allocated space than "b" + return (a->alloc_size - a->free_size) > (b->alloc_size - b->free_size); +} + +//---------------------------------------------------------------------- + +HeapProfileTable::HeapProfileTable(Allocator alloc, + DeAllocator dealloc, + bool profile_mmap) + : alloc_(alloc), + dealloc_(dealloc), + profile_mmap_(profile_mmap), + bucket_table_(NULL), + num_buckets_(0), + address_map_(NULL) { + // Make a hash table for buckets. + const int table_bytes = kHashTableSize * sizeof(*bucket_table_); + bucket_table_ = static_cast(alloc_(table_bytes)); + memset(bucket_table_, 0, table_bytes); + + // Make an allocation map. + address_map_ = + new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_); + + // Initialize. + memset(&total_, 0, sizeof(total_)); + num_buckets_ = 0; +} + +HeapProfileTable::~HeapProfileTable() { + // Free the allocation map. + address_map_->~AllocationMap(); + dealloc_(address_map_); + address_map_ = NULL; + + // Free the hash table. + for (int i = 0; i < kHashTableSize; i++) { + for (Bucket* curr = bucket_table_[i]; curr != 0; /**/) { + Bucket* bucket = curr; + curr = curr->next; + dealloc_(bucket->stack); + dealloc_(bucket); + } + } + dealloc_(bucket_table_); + bucket_table_ = NULL; +} + +HeapProfileTable::Bucket* HeapProfileTable::GetBucket(int depth, + const void* const key[]) { + // Make hash-value + uintptr_t h = 0; + for (int i = 0; i < depth; i++) { + h += reinterpret_cast(key[i]); + h += h << 10; + h ^= h >> 6; + } + h += h << 3; + h ^= h >> 11; + + // Lookup stack trace in table + unsigned int buck = ((unsigned int) h) % kHashTableSize; + for (Bucket* b = bucket_table_[buck]; b != 0; b = b->next) { + if ((b->hash == h) && + (b->depth == depth) && + equal(key, key + depth, b->stack)) { + return b; + } + } + + // Create new bucket + const size_t key_size = sizeof(key[0]) * depth; + const void** kcopy = reinterpret_cast(alloc_(key_size)); + copy(key, key + depth, kcopy); + Bucket* b = reinterpret_cast(alloc_(sizeof(Bucket))); + memset(b, 0, sizeof(*b)); + b->hash = h; + b->depth = depth; + b->stack = kcopy; + b->next = bucket_table_[buck]; + bucket_table_[buck] = b; + num_buckets_++; + return b; +} + +int HeapProfileTable::GetCallerStackTrace( + int skip_count, void* stack[kMaxStackDepth]) { + return MallocHook::GetCallerStackTrace( + stack, kMaxStackDepth, kStripFrames + skip_count + 1); +} + +void HeapProfileTable::RecordAlloc( + const void* ptr, size_t bytes, int stack_depth, + const void* const call_stack[]) { + Bucket* b = GetBucket(stack_depth, call_stack); + b->allocs++; + b->alloc_size += bytes; + total_.allocs++; + total_.alloc_size += bytes; + + AllocValue v; + v.set_bucket(b); // also did set_live(false); set_ignore(false) + v.bytes = bytes; + address_map_->Insert(ptr, v); +} + +void HeapProfileTable::RecordFree(const void* ptr) { + AllocValue v; + if (address_map_->FindAndRemove(ptr, &v)) { + Bucket* b = v.bucket(); + b->frees++; + b->free_size += v.bytes; + total_.frees++; + total_.free_size += v.bytes; + } +} + +bool HeapProfileTable::FindAlloc(const void* ptr, size_t* object_size) const { + const AllocValue* alloc_value = address_map_->Find(ptr); + if (alloc_value != NULL) *object_size = alloc_value->bytes; + return alloc_value != NULL; +} + +bool HeapProfileTable::FindAllocDetails(const void* ptr, + AllocInfo* info) const { + const AllocValue* alloc_value = address_map_->Find(ptr); + if (alloc_value != NULL) { + info->object_size = alloc_value->bytes; + info->call_stack = alloc_value->bucket()->stack; + info->stack_depth = alloc_value->bucket()->depth; + } + return alloc_value != NULL; +} + +bool HeapProfileTable::FindInsideAlloc(const void* ptr, + size_t max_size, + const void** object_ptr, + size_t* object_size) const { + const AllocValue* alloc_value = + address_map_->FindInside(&AllocValueSize, max_size, ptr, object_ptr); + if (alloc_value != NULL) *object_size = alloc_value->bytes; + return alloc_value != NULL; +} + +bool HeapProfileTable::MarkAsLive(const void* ptr) { + AllocValue* alloc = address_map_->FindMutable(ptr); + if (alloc && !alloc->live()) { + alloc->set_live(true); + return true; + } + return false; +} + +void HeapProfileTable::MarkAsIgnored(const void* ptr) { + AllocValue* alloc = address_map_->FindMutable(ptr); + if (alloc) { + alloc->set_ignore(true); + } +} + +// We'd be happier using snprintfer, but we don't to reduce dependencies. +int HeapProfileTable::UnparseBucket(const Bucket& b, + char* buf, int buflen, int bufsize, + const char* extra, + Stats* profile_stats) { + if (profile_stats != NULL) { + profile_stats->allocs += b.allocs; + profile_stats->alloc_size += b.alloc_size; + profile_stats->frees += b.frees; + profile_stats->free_size += b.free_size; + } + int printed = + snprintf(buf + buflen, bufsize - buflen, "%6d: %8" PRId64 " [%6d: %8" PRId64 "] @%s", + b.allocs - b.frees, + b.alloc_size - b.free_size, + b.allocs, + b.alloc_size, + extra); + // If it looks like the snprintf failed, ignore the fact we printed anything + if (printed < 0 || printed >= bufsize - buflen) return buflen; + buflen += printed; + for (int d = 0; d < b.depth; d++) { + printed = snprintf(buf + buflen, bufsize - buflen, " 0x%08" PRIxPTR, + reinterpret_cast(b.stack[d])); + if (printed < 0 || printed >= bufsize - buflen) return buflen; + buflen += printed; + } + printed = snprintf(buf + buflen, bufsize - buflen, "\n"); + if (printed < 0 || printed >= bufsize - buflen) return buflen; + buflen += printed; + return buflen; +} + +HeapProfileTable::Bucket** +HeapProfileTable::MakeSortedBucketList() const { + Bucket** list = static_cast(alloc_(sizeof(Bucket) * num_buckets_)); + + int bucket_count = 0; + for (int i = 0; i < kHashTableSize; i++) { + for (Bucket* curr = bucket_table_[i]; curr != 0; curr = curr->next) { + list[bucket_count++] = curr; + } + } + RAW_DCHECK(bucket_count == num_buckets_, ""); + + sort(list, list + num_buckets_, ByAllocatedSpace); + + return list; +} + +void HeapProfileTable::IterateOrderedAllocContexts( + AllocContextIterator callback) const { + Bucket** list = MakeSortedBucketList(); + AllocContextInfo info; + for (int i = 0; i < num_buckets_; ++i) { + *static_cast(&info) = *static_cast(list[i]); + info.stack_depth = list[i]->depth; + info.call_stack = list[i]->stack; + callback(info); + } + dealloc_(list); +} + +int HeapProfileTable::FillOrderedProfile(char buf[], int size) const { + Bucket** list = MakeSortedBucketList(); + + // Our file format is "bucket, bucket, ..., bucket, proc_self_maps_info". + // In the cases buf is too small, we'd rather leave out the last + // buckets than leave out the /proc/self/maps info. To ensure that, + // we actually print the /proc/self/maps info first, then move it to + // the end of the buffer, then write the bucket info into whatever + // is remaining, and then move the maps info one last time to close + // any gaps. Whew! + int map_length = snprintf(buf, size, "%s", kProcSelfMapsHeader); + if (map_length < 0 || map_length >= size) { + dealloc_(list); + return 0; + } + bool dummy; // "wrote_all" -- did /proc/self/maps fit in its entirety? + map_length += FillProcSelfMaps(buf + map_length, size - map_length, &dummy); + RAW_DCHECK(map_length <= size, ""); + char* const map_start = buf + size - map_length; // move to end + memmove(map_start, buf, map_length); + size -= map_length; + + Stats stats; + memset(&stats, 0, sizeof(stats)); + int bucket_length = snprintf(buf, size, "%s", kProfileHeader); + if (bucket_length < 0 || bucket_length >= size) { + dealloc_(list); + return 0; + } + bucket_length = UnparseBucket(total_, buf, bucket_length, size, + " heapprofile", &stats); + + // Dump the mmap list first. + if (profile_mmap_) { + BufferArgs buffer(buf, bucket_length, size); + MemoryRegionMap::IterateBuckets(DumpBucketIterator, &buffer); + bucket_length = buffer.buflen; + } + + for (int i = 0; i < num_buckets_; i++) { + bucket_length = UnparseBucket(*list[i], buf, bucket_length, size, "", + &stats); + } + RAW_DCHECK(bucket_length < size, ""); + + dealloc_(list); + + RAW_DCHECK(buf + bucket_length <= map_start, ""); + memmove(buf + bucket_length, map_start, map_length); // close the gap + + return bucket_length + map_length; +} + +// static +void HeapProfileTable::DumpBucketIterator(const Bucket* bucket, + BufferArgs* args) { + args->buflen = UnparseBucket(*bucket, args->buf, args->buflen, args->bufsize, + "", NULL); +} + +inline +void HeapProfileTable::DumpNonLiveIterator(const void* ptr, AllocValue* v, + const DumpArgs& args) { + if (v->live()) { + v->set_live(false); + return; + } + if (v->ignore()) { + return; + } + Bucket b; + memset(&b, 0, sizeof(b)); + b.allocs = 1; + b.alloc_size = v->bytes; + b.depth = v->bucket()->depth; + b.stack = v->bucket()->stack; + char buf[1024]; + int len = UnparseBucket(b, buf, 0, sizeof(buf), "", args.profile_stats); + RawWrite(args.fd, buf, len); +} + +// Callback from NonLiveSnapshot; adds entry to arg->dest +// if not the entry is not live and is not present in arg->base. +void HeapProfileTable::AddIfNonLive(const void* ptr, AllocValue* v, + AddNonLiveArgs* arg) { + if (v->live()) { + v->set_live(false); + } else { + if (arg->base != NULL && arg->base->map_.Find(ptr) != NULL) { + // Present in arg->base, so do not save + } else { + arg->dest->Add(ptr, *v); + } + } +} + +bool HeapProfileTable::WriteProfile(const char* file_name, + const Bucket& total, + AllocationMap* allocations) { + RAW_VLOG(1, "Dumping non-live heap profile to %s", file_name); + RawFD fd = RawOpenForWriting(file_name); + if (fd == kIllegalRawFD) { + RAW_LOG(ERROR, "Failed dumping filtered heap profile to %s", file_name); + return false; + } + RawWrite(fd, kProfileHeader, strlen(kProfileHeader)); + char buf[512]; + int len = UnparseBucket(total, buf, 0, sizeof(buf), " heapprofile", NULL); + RawWrite(fd, buf, len); + const DumpArgs args(fd, NULL); + allocations->Iterate(DumpNonLiveIterator, args); + RawWrite(fd, kProcSelfMapsHeader, strlen(kProcSelfMapsHeader)); + DumpProcSelfMaps(fd); + RawClose(fd); + return true; +} + +void HeapProfileTable::CleanupOldProfiles(const char* prefix) { + if (!FLAGS_cleanup_old_heap_profiles) + return; + string pattern = string(prefix) + ".*" + kFileExt; +#if defined(HAVE_GLOB_H) + glob_t g; + const int r = glob(pattern.c_str(), GLOB_ERR, NULL, &g); + if (r == 0 || r == GLOB_NOMATCH) { + const int prefix_length = strlen(prefix); + for (int i = 0; i < g.gl_pathc; i++) { + const char* fname = g.gl_pathv[i]; + if ((strlen(fname) >= prefix_length) && + (memcmp(fname, prefix, prefix_length) == 0)) { + RAW_VLOG(1, "Removing old heap profile %s", fname); + unlink(fname); + } + } + } + globfree(&g); +#else /* HAVE_GLOB_H */ + RAW_LOG(WARNING, "Unable to remove old heap profiles (can't run glob())"); +#endif +} + +HeapProfileTable::Snapshot* HeapProfileTable::TakeSnapshot() { + Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_); + address_map_->Iterate(AddToSnapshot, s); + return s; +} + +void HeapProfileTable::ReleaseSnapshot(Snapshot* s) { + s->~Snapshot(); + dealloc_(s); +} + +// Callback from TakeSnapshot; adds a single entry to snapshot +void HeapProfileTable::AddToSnapshot(const void* ptr, AllocValue* v, + Snapshot* snapshot) { + snapshot->Add(ptr, *v); +} + +HeapProfileTable::Snapshot* HeapProfileTable::NonLiveSnapshot( + Snapshot* base) { + RAW_VLOG(2, "NonLiveSnapshot input: %d %d\n", + int(total_.allocs - total_.frees), + int(total_.alloc_size - total_.free_size)); + + Snapshot* s = new (alloc_(sizeof(Snapshot))) Snapshot(alloc_, dealloc_); + AddNonLiveArgs args; + args.dest = s; + args.base = base; + address_map_->Iterate(AddIfNonLive, &args); + RAW_VLOG(2, "NonLiveSnapshot output: %d %d\n", + int(s->total_.allocs - s->total_.frees), + int(s->total_.alloc_size - s->total_.free_size)); + return s; +} + +// Information kept per unique bucket seen +struct HeapProfileTable::Snapshot::Entry { + int count; + int bytes; + Bucket* bucket; + Entry() : count(0), bytes(0) { } + + // Order by decreasing bytes + bool operator<(const Entry& x) const { + return this->bytes > x.bytes; + } +}; + +// State used to generate leak report. We keep a mapping from Bucket pointer +// the collected stats for that bucket. +struct HeapProfileTable::Snapshot::ReportState { + map buckets_; +}; + +// Callback from ReportLeaks; updates ReportState. +void HeapProfileTable::Snapshot::ReportCallback(const void* ptr, + AllocValue* v, + ReportState* state) { + Entry* e = &state->buckets_[v->bucket()]; // Creates empty Entry first time + e->bucket = v->bucket(); + e->count++; + e->bytes += v->bytes; +} + +void HeapProfileTable::Snapshot::ReportLeaks(const char* checker_name, + const char* filename, + bool should_symbolize) { + // This is only used by the heap leak checker, but is intimately + // tied to the allocation map that belongs in this module and is + // therefore placed here. + RAW_LOG(ERROR, "Leak check %s detected leaks of %zu bytes " + "in %zu objects", + checker_name, + size_t(total_.alloc_size), + size_t(total_.allocs)); + + // Group objects by Bucket + ReportState state; + map_.Iterate(&ReportCallback, &state); + + // Sort buckets by decreasing leaked size + const int n = state.buckets_.size(); + Entry* entries = new Entry[n]; + int dst = 0; + for (map::const_iterator iter = state.buckets_.begin(); + iter != state.buckets_.end(); + ++iter) { + entries[dst++] = iter->second; + } + sort(entries, entries + n); + + // Report a bounded number of leaks to keep the leak report from + // growing too long. + const int to_report = + (FLAGS_heap_check_max_leaks > 0 && + n > FLAGS_heap_check_max_leaks) ? FLAGS_heap_check_max_leaks : n; + RAW_LOG(ERROR, "The %d largest leaks:", to_report); + + // Print + SymbolTable symbolization_table; + for (int i = 0; i < to_report; i++) { + const Entry& e = entries[i]; + for (int j = 0; j < e.bucket->depth; j++) { + symbolization_table.Add(e.bucket->stack[j]); + } + } + static const int kBufSize = 2<<10; + char buffer[kBufSize]; + if (should_symbolize) + symbolization_table.Symbolize(); + for (int i = 0; i < to_report; i++) { + const Entry& e = entries[i]; + base::RawPrinter printer(buffer, kBufSize); + printer.Printf("Leak of %d bytes in %d objects allocated from:\n", + e.bytes, e.count); + for (int j = 0; j < e.bucket->depth; j++) { + const void* pc = e.bucket->stack[j]; + printer.Printf("\t@ %" PRIxPTR " %s\n", + reinterpret_cast(pc), symbolization_table.GetSymbol(pc)); + } + RAW_LOG(ERROR, "%s", buffer); + } + + if (to_report < n) { + RAW_LOG(ERROR, "Skipping leaks numbered %d..%d", + to_report, n-1); + } + delete[] entries; + + // TODO: Dump the sorted Entry list instead of dumping raw data? + // (should be much shorter) + if (!HeapProfileTable::WriteProfile(filename, total_, &map_)) { + RAW_LOG(ERROR, "Could not write pprof profile to %s", filename); + } +} + +void HeapProfileTable::Snapshot::ReportObject(const void* ptr, + AllocValue* v, + char* unused) { + // Perhaps also log the allocation stack trace (unsymbolized) + // on this line in case somebody finds it useful. + RAW_LOG(ERROR, "leaked %zu byte object %p", v->bytes, ptr); +} + +void HeapProfileTable::Snapshot::ReportIndividualObjects() { + char unused; + map_.Iterate(ReportObject, &unused); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.h b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.h new file mode 100644 index 000000000..afe13198b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-profile-table.h @@ -0,0 +1,399 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2006, 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: Sanjay Ghemawat +// Maxim Lifantsev (refactoring) +// + +#ifndef BASE_HEAP_PROFILE_TABLE_H_ +#define BASE_HEAP_PROFILE_TABLE_H_ + +#include "addressmap-inl.h" +#include "base/basictypes.h" +#include "base/logging.h" // for RawFD +#include "heap-profile-stats.h" + +// Table to maintain a heap profile data inside, +// i.e. the set of currently active heap memory allocations. +// thread-unsafe and non-reentrant code: +// each instance object must be used by one thread +// at a time w/o self-recursion. +// +// TODO(maxim): add a unittest for this class. +class HeapProfileTable { + public: + + // Extension to be used for heap pforile files. + static const char kFileExt[]; + + // Longest stack trace we record. + static const int kMaxStackDepth = 32; + + // data types ---------------------------- + + // Profile stats. + typedef HeapProfileStats Stats; + + // Info we can return about an allocation. + struct AllocInfo { + size_t object_size; // size of the allocation + const void* const* call_stack; // call stack that made the allocation call + int stack_depth; // depth of call_stack + bool live; + bool ignored; + }; + + // Info we return about an allocation context. + // An allocation context is a unique caller stack trace + // of an allocation operation. + struct AllocContextInfo : public Stats { + int stack_depth; // Depth of stack trace + const void* const* call_stack; // Stack trace + }; + + // Memory (de)allocator interface we'll use. + typedef void* (*Allocator)(size_t size); + typedef void (*DeAllocator)(void* ptr); + + // interface --------------------------- + + HeapProfileTable(Allocator alloc, DeAllocator dealloc, bool profile_mmap); + ~HeapProfileTable(); + + // Collect the stack trace for the function that asked to do the + // allocation for passing to RecordAlloc() below. + // + // The stack trace is stored in 'stack'. The stack depth is returned. + // + // 'skip_count' gives the number of stack frames between this call + // and the memory allocation function. + static int GetCallerStackTrace(int skip_count, void* stack[kMaxStackDepth]); + + // Record an allocation at 'ptr' of 'bytes' bytes. 'stack_depth' + // and 'call_stack' identifying the function that requested the + // allocation. They can be generated using GetCallerStackTrace() above. + void RecordAlloc(const void* ptr, size_t bytes, + int stack_depth, const void* const call_stack[]); + + // Record the deallocation of memory at '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(const void* ptr, size_t* object_size) const; + // Same as FindAlloc, but fills all of *info. + bool FindAllocDetails(const void* ptr, AllocInfo* info) const; + + // Return true iff "ptr" points into a recorded allocation + // If yes, fill *object_ptr with the actual allocation address + // and *object_size with the allocation byte size. + // max_size specifies largest currently possible allocation size. + bool FindInsideAlloc(const void* ptr, size_t max_size, + const void** object_ptr, size_t* object_size) const; + + // If "ptr" points to a recorded allocation and it's not marked as live + // mark it as live and return true. Else return false. + // All allocations start as non-live. + bool MarkAsLive(const void* ptr); + + // If "ptr" points to a recorded allocation, mark it as "ignored". + // Ignored objects are treated like other objects, except that they + // are skipped in heap checking reports. + void MarkAsIgnored(const void* ptr); + + // Return current total (de)allocation statistics. It doesn't contain + // mmap'ed regions. + const Stats& total() const { return total_; } + + // Allocation data iteration callback: gets passed object pointer and + // fully-filled AllocInfo. + typedef void (*AllocIterator)(const void* ptr, const AllocInfo& info); + + // Iterate over the allocation profile data calling "callback" + // for every allocation. + void IterateAllocs(AllocIterator callback) const { + address_map_->Iterate(MapArgsAllocIterator, callback); + } + + // Allocation context profile data iteration callback + typedef void (*AllocContextIterator)(const AllocContextInfo& info); + + // Iterate over the allocation context profile data calling "callback" + // for every allocation context. Allocation contexts are ordered by the + // size of allocated space. + void IterateOrderedAllocContexts(AllocContextIterator callback) const; + + // Fill profile data into buffer 'buf' of size 'size' + // and return the actual size occupied by the dump in 'buf'. + // The profile buckets are dumped in the decreasing order + // of currently allocated bytes. + // We do not provision for 0-terminating 'buf'. + int FillOrderedProfile(char buf[], int size) const; + + // Cleanup any old profile files matching prefix + ".*" + kFileExt. + static void CleanupOldProfiles(const char* prefix); + + // Return a snapshot of the current contents of *this. + // Caller must call ReleaseSnapshot() on result when no longer needed. + // The result is only valid while this exists and until + // the snapshot is discarded by calling ReleaseSnapshot(). + class Snapshot; + Snapshot* TakeSnapshot(); + + // Release a previously taken snapshot. snapshot must not + // be used after this call. + void ReleaseSnapshot(Snapshot* snapshot); + + // Return a snapshot of every non-live, non-ignored object in *this. + // If "base" is non-NULL, skip any objects present in "base". + // As a side-effect, clears the "live" bit on every live object in *this. + // Caller must call ReleaseSnapshot() on result when no longer needed. + Snapshot* NonLiveSnapshot(Snapshot* base); + + private: + + // data types ---------------------------- + + // Hash table bucket to hold (de)allocation stats + // for a given allocation call stack trace. + typedef HeapProfileBucket Bucket; + + // Info stored in the address map + struct AllocValue { + // Access to the stack-trace bucket + Bucket* bucket() const { + return reinterpret_cast(bucket_rep & ~uintptr_t(kMask)); + } + // This also does set_live(false). + void set_bucket(Bucket* b) { bucket_rep = reinterpret_cast(b); } + size_t bytes; // Number of bytes in this allocation + + // Access to the allocation liveness flag (for leak checking) + bool live() const { return bucket_rep & kLive; } + void set_live(bool l) { + bucket_rep = (bucket_rep & ~uintptr_t(kLive)) | (l ? kLive : 0); + } + + // Should this allocation be ignored if it looks like a leak? + bool ignore() const { return bucket_rep & kIgnore; } + void set_ignore(bool r) { + bucket_rep = (bucket_rep & ~uintptr_t(kIgnore)) | (r ? kIgnore : 0); + } + + private: + // We store a few bits in the bottom bits of bucket_rep. + // (Alignment is at least four, so we have at least two bits.) + static const int kLive = 1; + static const int kIgnore = 2; + static const int kMask = kLive | kIgnore; + + uintptr_t bucket_rep; + }; + + // helper for FindInsideAlloc + static size_t AllocValueSize(const AllocValue& v) { return v.bytes; } + + typedef AddressMap AllocationMap; + + // Arguments that need to be passed DumpBucketIterator callback below. + struct BufferArgs { + BufferArgs(char* buf_arg, int buflen_arg, int bufsize_arg) + : buf(buf_arg), + buflen(buflen_arg), + bufsize(bufsize_arg) { + } + + char* buf; + int buflen; + int bufsize; + + DISALLOW_COPY_AND_ASSIGN(BufferArgs); + }; + + // Arguments that need to be passed DumpNonLiveIterator callback below. + struct DumpArgs { + DumpArgs(RawFD fd_arg, Stats* profile_stats_arg) + : fd(fd_arg), + profile_stats(profile_stats_arg) { + } + + RawFD fd; // file to write to + Stats* profile_stats; // stats to update (may be NULL) + }; + + // helpers ---------------------------- + + // Unparse bucket b and print its portion of profile dump into buf. + // We return the amount of space in buf that we use. We start printing + // at buf + buflen, and promise not to go beyond buf + bufsize. + // We do not provision for 0-terminating 'buf'. + // + // If profile_stats is non-NULL, we update *profile_stats by + // counting bucket b. + // + // "extra" is appended to the unparsed bucket. Typically it is empty, + // but may be set to something like " heapprofile" for the total + // bucket to indicate the type of the profile. + static int UnparseBucket(const Bucket& b, + char* buf, int buflen, int bufsize, + const char* extra, + Stats* profile_stats); + + // Get the bucket for the caller stack trace 'key' of depth 'depth' + // creating the bucket if needed. + Bucket* GetBucket(int depth, const void* const key[]); + + // Helper for IterateAllocs to do callback signature conversion + // from AllocationMap::Iterate to AllocIterator. + static void MapArgsAllocIterator(const void* ptr, AllocValue* v, + AllocIterator callback) { + AllocInfo info; + info.object_size = v->bytes; + info.call_stack = v->bucket()->stack; + info.stack_depth = v->bucket()->depth; + info.live = v->live(); + info.ignored = v->ignore(); + callback(ptr, info); + } + + // Helper to dump a bucket. + inline static void DumpBucketIterator(const Bucket* bucket, + BufferArgs* args); + + // Helper for DumpNonLiveProfile to do object-granularity + // heap profile dumping. It gets passed to AllocationMap::Iterate. + inline static void DumpNonLiveIterator(const void* ptr, AllocValue* v, + const DumpArgs& args); + + // Helper for IterateOrderedAllocContexts and FillOrderedProfile. + // Creates a sorted list of Buckets whose length is num_buckets_. + // The caller is responsible for deallocating the returned list. + Bucket** MakeSortedBucketList() const; + + // Helper for TakeSnapshot. Saves object to snapshot. + static void AddToSnapshot(const void* ptr, AllocValue* v, Snapshot* s); + + // Arguments passed to AddIfNonLive + struct AddNonLiveArgs { + Snapshot* dest; + Snapshot* base; + }; + + // Helper for NonLiveSnapshot. Adds the object to the destination + // snapshot if it is non-live. + static void AddIfNonLive(const void* ptr, AllocValue* v, + AddNonLiveArgs* arg); + + // Write contents of "*allocations" as a heap profile to + // "file_name". "total" must contain the total of all entries in + // "*allocations". + static bool WriteProfile(const char* file_name, + const Bucket& total, + AllocationMap* allocations); + + // data ---------------------------- + + // Memory (de)allocator that we use. + Allocator alloc_; + DeAllocator dealloc_; + + // Overall profile stats; we use only the Stats part, + // but make it a Bucket to pass to UnparseBucket. + Bucket total_; + + bool profile_mmap_; + + // Bucket hash table for malloc. + // We hand-craft one instead of using one of the pre-written + // ones because we do not want to use malloc when operating on the table. + // It is only few lines of code, so no big deal. + Bucket** bucket_table_; + int num_buckets_; + + // Map of all currently allocated objects and mapped regions we know about. + AllocationMap* address_map_; + + DISALLOW_COPY_AND_ASSIGN(HeapProfileTable); +}; + +class HeapProfileTable::Snapshot { + public: + const Stats& total() const { return total_; } + + // Report anything in this snapshot as a leak. + // May use new/delete for temporary storage. + // If should_symbolize is true, will fork (which is not threadsafe) + // to turn addresses into symbol names. Set to false for maximum safety. + // Also writes a heap profile to "filename" that contains + // all of the objects in this snapshot. + void ReportLeaks(const char* checker_name, const char* filename, + bool should_symbolize); + + // Report the addresses of all leaked objects. + // May use new/delete for temporary storage. + void ReportIndividualObjects(); + + bool Empty() const { + return (total_.allocs == 0) && (total_.alloc_size == 0); + } + + private: + friend class HeapProfileTable; + + // Total count/size are stored in a Bucket so we can reuse UnparseBucket + Bucket total_; + + // We share the Buckets managed by the parent table, but have our + // own object->bucket map. + AllocationMap map_; + + Snapshot(Allocator alloc, DeAllocator dealloc) : map_(alloc, dealloc) { + memset(&total_, 0, sizeof(total_)); + } + + // Callback used to populate a Snapshot object with entries found + // in another allocation map. + inline void Add(const void* ptr, const AllocValue& v) { + map_.Insert(ptr, v); + total_.allocs++; + total_.alloc_size += v.bytes; + } + + // Helpers for sorting and generating leak reports + struct Entry; + struct ReportState; + static void ReportCallback(const void* ptr, AllocValue* v, ReportState*); + static void ReportObject(const void* ptr, AllocValue* v, char*); + + DISALLOW_COPY_AND_ASSIGN(Snapshot); +}; + +#endif // BASE_HEAP_PROFILE_TABLE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/heap-profiler.cc b/trunk/3rdparty/gperftools-2-fit/src/heap-profiler.cc new file mode 100644 index 000000000..47df77922 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/heap-profiler.cc @@ -0,0 +1,622 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// TODO: Log large allocations + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include // for open() +#endif +#ifdef HAVE_MMAP +#include +#endif +#include +#include +#include +#include + +#include +#include + +#include + +#include "base/logging.h" +#include "base/basictypes.h" // for PRId64, among other things +#include "base/googleinit.h" +#include "base/commandlineflags.h" +#include "malloc_hook-inl.h" +#include "tcmalloc_guard.h" +#include +#include +#include "base/spinlock.h" +#include "base/low_level_alloc.h" +#include "base/sysinfo.h" // for GetUniquePathFromEnv() +#include "heap-profile-table.h" +#include "memory_region_map.h" + + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 4096 // seems conservative for max filename len! +#endif +#endif + +using std::string; +using std::sort; + +//---------------------------------------------------------------------- +// Flags that control heap-profiling +// +// The thread-safety of the profiler depends on these being immutable +// after main starts, so don't change them. +//---------------------------------------------------------------------- + +DEFINE_int64(heap_profile_allocation_interval, + EnvToInt64("HEAP_PROFILE_ALLOCATION_INTERVAL", 1 << 30 /*1GB*/), + "If non-zero, dump heap profiling information once every " + "specified number of bytes allocated by the program since " + "the last dump."); +DEFINE_int64(heap_profile_deallocation_interval, + EnvToInt64("HEAP_PROFILE_DEALLOCATION_INTERVAL", 0), + "If non-zero, dump heap profiling information once every " + "specified number of bytes deallocated by the program " + "since the last dump."); +// We could also add flags that report whenever inuse_bytes changes by +// X or -X, but there hasn't been a need for that yet, so we haven't. +DEFINE_int64(heap_profile_inuse_interval, + EnvToInt64("HEAP_PROFILE_INUSE_INTERVAL", 100 << 20 /*100MB*/), + "If non-zero, dump heap profiling information whenever " + "the high-water memory usage mark increases by the specified " + "number of bytes."); +DEFINE_int64(heap_profile_time_interval, + EnvToInt64("HEAP_PROFILE_TIME_INTERVAL", 0), + "If non-zero, dump heap profiling information once every " + "specified number of seconds since the last dump."); +DEFINE_bool(mmap_log, + EnvToBool("HEAP_PROFILE_MMAP_LOG", false), + "Should mmap/munmap calls be logged?"); +DEFINE_bool(mmap_profile, + EnvToBool("HEAP_PROFILE_MMAP", false), + "If heap-profiling is on, also profile mmap, mremap, and sbrk)"); +DEFINE_bool(only_mmap_profile, + EnvToBool("HEAP_PROFILE_ONLY_MMAP", false), + "If heap-profiling is on, only profile mmap, mremap, and sbrk; " + "do not profile malloc/new/etc"); + + +//---------------------------------------------------------------------- +// Locking +//---------------------------------------------------------------------- + +// A pthread_mutex has way too much lock contention to be used here. +// +// I would like to use Mutex, but it can call malloc(), +// which can cause us to fall into an infinite recursion. +// +// So we use a simple spinlock. +static SpinLock heap_lock(SpinLock::LINKER_INITIALIZED); + +//---------------------------------------------------------------------- +// Simple allocator for heap profiler's internal memory +//---------------------------------------------------------------------- + +static LowLevelAlloc::Arena *heap_profiler_memory; + +static void* ProfilerMalloc(size_t bytes) { + return LowLevelAlloc::AllocWithArena(bytes, heap_profiler_memory); +} +static void ProfilerFree(void* p) { + LowLevelAlloc::Free(p); +} + +// We use buffers of this size in DoGetHeapProfile. +static const int kProfileBufferSize = 1 << 20; + +// This is a last-ditch buffer we use in DumpProfileLocked in case we +// can't allocate more memory from ProfilerMalloc. We expect this +// will be used by HeapProfileEndWriter when the application has to +// exit due to out-of-memory. This buffer is allocated in +// HeapProfilerStart. Access to this must be protected by heap_lock. +static char* global_profiler_buffer = NULL; + + +//---------------------------------------------------------------------- +// Profiling control/state data +//---------------------------------------------------------------------- + +// Access to all of these is protected by heap_lock. +static bool is_on = false; // If are on as a subsytem. +static bool dumping = false; // Dumping status to prevent recursion +static char* filename_prefix = NULL; // Prefix used for profile file names + // (NULL if no need for dumping yet) +static int dump_count = 0; // How many dumps so far +static int64 last_dump_alloc = 0; // alloc_size when did we last dump +static int64 last_dump_free = 0; // free_size when did we last dump +static int64 high_water_mark = 0; // In-use-bytes at last high-water dump +static int64 last_dump_time = 0; // The time of the last dump + +static HeapProfileTable* heap_profile = NULL; // the heap profile table + +//---------------------------------------------------------------------- +// Profile generation +//---------------------------------------------------------------------- + +// Input must be a buffer of size at least 1MB. +static char* DoGetHeapProfileLocked(char* buf, int buflen) { + // We used to be smarter about estimating the required memory and + // then capping it to 1MB and generating the profile into that. + if (buf == NULL || buflen < 1) + return NULL; + + RAW_DCHECK(heap_lock.IsHeld(), ""); + int bytes_written = 0; + if (is_on) { + HeapProfileTable::Stats const stats = heap_profile->total(); + (void)stats; // avoid an unused-variable warning in non-debug mode. + bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1); + // FillOrderedProfile should not reduce the set of active mmap-ed regions, + // hence MemoryRegionMap will let us remove everything we've added above: + RAW_DCHECK(stats.Equivalent(heap_profile->total()), ""); + // if this fails, we somehow removed by FillOrderedProfile + // more than we have added. + } + buf[bytes_written] = '\0'; + RAW_DCHECK(bytes_written == strlen(buf), ""); + + return buf; +} + +extern "C" char* GetHeapProfile() { + // Use normal malloc: we return the profile to the user to free it: + char* buffer = reinterpret_cast(malloc(kProfileBufferSize)); + SpinLockHolder l(&heap_lock); + return DoGetHeapProfileLocked(buffer, kProfileBufferSize); +} + +// defined below +static void NewHook(const void* ptr, size_t size); +static void DeleteHook(const void* ptr); + +// Helper for HeapProfilerDump. +static void DumpProfileLocked(const char* reason) { + RAW_DCHECK(heap_lock.IsHeld(), ""); + RAW_DCHECK(is_on, ""); + RAW_DCHECK(!dumping, ""); + + if (filename_prefix == NULL) return; // we do not yet need dumping + + dumping = true; + + // Make file name + char file_name[1000]; + dump_count++; + snprintf(file_name, sizeof(file_name), "%s.%04d%s", + filename_prefix, dump_count, HeapProfileTable::kFileExt); + + // Dump the profile + RAW_VLOG(0, "Dumping heap profile to %s (%s)", file_name, reason); + // We must use file routines that don't access memory, since we hold + // a memory lock now. + RawFD fd = RawOpenForWriting(file_name); + if (fd == kIllegalRawFD) { + RAW_LOG(ERROR, "Failed dumping heap profile to %s", file_name); + dumping = false; + return; + } + + // This case may be impossible, but it's best to be safe. + // It's safe to use the global buffer: we're protected by heap_lock. + if (global_profiler_buffer == NULL) { + global_profiler_buffer = + reinterpret_cast(ProfilerMalloc(kProfileBufferSize)); + } + + char* profile = DoGetHeapProfileLocked(global_profiler_buffer, + kProfileBufferSize); + RawWrite(fd, profile, strlen(profile)); + RawClose(fd); + + dumping = false; +} + +//---------------------------------------------------------------------- +// Profile collection +//---------------------------------------------------------------------- + +// Dump a profile after either an allocation or deallocation, if +// the memory use has changed enough since the last dump. +static void MaybeDumpProfileLocked() { + if (!dumping) { + const HeapProfileTable::Stats& total = heap_profile->total(); + const int64 inuse_bytes = total.alloc_size - total.free_size; + bool need_to_dump = false; + char buf[128]; + + if (FLAGS_heap_profile_allocation_interval > 0 && + total.alloc_size >= + last_dump_alloc + FLAGS_heap_profile_allocation_interval) { + snprintf(buf, sizeof(buf), ("%" PRId64 " MB allocated cumulatively, " + "%" PRId64 " MB currently in use"), + total.alloc_size >> 20, inuse_bytes >> 20); + need_to_dump = true; + } else if (FLAGS_heap_profile_deallocation_interval > 0 && + total.free_size >= + last_dump_free + FLAGS_heap_profile_deallocation_interval) { + snprintf(buf, sizeof(buf), ("%" PRId64 " MB freed cumulatively, " + "%" PRId64 " MB currently in use"), + total.free_size >> 20, inuse_bytes >> 20); + need_to_dump = true; + } else if (FLAGS_heap_profile_inuse_interval > 0 && + inuse_bytes > + high_water_mark + FLAGS_heap_profile_inuse_interval) { + snprintf(buf, sizeof(buf), "%" PRId64 " MB currently in use", + inuse_bytes >> 20); + need_to_dump = true; + } else if (FLAGS_heap_profile_time_interval > 0 ) { + int64 current_time = time(NULL); + if (current_time - last_dump_time >= + FLAGS_heap_profile_time_interval) { + snprintf(buf, sizeof(buf), "%" PRId64 " sec since the last dump", + current_time - last_dump_time); + need_to_dump = true; + last_dump_time = current_time; + } + } + if (need_to_dump) { + DumpProfileLocked(buf); + + last_dump_alloc = total.alloc_size; + last_dump_free = total.free_size; + if (inuse_bytes > high_water_mark) + high_water_mark = inuse_bytes; + } + } +} + +// Record an allocation in the profile. +static void RecordAlloc(const void* ptr, size_t bytes, int skip_count) { + // Take the stack trace outside the critical section. + void* stack[HeapProfileTable::kMaxStackDepth]; + int depth = HeapProfileTable::GetCallerStackTrace(skip_count + 1, stack); + SpinLockHolder l(&heap_lock); + if (is_on) { + heap_profile->RecordAlloc(ptr, bytes, depth, stack); + MaybeDumpProfileLocked(); + } +} + +// Record a deallocation in the profile. +static void RecordFree(const void* ptr) { + SpinLockHolder l(&heap_lock); + if (is_on) { + heap_profile->RecordFree(ptr); + MaybeDumpProfileLocked(); + } +} + +//---------------------------------------------------------------------- +// Allocation/deallocation hooks for MallocHook +//---------------------------------------------------------------------- + +// static +void NewHook(const void* ptr, size_t size) { + if (ptr != NULL) RecordAlloc(ptr, size, 0); +} + +// static +void DeleteHook(const void* ptr) { + if (ptr != NULL) RecordFree(ptr); +} + +// TODO(jandrews): Re-enable stack tracing +#ifdef TODO_REENABLE_STACK_TRACING +static void RawInfoStackDumper(const char* message, void*) { + RAW_LOG(INFO, "%.*s", static_cast(strlen(message) - 1), message); + // -1 is to chop the \n which will be added by RAW_LOG +} +#endif + +static void MmapHook(const void* result, const void* start, size_t size, + int prot, int flags, int fd, off_t offset) { + if (FLAGS_mmap_log) { // log it + // We use PRIxPTR not just '%p' to avoid deadlocks + // in pretty-printing of NULL as "nil". + // TODO(maxim): instead should use a safe snprintf reimplementation + RAW_LOG(INFO, + "mmap(start=0x%" PRIxPTR ", len=%zu, prot=0x%x, flags=0x%x, " + "fd=%d, offset=0x%x) = 0x%" PRIxPTR "", + (uintptr_t) start, size, prot, flags, fd, (unsigned int) offset, + (uintptr_t) result); +#ifdef TODO_REENABLE_STACK_TRACING + DumpStackTrace(1, RawInfoStackDumper, NULL); +#endif + } +} + +static void MremapHook(const void* result, const void* old_addr, + size_t old_size, size_t new_size, + int flags, const void* new_addr) { + if (FLAGS_mmap_log) { // log it + // We use PRIxPTR not just '%p' to avoid deadlocks + // in pretty-printing of NULL as "nil". + // TODO(maxim): instead should use a safe snprintf reimplementation + RAW_LOG(INFO, + "mremap(old_addr=0x%" PRIxPTR ", old_size=%zu, " + "new_size=%zu, flags=0x%x, new_addr=0x%" PRIxPTR ") = " + "0x%" PRIxPTR "", + (uintptr_t) old_addr, old_size, new_size, flags, + (uintptr_t) new_addr, (uintptr_t) result); +#ifdef TODO_REENABLE_STACK_TRACING + DumpStackTrace(1, RawInfoStackDumper, NULL); +#endif + } +} + +static void MunmapHook(const void* ptr, size_t size) { + if (FLAGS_mmap_log) { // log it + // We use PRIxPTR not just '%p' to avoid deadlocks + // in pretty-printing of NULL as "nil". + // TODO(maxim): instead should use a safe snprintf reimplementation + RAW_LOG(INFO, "munmap(start=0x%" PRIxPTR ", len=%zu)", + (uintptr_t) ptr, size); +#ifdef TODO_REENABLE_STACK_TRACING + DumpStackTrace(1, RawInfoStackDumper, NULL); +#endif + } +} + +static void SbrkHook(const void* result, ptrdiff_t increment) { + if (FLAGS_mmap_log) { // log it + RAW_LOG(INFO, "sbrk(inc=%zd) = 0x%" PRIxPTR "", + increment, (uintptr_t) result); +#ifdef TODO_REENABLE_STACK_TRACING + DumpStackTrace(1, RawInfoStackDumper, NULL); +#endif + } +} + +//---------------------------------------------------------------------- +// Starting/stopping/dumping +//---------------------------------------------------------------------- + +extern "C" void HeapProfilerStart(const char* prefix) { + SpinLockHolder l(&heap_lock); + + if (is_on) return; + + is_on = true; + + RAW_VLOG(0, "Starting tracking the heap"); + + // This should be done before the hooks are set up, since it should + // call new, and we want that to be accounted for correctly. + MallocExtension::Initialize(); + + if (FLAGS_only_mmap_profile) { + FLAGS_mmap_profile = true; + } + + if (FLAGS_mmap_profile) { + // Ask MemoryRegionMap to record all mmap, mremap, and sbrk + // call stack traces of at least size kMaxStackDepth: + MemoryRegionMap::Init(HeapProfileTable::kMaxStackDepth, + /* use_buckets */ true); + } + + if (FLAGS_mmap_log) { + // Install our hooks to do the logging: + RAW_CHECK(MallocHook::AddMmapHook(&MmapHook), ""); + RAW_CHECK(MallocHook::AddMremapHook(&MremapHook), ""); + RAW_CHECK(MallocHook::AddMunmapHook(&MunmapHook), ""); + RAW_CHECK(MallocHook::AddSbrkHook(&SbrkHook), ""); + } + + heap_profiler_memory = + LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena()); + + // Reserve space now for the heap profiler, so we can still write a + // heap profile even if the application runs out of memory. + global_profiler_buffer = + reinterpret_cast(ProfilerMalloc(kProfileBufferSize)); + + heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable))) + HeapProfileTable(ProfilerMalloc, ProfilerFree, FLAGS_mmap_profile); + + last_dump_alloc = 0; + last_dump_free = 0; + high_water_mark = 0; + last_dump_time = 0; + + // We do not reset dump_count so if the user does a sequence of + // HeapProfilerStart/HeapProfileStop, we will get a continuous + // sequence of profiles. + + if (FLAGS_only_mmap_profile == false) { + // Now set the hooks that capture new/delete and malloc/free. + RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); + RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); + } + + // Copy filename prefix + RAW_DCHECK(filename_prefix == NULL, ""); + const int prefix_length = strlen(prefix); + filename_prefix = reinterpret_cast(ProfilerMalloc(prefix_length + 1)); + memcpy(filename_prefix, prefix, prefix_length); + filename_prefix[prefix_length] = '\0'; +} + +extern "C" int IsHeapProfilerRunning() { + SpinLockHolder l(&heap_lock); + return is_on ? 1 : 0; // return an int, because C code doesn't have bool +} + +extern "C" void HeapProfilerStop() { + SpinLockHolder l(&heap_lock); + + if (!is_on) return; + + if (FLAGS_only_mmap_profile == false) { + // Unset our new/delete hooks, checking they were set: + RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), ""); + RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), ""); + } + if (FLAGS_mmap_log) { + // Restore mmap/sbrk hooks, checking that our hooks were set: + RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), ""); + RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), ""); + RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), ""); + RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), ""); + } + + // free profile + heap_profile->~HeapProfileTable(); + ProfilerFree(heap_profile); + heap_profile = NULL; + + // free output-buffer memory + ProfilerFree(global_profiler_buffer); + + // free prefix + ProfilerFree(filename_prefix); + filename_prefix = NULL; + + if (!LowLevelAlloc::DeleteArena(heap_profiler_memory)) { + RAW_LOG(FATAL, "Memory leak in HeapProfiler:"); + } + + if (FLAGS_mmap_profile) { + MemoryRegionMap::Shutdown(); + } + + is_on = false; +} + +extern "C" void HeapProfilerDump(const char *reason) { + SpinLockHolder l(&heap_lock); + if (is_on && !dumping) { + DumpProfileLocked(reason); + } +} + +// Signal handler that is registered when a user selectable signal +// number is defined in the environment variable HEAPPROFILESIGNAL. +static void HeapProfilerDumpSignal(int signal_number) { + (void)signal_number; + if (!heap_lock.TryLock()) { + return; + } + if (is_on && !dumping) { + DumpProfileLocked("signal"); + } + heap_lock.Unlock(); +} + + +//---------------------------------------------------------------------- +// Initialization/finalization code +//---------------------------------------------------------------------- + +// Initialization code +static void HeapProfilerInit() { + // Everything after this point is for setting up the profiler based on envvar + char fname[PATH_MAX]; + if (!GetUniquePathFromEnv("HEAPPROFILE", fname)) { + return; + } + // We do a uid check so we don't write out files in a setuid executable. +#ifdef HAVE_GETEUID + if (getuid() != geteuid()) { + RAW_LOG(WARNING, ("HeapProfiler: ignoring HEAPPROFILE because " + "program seems to be setuid\n")); + return; + } +#endif + + char *signal_number_str = getenv("HEAPPROFILESIGNAL"); + if (signal_number_str != NULL) { + long int signal_number = strtol(signal_number_str, NULL, 10); + intptr_t old_signal_handler = reinterpret_cast(signal(signal_number, HeapProfilerDumpSignal)); + if (old_signal_handler == reinterpret_cast(SIG_ERR)) { + RAW_LOG(FATAL, "Failed to set signal. Perhaps signal number %s is invalid\n", signal_number_str); + } else if (old_signal_handler == 0) { + RAW_LOG(INFO,"Using signal %d as heap profiling switch", signal_number); + } else { + RAW_LOG(FATAL, "Signal %d already in use\n", signal_number); + } + } + + HeapProfileTable::CleanupOldProfiles(fname); + + HeapProfilerStart(fname); +} + +// class used for finalization -- dumps the heap-profile at program exit +struct HeapProfileEndWriter { + ~HeapProfileEndWriter() { + char buf[128]; + if (heap_profile) { + const HeapProfileTable::Stats& total = heap_profile->total(); + const int64 inuse_bytes = total.alloc_size - total.free_size; + + if ((inuse_bytes >> 20) > 0) { + snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " MB in use"), + inuse_bytes >> 20); + } else if ((inuse_bytes >> 10) > 0) { + snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " kB in use"), + inuse_bytes >> 10); + } else { + snprintf(buf, sizeof(buf), ("Exiting, %" PRId64 " bytes in use"), + inuse_bytes); + } + } else { + snprintf(buf, sizeof(buf), ("Exiting")); + } + HeapProfilerDump(buf); + } +}; + +// We want to make sure tcmalloc is up and running before starting the profiler +static const TCMallocGuard tcmalloc_initializer; +REGISTER_MODULE_INITIALIZER(heapprofiler, HeapProfilerInit()); +static HeapProfileEndWriter heap_profile_end_writer; diff --git a/trunk/3rdparty/gperftools-2-fit/src/internal_logging.cc b/trunk/3rdparty/gperftools-2-fit/src/internal_logging.cc new file mode 100644 index 000000000..ca1c86ed7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/internal_logging.cc @@ -0,0 +1,192 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// Sanjay Ghemawat + +#include +#include "internal_logging.h" +#include // for va_end, va_start +#include // for vsnprintf, va_list, etc +#include // for abort +#include // for strlen, memcpy +#ifdef HAVE_UNISTD_H +#include // for write() +#endif + +#include +#include "base/logging.h" // for perftools_vsnprintf +#include "base/spinlock.h" // for SpinLockHolder, SpinLock + +// Variables for storing crash output. Allocated statically since we +// may not be able to heap-allocate while crashing. +static SpinLock crash_lock(base::LINKER_INITIALIZED); +static bool crashed = false; +static const int kStatsBufferSize = 16 << 10; +static char stats_buffer[kStatsBufferSize] = { 0 }; + +namespace tcmalloc { + +static void WriteMessage(const char* msg, int length) { + write(STDERR_FILENO, msg, length); +} + +void (*log_message_writer)(const char* msg, int length) = WriteMessage; + + +class Logger { + public: + bool Add(const LogItem& item); + bool AddStr(const char* str, int n); + bool AddNum(uint64_t num, int base); // base must be 10 or 16. + + static const int kBufSize = 200; + char* p_; + char* end_; + char buf_[kBufSize]; +}; + +void Log(LogMode mode, const char* filename, int line, + LogItem a, LogItem b, LogItem c, LogItem d) { + Logger state; + state.p_ = state.buf_; + state.end_ = state.buf_ + sizeof(state.buf_); + state.AddStr(filename, strlen(filename)) + && state.AddStr(":", 1) + && state.AddNum(line, 10) + && state.AddStr("]", 1) + && state.Add(a) + && state.Add(b) + && state.Add(c) + && state.Add(d); + + // Teminate with newline + if (state.p_ >= state.end_) { + state.p_ = state.end_ - 1; + } + *state.p_ = '\n'; + state.p_++; + + int msglen = state.p_ - state.buf_; + if (mode == kLog) { + (*log_message_writer)(state.buf_, msglen); + return; + } + + bool first_crash = false; + { + SpinLockHolder l(&crash_lock); + if (!crashed) { + crashed = true; + first_crash = true; + } + } + + (*log_message_writer)(state.buf_, msglen); + if (first_crash && mode == kCrashWithStats) { + MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize); + (*log_message_writer)(stats_buffer, strlen(stats_buffer)); + } + + abort(); +} + +bool Logger::Add(const LogItem& item) { + // Separate items with spaces + if (p_ < end_) { + *p_ = ' '; + p_++; + } + + switch (item.tag_) { + case LogItem::kStr: + return AddStr(item.u_.str, strlen(item.u_.str)); + case LogItem::kUnsigned: + return AddNum(item.u_.unum, 10); + case LogItem::kSigned: + if (item.u_.snum < 0) { + // The cast to uint64_t is intentionally before the negation + // so that we do not attempt to negate -2^63. + return AddStr("-", 1) + && AddNum(- static_cast(item.u_.snum), 10); + } else { + return AddNum(static_cast(item.u_.snum), 10); + } + case LogItem::kPtr: + return AddStr("0x", 2) + && AddNum(reinterpret_cast(item.u_.ptr), 16); + default: + return false; + } +} + +bool Logger::AddStr(const char* str, int n) { + if (end_ - p_ < n) { + return false; + } else { + memcpy(p_, str, n); + p_ += n; + return true; + } +} + +bool Logger::AddNum(uint64_t num, int base) { + static const char kDigits[] = "0123456789abcdef"; + char space[22]; // more than enough for 2^64 in smallest supported base (10) + char* end = space + sizeof(space); + char* pos = end; + do { + pos--; + *pos = kDigits[num % base]; + num /= base; + } while (num > 0 && pos > space); + return AddStr(pos, end - pos); +} + +} // end tcmalloc namespace + +void TCMalloc_Printer::printf(const char* format, ...) { + if (left_ > 0) { + va_list ap; + va_start(ap, format); + const int r = perftools_vsnprintf(buf_, left_, format, ap); + va_end(ap); + if (r < 0) { + // Perhaps an old glibc that returns -1 on truncation? + left_ = 0; + } else if (r > left_) { + // Truncation + left_ = 0; + } else { + left_ -= r; + buf_ += r; + } + } +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/internal_logging.h b/trunk/3rdparty/gperftools-2-fit/src/internal_logging.h new file mode 100644 index 000000000..1b0468e0d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/internal_logging.h @@ -0,0 +1,144 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Internal logging and related utility routines. + +#ifndef TCMALLOC_INTERNAL_LOGGING_H_ +#define TCMALLOC_INTERNAL_LOGGING_H_ + +#include +#include // for size_t +#if defined HAVE_STDINT_H +#include +#elif defined HAVE_INTTYPES_H +#include +#else +#include +#endif + +//------------------------------------------------------------------- +// Utility routines +//------------------------------------------------------------------- + +// Safe logging helper: we write directly to the stderr file +// descriptor and avoid FILE buffering because that may invoke +// malloc(). +// +// Example: +// Log(kLog, __FILE__, __LINE__, "error", bytes); + +namespace tcmalloc { +enum LogMode { + kLog, // Just print the message + kCrash, // Print the message and crash + kCrashWithStats // Print the message, some stats, and crash +}; + +class Logger; + +// A LogItem holds any of the argument types that can be passed to Log() +class LogItem { + public: + LogItem() : tag_(kEnd) { } + LogItem(const char* v) : tag_(kStr) { u_.str = v; } + LogItem(int v) : tag_(kSigned) { u_.snum = v; } + LogItem(long v) : tag_(kSigned) { u_.snum = v; } + LogItem(long long v) : tag_(kSigned) { u_.snum = v; } + LogItem(unsigned int v) : tag_(kUnsigned) { u_.unum = v; } + LogItem(unsigned long v) : tag_(kUnsigned) { u_.unum = v; } + LogItem(unsigned long long v) : tag_(kUnsigned) { u_.unum = v; } + LogItem(const void* v) : tag_(kPtr) { u_.ptr = v; } + private: + friend class Logger; + enum Tag { + kStr, + kSigned, + kUnsigned, + kPtr, + kEnd + }; + Tag tag_; + union { + const char* str; + const void* ptr; + int64_t snum; + uint64_t unum; + } u_; +}; + +extern PERFTOOLS_DLL_DECL void Log(LogMode mode, const char* filename, int line, + LogItem a, LogItem b = LogItem(), + LogItem c = LogItem(), LogItem d = LogItem()); + +// Tests can override this function to collect logging messages. +extern PERFTOOLS_DLL_DECL void (*log_message_writer)(const char* msg, int length); + +} // end tcmalloc namespace + +// Like assert(), but executed even in NDEBUG mode +#undef CHECK_CONDITION +#define CHECK_CONDITION(cond) \ +do { \ + if (!(cond)) { \ + ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond); \ + } \ +} while (0) + +// Our own version of assert() so we can avoid hanging by trying to do +// all kinds of goofy printing while holding the malloc lock. +#ifndef NDEBUG +#define ASSERT(cond) CHECK_CONDITION(cond) +#else +#define ASSERT(cond) ((void) 0) +#endif + +// Print into buffer +class TCMalloc_Printer { + private: + char* buf_; // Where should we write next + int left_; // Space left in buffer (including space for \0) + + public: + // REQUIRES: "length > 0" + TCMalloc_Printer(char* buf, int length) : buf_(buf), left_(length) { + buf[0] = '\0'; + } + + void printf(const char* format, ...) +#ifdef HAVE___ATTRIBUTE__ + __attribute__ ((__format__ (__printf__, 2, 3))) +#endif +; +}; + +#endif // TCMALLOC_INTERNAL_LOGGING_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/libc_override.h b/trunk/3rdparty/gperftools-2-fit/src/libc_override.h new file mode 100644 index 000000000..c981c3d59 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/libc_override.h @@ -0,0 +1,99 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 .h file imports the code that causes tcmalloc to override libc +// versions of malloc/free/new/delete/etc. That is, it provides the +// logic that makes it so calls to malloc(10) go through tcmalloc, +// rather than the default (libc) malloc. +// +// This file also provides a method: ReplaceSystemAlloc(), that every +// libc_override_*.h file it #includes is required to provide. This +// is called when first setting up tcmalloc -- that is, when a global +// constructor in tcmalloc.cc is executed -- to do any initialization +// work that may be required for this OS. (Note we cannot entirely +// control when tcmalloc is initialized, and the system may do some +// mallocs and frees before this routine is called.) It may be a +// noop. +// +// Every libc has its own way of doing this, and sometimes the compiler +// matters too, so we have a different file for each libc, and often +// for different compilers and OS's. + +#ifndef TCMALLOC_LIBC_OVERRIDE_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_INL_H_ + +#include +#ifdef HAVE_FEATURES_H +#include // for __GLIBC__ +#endif +#include + +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#define CPP_NOTHROW noexcept +#define CPP_BADALLOC +#else +#define CPP_NOTHROW throw() +#define CPP_BADALLOC throw(std::bad_alloc) +#endif + +static void ReplaceSystemAlloc(); // defined in the .h files below + +// For windows, there are two ways to get tcmalloc. If we're +// patching, then src/windows/patch_function.cc will do the necessary +// overriding here. Otherwise, we doing the 'redefine' trick, where +// we remove malloc/new/etc from mscvcrt.dll, and just need to define +// them now. +#if defined(_WIN32) && defined(WIN32_DO_PATCHING) +void PatchWindowsFunctions(); // in src/windows/patch_function.cc +static void ReplaceSystemAlloc() { PatchWindowsFunctions(); } + +#elif defined(_WIN32) && !defined(WIN32_DO_PATCHING) +#include "libc_override_redefine.h" + +#elif defined(__APPLE__) +#include "libc_override_osx.h" + +#elif defined(__GLIBC__) +#include "libc_override_glibc.h" + +// Not all gcc systems necessarily support weak symbols, but all the +// ones I know of do, so for now just assume they all do. +#elif defined(__GNUC__) +#include "libc_override_gcc_and_weak.h" + +#else +#error Need to add support for your libc/OS here + +#endif + +#endif // TCMALLOC_LIBC_OVERRIDE_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/libc_override_gcc_and_weak.h b/trunk/3rdparty/gperftools-2-fit/src/libc_override_gcc_and_weak.h new file mode 100644 index 000000000..bb99b6900 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/libc_override_gcc_and_weak.h @@ -0,0 +1,244 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 +// +// Used to override malloc routines on systems that define the +// memory allocation routines to be weak symbols in their libc +// (almost all unix-based systems are like this), on gcc, which +// suppports the 'alias' attribute. + +#ifndef TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ + +#ifdef HAVE_SYS_CDEFS_H +#include // for __THROW +#endif +#include + +#include "getenv_safe.h" // TCMallocGetenvSafe +#include "base/commandlineflags.h" + +#ifndef __THROW // I guess we're not on a glibc-like system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +#ifndef __GNUC__ +# error libc_override_gcc_and_weak.h is for gcc distributions only. +#endif + +#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn), used)) + +void* operator new(size_t size) CPP_BADALLOC ALIAS(tc_new); +void operator delete(void* p) CPP_NOTHROW ALIAS(tc_delete); +void* operator new[](size_t size) CPP_BADALLOC ALIAS(tc_newarray); +void operator delete[](void* p) CPP_NOTHROW ALIAS(tc_deletearray); +void* operator new(size_t size, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_new_nothrow); +void* operator new[](size_t size, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_newarray_nothrow); +void operator delete(void* p, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_delete_nothrow); +void operator delete[](void* p, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_deletearray_nothrow); + +#if defined(ENABLE_SIZED_DELETE) + +void operator delete(void *p, size_t size) CPP_NOTHROW + ALIAS(tc_delete_sized); +void operator delete[](void *p, size_t size) CPP_NOTHROW + ALIAS(tc_deletearray_sized); + +#elif defined(ENABLE_DYNAMIC_SIZED_DELETE) && \ + (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + +static void delegate_sized_delete(void *p, size_t s) { + (operator delete)(p); +} + +static void delegate_sized_deletearray(void *p, size_t s) { + (operator delete[])(p); +} + +extern "C" __attribute__((weak)) +int tcmalloc_sized_delete_enabled(void); + +static bool sized_delete_enabled(void) { + if (tcmalloc_sized_delete_enabled != 0) { + return !!tcmalloc_sized_delete_enabled(); + } + + const char *flag = TCMallocGetenvSafe("TCMALLOC_ENABLE_SIZED_DELETE"); + return tcmalloc::commandlineflags::StringToBool(flag, false); +} + +extern "C" { + +static void *resolve_delete_sized(void) { + if (sized_delete_enabled()) { + return reinterpret_cast(tc_delete_sized); + } + return reinterpret_cast(delegate_sized_delete); +} + +static void *resolve_deletearray_sized(void) { + if (sized_delete_enabled()) { + return reinterpret_cast(tc_deletearray_sized); + } + return reinterpret_cast(delegate_sized_deletearray); +} + +} + +void operator delete(void *p, size_t size) CPP_NOTHROW + __attribute__((ifunc("resolve_delete_sized"))); +void operator delete[](void *p, size_t size) CPP_NOTHROW + __attribute__((ifunc("resolve_deletearray_sized"))); + +#else /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */ + +void operator delete(void *p, size_t size) CPP_NOTHROW + ALIAS(tc_delete_sized); +void operator delete[](void *p, size_t size) CPP_NOTHROW + ALIAS(tc_deletearray_sized); + +#endif /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */ + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + +void* operator new(size_t size, std::align_val_t al) + ALIAS(tc_new_aligned); +void operator delete(void* p, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_delete_aligned); +void* operator new[](size_t size, std::align_val_t al) + ALIAS(tc_newarray_aligned); +void operator delete[](void* p, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_deletearray_aligned); +void* operator new(size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_new_aligned_nothrow); +void* operator new[](size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_newarray_aligned_nothrow); +void operator delete(void* p, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_delete_aligned_nothrow); +void operator delete[](void* p, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW + ALIAS(tc_deletearray_aligned_nothrow); + +#if defined(ENABLE_SIZED_DELETE) + +void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_delete_sized_aligned); +void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_deletearray_sized_aligned); + +#else /* defined(ENABLE_SIZED_DELETE) */ + +#if defined(ENABLE_DYNAMIC_SIZED_DELETE) && \ + (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + +static void delegate_sized_aligned_delete(void *p, size_t s, std::align_val_t al) { + (operator delete)(p, al); +} + +static void delegate_sized_aligned_deletearray(void *p, size_t s, std::align_val_t al) { + (operator delete[])(p, al); +} + +extern "C" { + +static void *resolve_delete_sized_aligned(void) { + if (sized_delete_enabled()) { + return reinterpret_cast(tc_delete_sized_aligned); + } + return reinterpret_cast(delegate_sized_aligned_delete); +} + +static void *resolve_deletearray_sized_aligned(void) { + if (sized_delete_enabled()) { + return reinterpret_cast(tc_deletearray_sized_aligned); + } + return reinterpret_cast(delegate_sized_aligned_deletearray); +} + +} + +void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW + __attribute__((ifunc("resolve_delete_sized_aligned"))); +void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW + __attribute__((ifunc("resolve_deletearray_sized_aligned"))); + +#else /* defined(ENABLE_DYN_SIZED_DELETE) */ + +void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_delete_sized_aligned); +void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW + ALIAS(tc_deletearray_sized_aligned); + +#endif /* defined(ENABLE_DYN_SIZED_DELETE) */ + +#endif /* defined(ENABLE_SIZED_DELETE) */ + +#endif /* defined(ENABLE_ALIGNED_NEW_DELETE) */ + +extern "C" { + void* malloc(size_t size) __THROW ALIAS(tc_malloc); + void free(void* ptr) __THROW ALIAS(tc_free); + void* realloc(void* ptr, size_t size) __THROW ALIAS(tc_realloc); + void* calloc(size_t n, size_t size) __THROW ALIAS(tc_calloc); + void cfree(void* ptr) __THROW ALIAS(tc_cfree); + void* memalign(size_t align, size_t s) __THROW ALIAS(tc_memalign); + void* aligned_alloc(size_t align, size_t s) __THROW ALIAS(tc_memalign); + void* valloc(size_t size) __THROW ALIAS(tc_valloc); + void* pvalloc(size_t size) __THROW ALIAS(tc_pvalloc); + int posix_memalign(void** r, size_t a, size_t s) __THROW + ALIAS(tc_posix_memalign); +#ifndef __UCLIBC__ + void malloc_stats(void) __THROW ALIAS(tc_malloc_stats); +#endif + int mallopt(int cmd, int value) __THROW ALIAS(tc_mallopt); +#ifdef HAVE_STRUCT_MALLINFO + struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo); +#endif + size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size); +#if defined(__ANDROID__) + size_t malloc_usable_size(const void* p) __THROW + ALIAS(tc_malloc_size); +#else + size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size); +#endif +} // extern "C" + +#undef ALIAS + +// No need to do anything at tcmalloc-registration time: we do it all +// via overriding weak symbols (at link time). +static void ReplaceSystemAlloc() { } + +#endif // TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/libc_override_glibc.h b/trunk/3rdparty/gperftools-2-fit/src/libc_override_glibc.h new file mode 100644 index 000000000..32692132a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/libc_override_glibc.h @@ -0,0 +1,92 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 +// +// Used to override malloc routines on systems that are using glibc. + +#ifndef TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ + +#include +#include // for __GLIBC__ +#include + +#ifndef __GLIBC__ +# error libc_override_glibc.h is for glibc distributions only. +#endif + +// In glibc, the memory-allocation methods are weak symbols, so we can +// just override them with our own. If we're using gcc, we can use +// __attribute__((alias)) to do the overriding easily (exception: +// Mach-O, which doesn't support aliases). Otherwise we have to use a +// function call. +#if !defined(__GNUC__) || defined(__MACH__) + +// This also defines ReplaceSystemAlloc(). +# include "libc_override_redefine.h" // defines functions malloc()/etc + +#else // #if !defined(__GNUC__) || defined(__MACH__) + +// If we get here, we're a gcc system, so do all the overriding we do +// with gcc. This does the overriding of all the 'normal' memory +// allocation. This also defines ReplaceSystemAlloc(). +# include "libc_override_gcc_and_weak.h" + +// We also have to do some glibc-specific overriding. Some library +// routines on RedHat 9 allocate memory using malloc() and free it +// using __libc_free() (or vice-versa). Since we provide our own +// implementations of malloc/free, we need to make sure that the +// __libc_XXX variants (defined as part of glibc) also point to the +// same implementations. Since it only matters for redhat, we +// do it inside the gcc #ifdef, since redhat uses gcc. +// TODO(csilvers): only do this if we detect we're an old enough glibc? + +#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn))) +extern "C" { + void* __libc_malloc(size_t size) ALIAS(tc_malloc); + void __libc_free(void* ptr) ALIAS(tc_free); + void* __libc_realloc(void* ptr, size_t size) ALIAS(tc_realloc); + void* __libc_calloc(size_t n, size_t size) ALIAS(tc_calloc); + void __libc_cfree(void* ptr) ALIAS(tc_cfree); + void* __libc_memalign(size_t align, size_t s) ALIAS(tc_memalign); + void* __libc_valloc(size_t size) ALIAS(tc_valloc); + void* __libc_pvalloc(size_t size) ALIAS(tc_pvalloc); + int __posix_memalign(void** r, size_t a, size_t s) ALIAS(tc_posix_memalign); +} // extern "C" +#undef ALIAS + +#endif // #if defined(__GNUC__) && !defined(__MACH__) + +// No need to write ReplaceSystemAlloc(); one of the #includes above +// did it for us. + +#endif // TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/libc_override_osx.h b/trunk/3rdparty/gperftools-2-fit/src/libc_override_osx.h new file mode 100644 index 000000000..9d5d61150 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/libc_override_osx.h @@ -0,0 +1,308 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 +// +// Used to override malloc routines on OS X systems. We use the +// malloc-zone functionality built into OS X to register our malloc +// routine. +// +// 1) We used to use the normal 'override weak libc malloc/etc' +// technique for OS X. This is not optimal because mach does not +// support the 'alias' attribute, so we had to have forwarding +// functions. It also does not work very well with OS X shared +// libraries (dylibs) -- in general, the shared libs don't use +// tcmalloc unless run with the DYLD_FORCE_FLAT_NAMESPACE envvar. +// +// 2) Another approach would be to use an interposition array: +// static const interpose_t interposers[] __attribute__((section("__DATA, __interpose"))) = { +// { (void *)tc_malloc, (void *)malloc }, +// { (void *)tc_free, (void *)free }, +// }; +// This requires the user to set the DYLD_INSERT_LIBRARIES envvar, so +// is not much better. +// +// 3) Registering a new malloc zone avoids all these issues: +// http://www.opensource.apple.com/source/Libc/Libc-583/include/malloc/malloc.h +// http://www.opensource.apple.com/source/Libc/Libc-583/gen/malloc.c +// If we make tcmalloc the default malloc zone (undocumented but +// possible) then all new allocs use it, even those in shared +// libraries. Allocs done before tcmalloc was installed, or in libs +// that aren't using tcmalloc for some reason, will correctly go +// through the malloc-zone interface when free-ing, and will pick up +// the libc free rather than tcmalloc free. So it should "never" +// cause a crash (famous last words). +// +// 4) The routines one must define for one's own malloc have changed +// between OS X versions. This requires some hoops on our part, but +// is only really annoying when it comes to posix_memalign. The right +// behavior there depends on what OS version tcmalloc was compiled on, +// but also what OS version the program is running on. For now, we +// punt and don't implement our own posix_memalign. Apps that really +// care can use tc_posix_memalign directly. + +#ifndef TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ +#define TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ + +#include +#ifdef HAVE_FEATURES_H +#include +#endif +#include + +#if !defined(__APPLE__) +# error libc_override_glibc-osx.h is for OS X distributions only. +#endif + +#include +#include + +namespace tcmalloc { + void CentralCacheLockAll(); + void CentralCacheUnlockAll(); +} + +// from AvailabilityMacros.h +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +extern "C" { + // This function is only available on 10.6 (and later) but the + // LibSystem headers do not use AvailabilityMacros.h to handle weak + // importing automatically. This prototype is a copy of the one in + // with the WEAK_IMPORT_ATTRBIUTE added. + extern malloc_zone_t *malloc_default_purgeable_zone(void) + WEAK_IMPORT_ATTRIBUTE; +} +#endif + +// We need to provide wrappers around all the libc functions. +namespace { +size_t mz_size(malloc_zone_t* zone, const void* ptr) { + if (MallocExtension::instance()->GetOwnership(ptr) != MallocExtension::kOwned) + return 0; // malloc_zone semantics: return 0 if we don't own the memory + + // TODO(csilvers): change this method to take a const void*, one day. + return MallocExtension::instance()->GetAllocatedSize(const_cast(ptr)); +} + +void* mz_malloc(malloc_zone_t* zone, size_t size) { + return tc_malloc(size); +} + +void* mz_calloc(malloc_zone_t* zone, size_t num_items, size_t size) { + return tc_calloc(num_items, size); +} + +void* mz_valloc(malloc_zone_t* zone, size_t size) { + return tc_valloc(size); +} + +void mz_free(malloc_zone_t* zone, void* ptr) { + return tc_free(ptr); +} + +void* mz_realloc(malloc_zone_t* zone, void* ptr, size_t size) { + return tc_realloc(ptr, size); +} + +void* mz_memalign(malloc_zone_t* zone, size_t align, size_t size) { + return tc_memalign(align, size); +} + +void mz_destroy(malloc_zone_t* zone) { + // A no-op -- we will not be destroyed! +} + +// malloc_introspection callbacks. I'm not clear on what all of these do. +kern_return_t mi_enumerator(task_t task, void *, + unsigned type_mask, vm_address_t zone_address, + memory_reader_t reader, + vm_range_recorder_t recorder) { + // Should enumerate all the pointers we have. Seems like a lot of work. + return KERN_FAILURE; +} + +size_t mi_good_size(malloc_zone_t *zone, size_t size) { + // I think it's always safe to return size, but we maybe could do better. + return size; +} + +boolean_t mi_check(malloc_zone_t *zone) { + return MallocExtension::instance()->VerifyAllMemory(); +} + +void mi_print(malloc_zone_t *zone, boolean_t verbose) { + int bufsize = 8192; + if (verbose) + bufsize = 102400; // I picked this size arbitrarily + char* buffer = new char[bufsize]; + MallocExtension::instance()->GetStats(buffer, bufsize); + fprintf(stdout, "%s", buffer); + delete[] buffer; +} + +void mi_log(malloc_zone_t *zone, void *address) { + // I don't think we support anything like this +} + +void mi_force_lock(malloc_zone_t *zone) { + tcmalloc::CentralCacheLockAll(); +} + +void mi_force_unlock(malloc_zone_t *zone) { + tcmalloc::CentralCacheUnlockAll(); +} + +void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + // TODO(csilvers): figure out how to fill these out + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +boolean_t mi_zone_locked(malloc_zone_t *zone) { + return false; // Hopefully unneeded by us! +} + +} // unnamed namespace + +// OS X doesn't have pvalloc, cfree, malloc_statc, etc, so we can just +// define our own. :-) OS X supplies posix_memalign in some versions +// but not others, either strongly or weakly linked, in a way that's +// difficult enough to code to correctly, that I just don't try to +// support either memalign() or posix_memalign(). If you need them +// and are willing to code to tcmalloc, you can use tc_posix_memalign(). +extern "C" { + void cfree(void* p) { tc_cfree(p); } + void* pvalloc(size_t s) { return tc_pvalloc(s); } + void malloc_stats(void) { tc_malloc_stats(); } + int mallopt(int cmd, int v) { return tc_mallopt(cmd, v); } + // No struct mallinfo on OS X, so don't define mallinfo(). + // An alias for malloc_size(), which OS X defines. + size_t malloc_usable_size(void* p) { return tc_malloc_size(p); } +} // extern "C" + +static malloc_zone_t *get_default_zone() { + malloc_zone_t **zones = NULL; + unsigned int num_zones = 0; + + /* + * On OSX 10.12, malloc_default_zone returns a special zone that is not + * present in the list of registered zones. That zone uses a "lite zone" + * if one is present (apparently enabled when malloc stack logging is + * enabled), or the first registered zone otherwise. In practice this + * means unless malloc stack logging is enabled, the first registered + * zone is the default. + * So get the list of zones to get the first one, instead of relying on + * malloc_default_zone. + */ + if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones, + &num_zones)) { + /* Reset the value in case the failure happened after it was set. */ + num_zones = 0; + } + + if (num_zones) + return zones[0]; + + return malloc_default_zone(); +} + + +static void ReplaceSystemAlloc() { + static malloc_introspection_t tcmalloc_introspection; + memset(&tcmalloc_introspection, 0, sizeof(tcmalloc_introspection)); + + tcmalloc_introspection.enumerator = &mi_enumerator; + tcmalloc_introspection.good_size = &mi_good_size; + tcmalloc_introspection.check = &mi_check; + tcmalloc_introspection.print = &mi_print; + tcmalloc_introspection.log = &mi_log; + tcmalloc_introspection.force_lock = &mi_force_lock; + tcmalloc_introspection.force_unlock = &mi_force_unlock; + + static malloc_zone_t tcmalloc_zone; + memset(&tcmalloc_zone, 0, sizeof(malloc_zone_t)); + + // Start with a version 4 zone which is used for OS X 10.4 and 10.5. + tcmalloc_zone.version = 4; + tcmalloc_zone.zone_name = "tcmalloc"; + tcmalloc_zone.size = &mz_size; + tcmalloc_zone.malloc = &mz_malloc; + tcmalloc_zone.calloc = &mz_calloc; + tcmalloc_zone.valloc = &mz_valloc; + tcmalloc_zone.free = &mz_free; + tcmalloc_zone.realloc = &mz_realloc; + tcmalloc_zone.destroy = &mz_destroy; + tcmalloc_zone.batch_malloc = NULL; + tcmalloc_zone.batch_free = NULL; + tcmalloc_zone.introspect = &tcmalloc_introspection; + + // from AvailabilityMacros.h +#if defined(MAC_OS_X_VERSION_10_6) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + // Switch to version 6 on OSX 10.6 to support memalign. + tcmalloc_zone.version = 6; + tcmalloc_zone.free_definite_size = NULL; + tcmalloc_zone.memalign = &mz_memalign; + tcmalloc_introspection.zone_locked = &mi_zone_locked; + + // Request the default purgable zone to force its creation. The + // current default zone is registered with the purgable zone for + // doing tiny and small allocs. Sadly, it assumes that the default + // zone is the szone implementation from OS X and will crash if it + // isn't. By creating the zone now, this will be true and changing + // the default zone won't cause a problem. This only needs to + // happen when actually running on OS X 10.6 and higher (note the + // ifdef above only checks if we were *compiled* with 10.6 or + // higher; at runtime we have to check if this symbol is defined.) + if (malloc_default_purgeable_zone) { + malloc_default_purgeable_zone(); + } +#endif + + // Register the tcmalloc zone. At this point, it will not be the + // default zone. + malloc_zone_register(&tcmalloc_zone); + + // Unregister and reregister the default zone. Unregistering swaps + // the specified zone with the last one registered which for the + // default zone makes the more recently registered zone the default + // zone. The default zone is then re-registered to ensure that + // allocations made from it earlier will be handled correctly. + // Things are not guaranteed to work that way, but it's how they work now. + malloc_zone_t *default_zone = get_default_zone(); + malloc_zone_unregister(default_zone); + malloc_zone_register(default_zone); +} + +#endif // TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/libc_override_redefine.h b/trunk/3rdparty/gperftools-2-fit/src/libc_override_redefine.h new file mode 100644 index 000000000..4d61b25a9 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/libc_override_redefine.h @@ -0,0 +1,131 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 +// +// Used on systems that don't have their own definition of +// malloc/new/etc. (Typically this will be a windows msvcrt.dll that +// has been edited to remove the definitions.) We can just define our +// own as normal functions. +// +// This should also work on systems were all the malloc routines are +// defined as weak symbols, and there's no support for aliasing. + +#ifndef TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ +#define TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ + +void* operator new(size_t size) { return tc_new(size); } +void operator delete(void* p) CPP_NOTHROW { tc_delete(p); } +void* operator new[](size_t size) { return tc_newarray(size); } +void operator delete[](void* p) CPP_NOTHROW { tc_deletearray(p); } +void* operator new(size_t size, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_new_nothrow(size, nt); +} +void* operator new[](size_t size, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_newarray_nothrow(size, nt); +} +void operator delete(void* ptr, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_delete_nothrow(ptr, nt); +} +void operator delete[](void* ptr, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_deletearray_nothrow(ptr, nt); +} + +#ifdef ENABLE_SIZED_DELETE +void operator delete(void* p, size_t s) CPP_NOTHROW { tc_delete_sized(p, s); } +void operator delete[](void* p, size_t s) CPP_NOTHROW{ tc_deletearray_sized(p, s);} +#endif + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + +void* operator new(size_t size, std::align_val_t al) { + return tc_new_aligned(size, al); +} +void operator delete(void* p, std::align_val_t al) CPP_NOTHROW { + tc_delete_aligned(p, al); +} +void* operator new[](size_t size, std::align_val_t al) { + return tc_newarray_aligned(size, al); +} +void operator delete[](void* p, std::align_val_t al) CPP_NOTHROW { + tc_deletearray_aligned(p, al); +} +void* operator new(size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_new_aligned_nothrow(size, al, nt); +} +void* operator new[](size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_newarray_aligned_nothrow(size, al, nt); +} +void operator delete(void* ptr, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_delete_aligned_nothrow(ptr, al, nt); +} +void operator delete[](void* ptr, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW { + return tc_deletearray_aligned_nothrow(ptr, al, nt); +} + +#ifdef ENABLE_SIZED_DELETE +void operator delete(void* p, size_t s, std::align_val_t al) CPP_NOTHROW { + tc_delete_sized_aligned(p, s, al); +} +void operator delete[](void* p, size_t s, std::align_val_t al) CPP_NOTHROW { + tc_deletearray_sized_aligned(p, s, al); +} +#endif + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + +extern "C" { + void* malloc(size_t s) { return tc_malloc(s); } + void free(void* p) { tc_free(p); } + void* realloc(void* p, size_t s) { return tc_realloc(p, s); } + void* calloc(size_t n, size_t s) { return tc_calloc(n, s); } + void cfree(void* p) { tc_cfree(p); } + void* memalign(size_t a, size_t s) { return tc_memalign(a, s); } + void* aligned_alloc(size_t a, size_t s) { return tc_memalign(a, s); } + void* valloc(size_t s) { return tc_valloc(s); } + void* pvalloc(size_t s) { return tc_pvalloc(s); } + int posix_memalign(void** r, size_t a, size_t s) { + return tc_posix_memalign(r, a, s); + } + void malloc_stats(void) { tc_malloc_stats(); } + int mallopt(int cmd, int v) { return tc_mallopt(cmd, v); } +#ifdef HAVE_STRUCT_MALLINFO + struct mallinfo mallinfo(void) { return tc_mallinfo(); } +#endif + size_t malloc_size(void* p) { return tc_malloc_size(p); } + size_t malloc_usable_size(void* p) { return tc_malloc_size(p); } +} // extern "C" + +// No need to do anything at tcmalloc-registration time: we do it all +// via overriding weak symbols (at link time). +static void ReplaceSystemAlloc() { } + +#endif // TCMALLOC_LIBC_OVERRIDE_REDEFINE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/linked_list.h b/trunk/3rdparty/gperftools-2-fit/src/linked_list.h new file mode 100644 index 000000000..f25b6f890 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/linked_list.h @@ -0,0 +1,115 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat +// +// Some very basic linked list functions for dealing with using void * as +// storage. + +#ifndef TCMALLOC_LINKED_LIST_H_ +#define TCMALLOC_LINKED_LIST_H_ + +#include + +namespace tcmalloc { + +inline void *SLL_Next(void *t) { + return *(reinterpret_cast(t)); +} + +inline void SLL_SetNext(void *t, void *n) { + *(reinterpret_cast(t)) = n; +} + +inline void SLL_Push(void **list, void *element) { + void *next = *list; + *list = element; + SLL_SetNext(element, next); +} + +inline void *SLL_Pop(void **list) { + void *result = *list; + *list = SLL_Next(*list); + return result; +} + +inline bool SLL_TryPop(void **list, void **rv) { + void *result = *list; + if (!result) { + return false; + } + void *next = SLL_Next(*list); + *list = next; + *rv = result; + return true; +} + +// Remove N elements from a linked list to which head points. head will be +// modified to point to the new head. start and end will point to the first +// and last nodes of the range. Note that end will point to NULL after this +// function is called. +inline void SLL_PopRange(void **head, int N, void **start, void **end) { + if (N == 0) { + *start = NULL; + *end = NULL; + return; + } + + void *tmp = *head; + for (int i = 1; i < N; ++i) { + tmp = SLL_Next(tmp); + } + + *start = *head; + *end = tmp; + *head = SLL_Next(tmp); + // Unlink range from list. + SLL_SetNext(tmp, NULL); +} + +inline void SLL_PushRange(void **head, void *start, void *end) { + if (!start) return; + SLL_SetNext(end, *head); + *head = start; +} + +inline size_t SLL_Size(void *head) { + int count = 0; + while (head) { + count++; + head = SLL_Next(head); + } + return count; +} + +} // namespace tcmalloc + +#endif // TCMALLOC_LINKED_LIST_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/malloc_extension.cc b/trunk/3rdparty/gperftools-2-fit/src/malloc_extension.cc new file mode 100644 index 000000000..68cb98aeb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/malloc_extension.cc @@ -0,0 +1,388 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat + +#include +#include +#include +#include +#if defined HAVE_STDINT_H +#include +#elif defined HAVE_INTTYPES_H +#include +#else +#include +#endif +#include +#include "base/dynamic_annotations.h" +#include "base/sysinfo.h" // for FillProcSelfMaps +#ifndef NO_HEAP_CHECK +#include "gperftools/heap-checker.h" +#endif +#include "gperftools/malloc_extension.h" +#include "gperftools/malloc_extension_c.h" +#include "maybe_threads.h" +#include "base/googleinit.h" + +using std::string; +using std::vector; + +static void DumpAddressMap(string* result) { + *result += "\nMAPPED_LIBRARIES:\n"; + // We keep doubling until we get a fit + const size_t old_resultlen = result->size(); + for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) { + result->resize(old_resultlen + amap_size); + bool wrote_all = false; + const int bytes_written = + tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size, + &wrote_all); + if (wrote_all) { // we fit! + (*result)[old_resultlen + bytes_written] = '\0'; + result->resize(old_resultlen + bytes_written); + return; + } + } + result->reserve(old_resultlen); // just don't print anything +} + +// Note: this routine is meant to be called before threads are spawned. +void MallocExtension::Initialize() { + static bool initialize_called = false; + + if (initialize_called) return; + initialize_called = true; + +#ifdef __GLIBC__ + // GNU libc++ versions 3.3 and 3.4 obey the environment variables + // GLIBCPP_FORCE_NEW and GLIBCXX_FORCE_NEW respectively. Setting + // one of these variables forces the STL default allocator to call + // new() or delete() for each allocation or deletion. Otherwise + // the STL allocator tries to avoid the high cost of doing + // allocations by pooling memory internally. However, tcmalloc + // does allocations really fast, especially for the types of small + // items one sees in STL, so it's better off just using us. + // TODO: control whether we do this via an environment variable? + setenv("GLIBCPP_FORCE_NEW", "1", false /* no overwrite*/); + setenv("GLIBCXX_FORCE_NEW", "1", false /* no overwrite*/); + + // Now we need to make the setenv 'stick', which it may not do since + // the env is flakey before main() is called. But luckily stl only + // looks at this env var the first time it tries to do an alloc, and + // caches what it finds. So we just cause an stl alloc here. + string dummy("I need to be allocated"); + dummy += "!"; // so the definition of dummy isn't optimized out +#endif /* __GLIBC__ */ +} + +// SysAllocator implementation +SysAllocator::~SysAllocator() {} + +// Default implementation -- does nothing +MallocExtension::~MallocExtension() { } +bool MallocExtension::VerifyAllMemory() { return true; } +bool MallocExtension::VerifyNewMemory(const void* p) { return true; } +bool MallocExtension::VerifyArrayNewMemory(const void* p) { return true; } +bool MallocExtension::VerifyMallocMemory(const void* p) { return true; } + +bool MallocExtension::GetNumericProperty(const char* property, size_t* value) { + return false; +} + +bool MallocExtension::SetNumericProperty(const char* property, size_t value) { + return false; +} + +void MallocExtension::GetStats(char* buffer, int length) { + assert(length > 0); + buffer[0] = '\0'; +} + +bool MallocExtension::MallocMemoryStats(int* blocks, size_t* total, + int histogram[kMallocHistogramSize]) { + *blocks = 0; + *total = 0; + memset(histogram, 0, sizeof(*histogram) * kMallocHistogramSize); + return true; +} + +void** MallocExtension::ReadStackTraces(int* sample_period) { + return NULL; +} + +void** MallocExtension::ReadHeapGrowthStackTraces() { + return NULL; +} + +void MallocExtension::MarkThreadIdle() { + // Default implementation does nothing +} + +void MallocExtension::MarkThreadBusy() { + // Default implementation does nothing +} + +SysAllocator* MallocExtension::GetSystemAllocator() { + return NULL; +} + +void MallocExtension::SetSystemAllocator(SysAllocator *a) { + // Default implementation does nothing +} + +void MallocExtension::ReleaseToSystem(size_t num_bytes) { + // Default implementation does nothing +} + +void MallocExtension::ReleaseFreeMemory() { + ReleaseToSystem(static_cast(-1)); // SIZE_T_MAX +} + +void MallocExtension::SetMemoryReleaseRate(double rate) { + // Default implementation does nothing +} + +double MallocExtension::GetMemoryReleaseRate() { + return -1.0; +} + +size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) { + return size; +} + +size_t MallocExtension::GetAllocatedSize(const void* p) { + assert(GetOwnership(p) != kNotOwned); + return 0; +} + +MallocExtension::Ownership MallocExtension::GetOwnership(const void* p) { + return kUnknownOwnership; +} + +void MallocExtension::GetFreeListSizes( + vector* v) { + v->clear(); +} + +size_t MallocExtension::GetThreadCacheSize() { + return 0; +} + +void MallocExtension::MarkThreadTemporarilyIdle() { + // Default implementation does nothing +} + +// The current malloc extension object. + +static MallocExtension* current_instance; + +static void InitModule() { + if (current_instance != NULL) { + return; + } + current_instance = new MallocExtension; +#ifndef NO_HEAP_CHECK + HeapLeakChecker::IgnoreObject(current_instance); +#endif +} + +REGISTER_MODULE_INITIALIZER(malloc_extension_init, InitModule()) + +MallocExtension* MallocExtension::instance() { + InitModule(); + return current_instance; +} + +void MallocExtension::Register(MallocExtension* implementation) { + InitModule(); + // When running under valgrind, our custom malloc is replaced with + // valgrind's one and malloc extensions will not work. (Note: + // callers should be responsible for checking that they are the + // malloc that is really being run, before calling Register. This + // is just here as an extra sanity check.) + if (!RunningOnValgrind()) { + current_instance = implementation; + } +} + +// ----------------------------------------------------------------------- +// Heap sampling support +// ----------------------------------------------------------------------- + +namespace { + +// Accessors +uintptr_t Count(void** entry) { + return reinterpret_cast(entry[0]); +} +uintptr_t Size(void** entry) { + return reinterpret_cast(entry[1]); +} +uintptr_t Depth(void** entry) { + return reinterpret_cast(entry[2]); +} +void* PC(void** entry, int i) { + return entry[3+i]; +} + +void PrintCountAndSize(MallocExtensionWriter* writer, + uintptr_t count, uintptr_t size) { + char buf[100]; + snprintf(buf, sizeof(buf), + "%6" PRIu64 ": %8" PRIu64 " [%6" PRIu64 ": %8" PRIu64 "] @", + static_cast(count), + static_cast(size), + static_cast(count), + static_cast(size)); + writer->append(buf, strlen(buf)); +} + +void PrintHeader(MallocExtensionWriter* writer, + const char* label, void** entries) { + // Compute the total count and total size + uintptr_t total_count = 0; + uintptr_t total_size = 0; + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + total_count += Count(entry); + total_size += Size(entry); + } + + const char* const kTitle = "heap profile: "; + writer->append(kTitle, strlen(kTitle)); + PrintCountAndSize(writer, total_count, total_size); + writer->append(" ", 1); + writer->append(label, strlen(label)); + writer->append("\n", 1); +} + +void PrintStackEntry(MallocExtensionWriter* writer, void** entry) { + PrintCountAndSize(writer, Count(entry), Size(entry)); + + for (int i = 0; i < Depth(entry); i++) { + char buf[32]; + snprintf(buf, sizeof(buf), " %p", PC(entry, i)); + writer->append(buf, strlen(buf)); + } + writer->append("\n", 1); +} + +} + +void MallocExtension::GetHeapSample(MallocExtensionWriter* writer) { + int sample_period = 0; + void** entries = ReadStackTraces(&sample_period); + if (entries == NULL) { + const char* const kErrorMsg = + "This malloc implementation does not support sampling.\n" + "As of 2005/01/26, only tcmalloc supports sampling, and\n" + "you are probably running a binary that does not use\n" + "tcmalloc.\n"; + writer->append(kErrorMsg, strlen(kErrorMsg)); + return; + } + + char label[32]; + sprintf(label, "heap_v2/%d", sample_period); + PrintHeader(writer, label, entries); + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + PrintStackEntry(writer, entry); + } + delete[] entries; + + DumpAddressMap(writer); +} + +void MallocExtension::GetHeapGrowthStacks(MallocExtensionWriter* writer) { + void** entries = ReadHeapGrowthStackTraces(); + if (entries == NULL) { + const char* const kErrorMsg = + "This malloc implementation does not support " + "ReadHeapGrowthStackTraces().\n" + "As of 2005/09/27, only tcmalloc supports this, and you\n" + "are probably running a binary that does not use tcmalloc.\n"; + writer->append(kErrorMsg, strlen(kErrorMsg)); + return; + } + + // Do not canonicalize the stack entries, so that we get a + // time-ordered list of stack traces, which may be useful if the + // client wants to focus on the latest stack traces. + PrintHeader(writer, "growth", entries); + for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { + PrintStackEntry(writer, entry); + } + delete[] entries; + + DumpAddressMap(writer); +} + +void MallocExtension::Ranges(void* arg, RangeFunction func) { + // No callbacks by default +} + +// These are C shims that work on the current instance. + +#define C_SHIM(fn, retval, paramlist, arglist) \ + extern "C" PERFTOOLS_DLL_DECL retval MallocExtension_##fn paramlist { \ + return MallocExtension::instance()->fn arglist; \ + } + +C_SHIM(VerifyAllMemory, int, (void), ()); +C_SHIM(VerifyNewMemory, int, (const void* p), (p)); +C_SHIM(VerifyArrayNewMemory, int, (const void* p), (p)); +C_SHIM(VerifyMallocMemory, int, (const void* p), (p)); +C_SHIM(MallocMemoryStats, int, + (int* blocks, size_t* total, int histogram[kMallocHistogramSize]), + (blocks, total, histogram)); + +C_SHIM(GetStats, void, + (char* buffer, int buffer_length), (buffer, buffer_length)); +C_SHIM(GetNumericProperty, int, + (const char* property, size_t* value), (property, value)); +C_SHIM(SetNumericProperty, int, + (const char* property, size_t value), (property, value)); + +C_SHIM(MarkThreadIdle, void, (void), ()); +C_SHIM(MarkThreadBusy, void, (void), ()); +C_SHIM(ReleaseFreeMemory, void, (void), ()); +C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); +C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); +C_SHIM(GetAllocatedSize, size_t, (const void* p), (p)); +C_SHIM(GetThreadCacheSize, size_t, (void), ()); +C_SHIM(MarkThreadTemporarilyIdle, void, (void), ()); + +// Can't use the shim here because of the need to translate the enums. +extern "C" +MallocExtension_Ownership MallocExtension_GetOwnership(const void* p) { + return static_cast( + MallocExtension::instance()->GetOwnership(p)); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/malloc_hook-inl.h b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook-inl.h new file mode 100644 index 000000000..b07704ea6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook-inl.h @@ -0,0 +1,249 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// This has the implementation details of malloc_hook that are needed +// to use malloc-hook inside the tcmalloc system. It does not hold +// any of the client-facing calls that are used to add new hooks. + +#ifndef _MALLOC_HOOK_INL_H_ +#define _MALLOC_HOOK_INL_H_ + +#include +#include +#include "base/atomicops.h" +#include "base/basictypes.h" +#include + +#include "common.h" // for UNLIKELY + +namespace base { namespace internal { + +// Capacity of 8 means that HookList is 9 words. +static const int kHookListCapacity = 8; +// last entry is reserved for deprecated "singular" hooks. So we have +// 7 "normal" hooks per list +static const int kHookListMaxValues = 7; +static const int kHookListSingularIdx = 7; + +// HookList: a class that provides synchronized insertions and removals and +// lockless traversal. Most of the implementation is in malloc_hook.cc. +template +struct PERFTOOLS_DLL_DECL HookList { + COMPILE_ASSERT(sizeof(T) <= sizeof(AtomicWord), T_should_fit_in_AtomicWord); + + // Adds value to the list. Note that duplicates are allowed. Thread-safe and + // blocking (acquires hooklist_spinlock). Returns true on success; false + // otherwise (failures include invalid value and no space left). + bool Add(T value); + + void FixupPrivEndLocked(); + + // Removes the first entry matching value from the list. Thread-safe and + // blocking (acquires hooklist_spinlock). Returns true on success; false + // otherwise (failures include invalid value and no value found). + bool Remove(T value); + + // Store up to n values of the list in output_array, and return the number of + // elements stored. Thread-safe and non-blocking. This is fast (one memory + // access) if the list is empty. + int Traverse(T* output_array, int n) const; + + // Fast inline implementation for fast path of Invoke*Hook. + bool empty() const { + return base::subtle::NoBarrier_Load(&priv_end) == 0; + } + + // Used purely to handle deprecated singular hooks + T GetSingular() const { + const AtomicWord *place = &priv_data[kHookListSingularIdx]; + return bit_cast(base::subtle::NoBarrier_Load(place)); + } + + T ExchangeSingular(T new_val); + + // This internal data is not private so that the class is an aggregate and can + // be initialized by the linker. Don't access this directly. Use the + // INIT_HOOK_LIST macro in malloc_hook.cc. + + // One more than the index of the last valid element in priv_data. During + // 'Remove' this may be past the last valid element in priv_data, but + // subsequent values will be 0. + // + // Index kHookListCapacity-1 is reserved as 'deprecated' single hook pointer + AtomicWord priv_end; + AtomicWord priv_data[kHookListCapacity]; +}; + +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList new_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList delete_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList premmap_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList mmap_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList mmap_replacement_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList munmap_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList munmap_replacement_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList mremap_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList presbrk_hooks_; +ATTRIBUTE_VISIBILITY_HIDDEN extern HookList sbrk_hooks_; + +} } // namespace base::internal + +// The following method is DEPRECATED +inline MallocHook::NewHook MallocHook::GetNewHook() { + return base::internal::new_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeNewHook(const void* p, size_t s) { + if (PREDICT_FALSE(!base::internal::new_hooks_.empty())) { + InvokeNewHookSlow(p, s); + } +} + +// The following method is DEPRECATED +inline MallocHook::DeleteHook MallocHook::GetDeleteHook() { + return base::internal::delete_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeDeleteHook(const void* p) { + if (PREDICT_FALSE(!base::internal::delete_hooks_.empty())) { + InvokeDeleteHookSlow(p); + } +} + +// The following method is DEPRECATED +inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() { + return base::internal::premmap_hooks_.GetSingular(); +} + +inline void MallocHook::InvokePreMmapHook(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset) { + if (!base::internal::premmap_hooks_.empty()) { + InvokePreMmapHookSlow(start, size, protection, flags, fd, offset); + } +} + +// The following method is DEPRECATED +inline MallocHook::MmapHook MallocHook::GetMmapHook() { + return base::internal::mmap_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeMmapHook(const void* result, + const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset) { + if (!base::internal::mmap_hooks_.empty()) { + InvokeMmapHookSlow(result, start, size, protection, flags, fd, offset); + } +} + +inline bool MallocHook::InvokeMmapReplacement(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result) { + if (!base::internal::mmap_replacement_.empty()) { + return InvokeMmapReplacementSlow(start, size, + protection, flags, + fd, offset, + result); + } + return false; +} + +// The following method is DEPRECATED +inline MallocHook::MunmapHook MallocHook::GetMunmapHook() { + return base::internal::munmap_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) { + if (!base::internal::munmap_hooks_.empty()) { + InvokeMunmapHookSlow(p, size); + } +} + +inline bool MallocHook::InvokeMunmapReplacement( + const void* p, size_t size, int* result) { + if (!base::internal::mmap_replacement_.empty()) { + return InvokeMunmapReplacementSlow(p, size, result); + } + return false; +} + +// The following method is DEPRECATED +inline MallocHook::MremapHook MallocHook::GetMremapHook() { + return base::internal::mremap_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeMremapHook(const void* result, + const void* old_addr, + size_t old_size, + size_t new_size, + int flags, + const void* new_addr) { + if (!base::internal::mremap_hooks_.empty()) { + InvokeMremapHookSlow(result, old_addr, old_size, new_size, flags, new_addr); + } +} + +// The following method is DEPRECATED +inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() { + return base::internal::presbrk_hooks_.GetSingular(); +} + +inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) { + if (!base::internal::presbrk_hooks_.empty() && increment != 0) { + InvokePreSbrkHookSlow(increment); + } +} + +// The following method is DEPRECATED +inline MallocHook::SbrkHook MallocHook::GetSbrkHook() { + return base::internal::sbrk_hooks_.GetSingular(); +} + +inline void MallocHook::InvokeSbrkHook(const void* result, + ptrdiff_t increment) { + if (!base::internal::sbrk_hooks_.empty() && increment != 0) { + InvokeSbrkHookSlow(result, increment); + } +} + +#endif /* _MALLOC_HOOK_INL_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/malloc_hook.cc b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook.cc new file mode 100644 index 000000000..9d5741ef5 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook.cc @@ -0,0 +1,711 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat + +#include + +// Disable the glibc prototype of mremap(), as older versions of the +// system headers define this function with only four arguments, +// whereas newer versions allow an optional fifth argument: +#ifdef HAVE_MMAP +# define mremap glibc_mremap +# include +# undef mremap +#endif + +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include "base/logging.h" +#include "base/spinlock.h" +#include "maybe_emergency_malloc.h" +#include "maybe_threads.h" +#include "malloc_hook-inl.h" +#include + +// This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if +// you're porting to a system where you really can't get a stacktrace. +#ifdef NO_TCMALLOC_SAMPLES + // We use #define so code compiles even if you #include stacktrace.h somehow. +# define GetStackTrace(stack, depth, skip) (0) +#else +# include +#endif + +// __THROW is defined in glibc systems. It means, counter-intuitively, +// "This function will never throw an exception." It's an optional +// optimization tool, but we may need to use it to match glibc prototypes. +#ifndef __THROW // I guess we're not on a glibc system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +using std::copy; + + +// Declaration of default weak initialization function, that can be overridden +// by linking-in a strong definition (as heap-checker.cc does). This is +// extern "C" so that it doesn't trigger gold's --detect-odr-violations warning, +// which only looks at C++ symbols. +// +// This function is declared here as weak, and defined later, rather than a more +// straightforward simple weak definition, as a workround for an icc compiler +// issue ((Intel reference 290819). This issue causes icc to resolve weak +// symbols too early, at compile rather than link time. By declaring it (weak) +// here, then defining it below after its use, we can avoid the problem. +extern "C" { +ATTRIBUTE_WEAK void MallocHook_InitAtFirstAllocation_HeapLeakChecker(); +} + +namespace { + +void RemoveInitialHooksAndCallInitializers(); // below. + +pthread_once_t once = PTHREAD_ONCE_INIT; + +// These hooks are installed in MallocHook as the only initial hooks. The first +// hook that is called will run RemoveInitialHooksAndCallInitializers (see the +// definition below) and then redispatch to any malloc hooks installed by +// RemoveInitialHooksAndCallInitializers. +// +// Note(llib): there is a possibility of a race in the event that there are +// multiple threads running before the first allocation. This is pretty +// difficult to achieve, but if it is then multiple threads may concurrently do +// allocations. The first caller will call +// RemoveInitialHooksAndCallInitializers via one of the initial hooks. A +// concurrent allocation may, depending on timing either: +// * still have its initial malloc hook installed, run that and block on waiting +// for the first caller to finish its call to +// RemoveInitialHooksAndCallInitializers, and proceed normally. +// * occur some time during the RemoveInitialHooksAndCallInitializers call, at +// which point there could be no initial hooks and the subsequent hooks that +// are about to be set up by RemoveInitialHooksAndCallInitializers haven't +// been installed yet. I think the worst we can get is that some allocations +// will not get reported to some hooks set by the initializers called from +// RemoveInitialHooksAndCallInitializers. + +void InitialNewHook(const void* ptr, size_t size) { + perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers); + MallocHook::InvokeNewHook(ptr, size); +} + +void InitialPreMMapHook(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset) { + perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers); + MallocHook::InvokePreMmapHook(start, size, protection, flags, fd, offset); +} + +void InitialPreSbrkHook(ptrdiff_t increment) { + perftools_pthread_once(&once, &RemoveInitialHooksAndCallInitializers); + MallocHook::InvokePreSbrkHook(increment); +} + +// This function is called at most once by one of the above initial malloc +// hooks. It removes all initial hooks and initializes all other clients that +// want to get control at the very first memory allocation. The initializers +// may assume that the initial malloc hooks have been removed. The initializers +// may set up malloc hooks and allocate memory. +void RemoveInitialHooksAndCallInitializers() { + RAW_CHECK(MallocHook::RemoveNewHook(&InitialNewHook), ""); + RAW_CHECK(MallocHook::RemovePreMmapHook(&InitialPreMMapHook), ""); + RAW_CHECK(MallocHook::RemovePreSbrkHook(&InitialPreSbrkHook), ""); + + // HeapLeakChecker is currently the only module that needs to get control on + // the first memory allocation, but one can add other modules by following the + // same weak/strong function pattern. + MallocHook_InitAtFirstAllocation_HeapLeakChecker(); +} + +} // namespace + +// Weak default initialization function that must go after its use. +extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() { + // Do nothing. +} + +namespace base { namespace internal { + +// This lock is shared between all implementations of HookList::Add & Remove. +// The potential for contention is very small. This needs to be a SpinLock and +// not a Mutex since it's possible for Mutex locking to allocate memory (e.g., +// per-thread allocation in debug builds), which could cause infinite recursion. +static SpinLock hooklist_spinlock(base::LINKER_INITIALIZED); + +template +bool HookList::Add(T value_as_t) { + AtomicWord value = bit_cast(value_as_t); + if (value == 0) { + return false; + } + SpinLockHolder l(&hooklist_spinlock); + // Find the first slot in data that is 0. + int index = 0; + while ((index < kHookListMaxValues) && + (base::subtle::NoBarrier_Load(&priv_data[index]) != 0)) { + ++index; + } + if (index == kHookListMaxValues) { + return false; + } + AtomicWord prev_num_hooks = base::subtle::Acquire_Load(&priv_end); + base::subtle::NoBarrier_Store(&priv_data[index], value); + if (prev_num_hooks <= index) { + base::subtle::NoBarrier_Store(&priv_end, index + 1); + } + return true; +} + +template +void HookList::FixupPrivEndLocked() { + AtomicWord hooks_end = base::subtle::NoBarrier_Load(&priv_end); + while ((hooks_end > 0) && + (base::subtle::NoBarrier_Load(&priv_data[hooks_end - 1]) == 0)) { + --hooks_end; + } + base::subtle::NoBarrier_Store(&priv_end, hooks_end); +} + +template +bool HookList::Remove(T value_as_t) { + if (value_as_t == 0) { + return false; + } + SpinLockHolder l(&hooklist_spinlock); + AtomicWord hooks_end = base::subtle::NoBarrier_Load(&priv_end); + int index = 0; + while (index < hooks_end && value_as_t != bit_cast( + base::subtle::NoBarrier_Load(&priv_data[index]))) { + ++index; + } + if (index == hooks_end) { + return false; + } + base::subtle::NoBarrier_Store(&priv_data[index], 0); + FixupPrivEndLocked(); + return true; +} + +template +int HookList::Traverse(T* output_array, int n) const { + AtomicWord hooks_end = base::subtle::Acquire_Load(&priv_end); + int actual_hooks_end = 0; + for (int i = 0; i < hooks_end && n > 0; ++i) { + AtomicWord data = base::subtle::Acquire_Load(&priv_data[i]); + if (data != 0) { + *output_array++ = bit_cast(data); + ++actual_hooks_end; + --n; + } + } + return actual_hooks_end; +} + +template +T HookList::ExchangeSingular(T value_as_t) { + AtomicWord value = bit_cast(value_as_t); + AtomicWord old_value; + SpinLockHolder l(&hooklist_spinlock); + old_value = base::subtle::NoBarrier_Load(&priv_data[kHookListSingularIdx]); + base::subtle::NoBarrier_Store(&priv_data[kHookListSingularIdx], value); + if (value != 0) { + base::subtle::NoBarrier_Store(&priv_end, kHookListSingularIdx + 1); + } else { + FixupPrivEndLocked(); + } + return bit_cast(old_value); +} + +// Initialize a HookList (optionally with the given initial_value in index 0). +#define INIT_HOOK_LIST { 0 } +#define INIT_HOOK_LIST_WITH_VALUE(initial_value) \ + { 1, { reinterpret_cast(initial_value) } } + +// Explicit instantiation for malloc_hook_test.cc. This ensures all the methods +// are instantiated. +template struct HookList; + +HookList new_hooks_ = + INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook); +HookList delete_hooks_ = INIT_HOOK_LIST; +HookList premmap_hooks_ = + INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook); +HookList mmap_hooks_ = INIT_HOOK_LIST; +HookList munmap_hooks_ = INIT_HOOK_LIST; +HookList mremap_hooks_ = INIT_HOOK_LIST; +HookList presbrk_hooks_ = + INIT_HOOK_LIST_WITH_VALUE(InitialPreSbrkHook); +HookList sbrk_hooks_ = INIT_HOOK_LIST; + +// These lists contain either 0 or 1 hooks. +HookList mmap_replacement_ = { 0 }; +HookList munmap_replacement_ = { 0 }; + +#undef INIT_HOOK_LIST_WITH_VALUE +#undef INIT_HOOK_LIST + +} } // namespace base::internal + +using base::internal::kHookListMaxValues; +using base::internal::new_hooks_; +using base::internal::delete_hooks_; +using base::internal::premmap_hooks_; +using base::internal::mmap_hooks_; +using base::internal::mmap_replacement_; +using base::internal::munmap_hooks_; +using base::internal::munmap_replacement_; +using base::internal::mremap_hooks_; +using base::internal::presbrk_hooks_; +using base::internal::sbrk_hooks_; + +// These are available as C bindings as well as C++, hence their +// definition outside the MallocHook class. +extern "C" +int MallocHook_AddNewHook(MallocHook_NewHook hook) { + RAW_VLOG(10, "AddNewHook(%p)", hook); + return new_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveNewHook(MallocHook_NewHook hook) { + RAW_VLOG(10, "RemoveNewHook(%p)", hook); + return new_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_AddDeleteHook(MallocHook_DeleteHook hook) { + RAW_VLOG(10, "AddDeleteHook(%p)", hook); + return delete_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook hook) { + RAW_VLOG(10, "RemoveDeleteHook(%p)", hook); + return delete_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_AddPreMmapHook(MallocHook_PreMmapHook hook) { + RAW_VLOG(10, "AddPreMmapHook(%p)", hook); + return premmap_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemovePreMmapHook(MallocHook_PreMmapHook hook) { + RAW_VLOG(10, "RemovePreMmapHook(%p)", hook); + return premmap_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_SetMmapReplacement(MallocHook_MmapReplacement hook) { + RAW_VLOG(10, "SetMmapReplacement(%p)", hook); + // NOTE this is a best effort CHECK. Concurrent sets could succeed since + // this test is outside of the Add spin lock. + RAW_CHECK(mmap_replacement_.empty(), "Only one MMapReplacement is allowed."); + return mmap_replacement_.Add(hook); +} + +extern "C" +int MallocHook_RemoveMmapReplacement(MallocHook_MmapReplacement hook) { + RAW_VLOG(10, "RemoveMmapReplacement(%p)", hook); + return mmap_replacement_.Remove(hook); +} + +extern "C" +int MallocHook_AddMmapHook(MallocHook_MmapHook hook) { + RAW_VLOG(10, "AddMmapHook(%p)", hook); + return mmap_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveMmapHook(MallocHook_MmapHook hook) { + RAW_VLOG(10, "RemoveMmapHook(%p)", hook); + return mmap_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_AddMunmapHook(MallocHook_MunmapHook hook) { + RAW_VLOG(10, "AddMunmapHook(%p)", hook); + return munmap_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveMunmapHook(MallocHook_MunmapHook hook) { + RAW_VLOG(10, "RemoveMunmapHook(%p)", hook); + return munmap_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_SetMunmapReplacement(MallocHook_MunmapReplacement hook) { + RAW_VLOG(10, "SetMunmapReplacement(%p)", hook); + // NOTE this is a best effort CHECK. Concurrent sets could succeed since + // this test is outside of the Add spin lock. + RAW_CHECK(munmap_replacement_.empty(), + "Only one MunmapReplacement is allowed."); + return munmap_replacement_.Add(hook); +} + +extern "C" +int MallocHook_RemoveMunmapReplacement(MallocHook_MunmapReplacement hook) { + RAW_VLOG(10, "RemoveMunmapReplacement(%p)", hook); + return munmap_replacement_.Remove(hook); +} + +extern "C" +int MallocHook_AddMremapHook(MallocHook_MremapHook hook) { + RAW_VLOG(10, "AddMremapHook(%p)", hook); + return mremap_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveMremapHook(MallocHook_MremapHook hook) { + RAW_VLOG(10, "RemoveMremapHook(%p)", hook); + return mremap_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_AddPreSbrkHook(MallocHook_PreSbrkHook hook) { + RAW_VLOG(10, "AddPreSbrkHook(%p)", hook); + return presbrk_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemovePreSbrkHook(MallocHook_PreSbrkHook hook) { + RAW_VLOG(10, "RemovePreSbrkHook(%p)", hook); + return presbrk_hooks_.Remove(hook); +} + +extern "C" +int MallocHook_AddSbrkHook(MallocHook_SbrkHook hook) { + RAW_VLOG(10, "AddSbrkHook(%p)", hook); + return sbrk_hooks_.Add(hook); +} + +extern "C" +int MallocHook_RemoveSbrkHook(MallocHook_SbrkHook hook) { + RAW_VLOG(10, "RemoveSbrkHook(%p)", hook); + return sbrk_hooks_.Remove(hook); +} + +// The code below is DEPRECATED. +extern "C" +MallocHook_NewHook MallocHook_SetNewHook(MallocHook_NewHook hook) { + RAW_VLOG(10, "SetNewHook(%p)", hook); + return new_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook) { + RAW_VLOG(10, "SetDeleteHook(%p)", hook); + return delete_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook) { + RAW_VLOG(10, "SetPreMmapHook(%p)", hook); + return premmap_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook) { + RAW_VLOG(10, "SetMmapHook(%p)", hook); + return mmap_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook) { + RAW_VLOG(10, "SetMunmapHook(%p)", hook); + return munmap_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook) { + RAW_VLOG(10, "SetMremapHook(%p)", hook); + return mremap_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook) { + RAW_VLOG(10, "SetPreSbrkHook(%p)", hook); + return presbrk_hooks_.ExchangeSingular(hook); +} + +extern "C" +MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook) { + RAW_VLOG(10, "SetSbrkHook(%p)", hook); + return sbrk_hooks_.ExchangeSingular(hook); +} +// End of DEPRECATED code section. + +// Note: embedding the function calls inside the traversal of HookList would be +// very confusing, as it is legal for a hook to remove itself and add other +// hooks. Doing traversal first, and then calling the hooks ensures we only +// call the hooks registered at the start. +#define INVOKE_HOOKS(HookType, hook_list, args) do { \ + HookType hooks[kHookListMaxValues]; \ + int num_hooks = hook_list.Traverse(hooks, kHookListMaxValues); \ + for (int i = 0; i < num_hooks; ++i) { \ + (*hooks[i])args; \ + } \ + } while (0) + +// There should only be one replacement. Return the result of the first +// one, or false if there is none. +#define INVOKE_REPLACEMENT(HookType, hook_list, args) do { \ + HookType hooks[kHookListMaxValues]; \ + int num_hooks = hook_list.Traverse(hooks, kHookListMaxValues); \ + return (num_hooks > 0 && (*hooks[0])args); \ + } while (0) + + +void MallocHook::InvokeNewHookSlow(const void* p, size_t s) { + if (tcmalloc::IsEmergencyPtr(p)) { + return; + } + INVOKE_HOOKS(NewHook, new_hooks_, (p, s)); +} + +void MallocHook::InvokeDeleteHookSlow(const void* p) { + if (tcmalloc::IsEmergencyPtr(p)) { + return; + } + INVOKE_HOOKS(DeleteHook, delete_hooks_, (p)); +} + +void MallocHook::InvokePreMmapHookSlow(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset) { + INVOKE_HOOKS(PreMmapHook, premmap_hooks_, (start, size, protection, flags, fd, + offset)); +} + +void MallocHook::InvokeMmapHookSlow(const void* result, + const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset) { + INVOKE_HOOKS(MmapHook, mmap_hooks_, (result, start, size, protection, flags, + fd, offset)); +} + +bool MallocHook::InvokeMmapReplacementSlow(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result) { + INVOKE_REPLACEMENT(MmapReplacement, mmap_replacement_, + (start, size, protection, flags, fd, offset, result)); +} + +void MallocHook::InvokeMunmapHookSlow(const void* p, size_t s) { + INVOKE_HOOKS(MunmapHook, munmap_hooks_, (p, s)); +} + +bool MallocHook::InvokeMunmapReplacementSlow(const void* p, + size_t s, + int* result) { + INVOKE_REPLACEMENT(MunmapReplacement, munmap_replacement_, (p, s, result)); +} + +void MallocHook::InvokeMremapHookSlow(const void* result, + const void* old_addr, + size_t old_size, + size_t new_size, + int flags, + const void* new_addr) { + INVOKE_HOOKS(MremapHook, mremap_hooks_, (result, old_addr, old_size, new_size, + flags, new_addr)); +} + +void MallocHook::InvokePreSbrkHookSlow(ptrdiff_t increment) { + INVOKE_HOOKS(PreSbrkHook, presbrk_hooks_, (increment)); +} + +void MallocHook::InvokeSbrkHookSlow(const void* result, ptrdiff_t increment) { + INVOKE_HOOKS(SbrkHook, sbrk_hooks_, (result, increment)); +} + +#undef INVOKE_HOOKS + +#ifndef NO_TCMALLOC_SAMPLES + +DEFINE_ATTRIBUTE_SECTION_VARS(google_malloc); +DECLARE_ATTRIBUTE_SECTION_VARS(google_malloc); + // actual functions are in debugallocation.cc or tcmalloc.cc +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) \ + (reinterpret_cast(ATTRIBUTE_SECTION_START(name)) <= \ + reinterpret_cast(addr) && \ + reinterpret_cast(addr) < \ + reinterpret_cast(ATTRIBUTE_SECTION_STOP(name))) + +// 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(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 + // due to its special linkage mode, which prevents merging of the sections. +} + +#undef ADDR_IN_ATTRIBUTE_SECTION + +static bool checked_sections = false; + +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, " + "thus InHookCaller is broken!"); + } + checked_sections = true; + } +} + +#endif // !NO_TCMALLOC_SAMPLES + +// We can improve behavior/compactness of this function +// if we pass a generic test function (with a generic arg) +// into the implementations for GetStackTrace instead of the skip_count. +extern "C" int MallocHook_GetCallerStackTrace(void** result, int max_depth, + int skip_count) { +#if defined(NO_TCMALLOC_SAMPLES) + return 0; +#elif !defined(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, + // search for MallocHook::(Get|Set|Invoke)* to find such cases. + return GetStackTrace(result, max_depth, skip_count + int(DEBUG_MODE)); + // due to -foptimize-sibling-calls in opt mode + // there's no need for extra frame skip here then +#else + CheckInHookCaller(); + // MallocHook caller determination via InHookCaller works, use it: + static const int kMaxSkip = 32 + 6 + 3; + // Constant tuned to do just one GetStackTrace call below in practice + // and not get many frames that we don't actually need: + // currently max passsed max_depth is 32, + // max passed/needed skip_count is 6 + // and 3 is to account for some hook daisy chaining. + static const int kStackSize = kMaxSkip + 1; + void* stack[kStackSize]; + int depth = GetStackTrace(stack, kStackSize, 1); // skip this function frame + if (depth == 0) // silenty propagate cases when GetStackTrace does not work + return 0; + for (int i = 0; i < depth; ++i) { // stack[0] is our immediate caller + if (InHookCaller(stack[i])) { + // fast-path to slow-path calls may be implemented by compiler + // as non-tail calls. Causing two functions on stack trace to be + // inside google_malloc. In such case we're skipping to + // outermost such frame since this is where malloc stack frames + // really start. + while (i + 1 < depth && InHookCaller(stack[i+1])) { + i++; + } + RAW_VLOG(10, "Found hooked allocator at %d: %p <- %p", + i, stack[i], stack[i+1]); + i += 1; // skip hook caller frame + depth -= i; // correct depth + if (depth > max_depth) depth = max_depth; + copy(stack + i, stack + i + depth, result); + if (depth < max_depth && depth + i == kStackSize) { + // get frames for the missing depth + depth += + GetStackTrace(result + depth, max_depth - depth, 1 + kStackSize); + } + return depth; + } + } + RAW_LOG(WARNING, "Hooked allocator frame not found, returning empty trace"); + // If this happens try increasing kMaxSkip + // or else something must be wrong with InHookCaller, + // e.g. for every section used in InHookCaller + // all functions in that section must be inside the same library. + return 0; +#endif +} + +// On systems where we know how, we override mmap/munmap/mremap/sbrk +// to provide support for calling the related hooks (in addition, +// of course, to doing what these functions normally do). + +#if defined(__linux) +# include "malloc_hook_mmap_linux.h" + +#elif defined(__FreeBSD__) +# include "malloc_hook_mmap_freebsd.h" + +#else + +/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, + int flags, int fd, off_t offset) { + void* result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = mmap(start, length, prot, flags, fd, offset); + } + return result; +} + +/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = munmap(start, length); + } + return result; +} + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_freebsd.h b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_freebsd.h new file mode 100644 index 000000000..8575dcc7c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_freebsd.h @@ -0,0 +1,135 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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. + +// Override mmap/munmap/mremap/sbrk to provide support for calling the +// related hooks (in addition, of course, to doing what these +// functions normally do). + +#ifndef __FreeBSD__ +# error Should only be including malloc_hook_mmap_freebsd.h on FreeBSD systems. +#endif + +#include +#include +#include +#include +#include + +// Make sure mmap doesn't get #define'd away by +#undef mmap + +// According to the FreeBSD documentation, use syscall if you do not +// need 64-bit alignment otherwise use __syscall. Indeed, syscall +// doesn't work correctly in most situations on 64-bit. It's return +// type is 'int' so for things like SYS_mmap, it actually truncates +// the returned address to 32-bits. +#if defined(__amd64__) || defined(__x86_64__) +# define MALLOC_HOOK_SYSCALL __syscall +#else +# define MALLOC_HOOK_SYSCALL syscall +#endif + + +extern "C" { + void* mmap(void *start, size_t length,int prot, int flags, + int fd, off_t offset) __THROW + ATTRIBUTE_SECTION(malloc_hook); + int munmap(void* start, size_t length) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* sbrk(intptr_t increment) __THROW + ATTRIBUTE_SECTION(malloc_hook); +} + +static inline void* do_mmap(void *start, size_t length, + int prot, int flags, + int fd, off_t offset) __THROW { + return (void *)MALLOC_HOOK_SYSCALL(SYS_mmap, + start, length, prot, flags, fd, offset); +} + +static inline void* do_sbrk(intptr_t increment) { + static void *(*libc_sbrk)(intptr_t); + if (libc_sbrk == NULL) + libc_sbrk = (void *(*)(intptr_t))dlsym(RTLD_NEXT, "sbrk"); + + return libc_sbrk(increment); +} + + +extern "C" void* mmap(void *start, size_t length, int prot, int flags, + int fd, off_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap(start, length, prot, flags, fd, + static_cast(offset)); // avoid sign extension + } + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +extern "C" int munmap(void* start, size_t length) __THROW { + MallocHook::InvokeMunmapHook(start, length); + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = MALLOC_HOOK_SYSCALL(SYS_munmap, start, length); + } + + return result; +} + +extern "C" void* sbrk(intptr_t increment) __THROW { + MallocHook::InvokePreSbrkHook(increment); + void *result = do_sbrk(increment); + MallocHook::InvokeSbrkHook(result, increment); + return result; +} + +/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, + int flags, int fd, off_t offset) { + void* result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap(start, length, prot, flags, fd, offset); + } + + return result; +} + +/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = MALLOC_HOOK_SYSCALL(SYS_munmap, start, length); + } + return result; +} + +#undef MALLOC_HOOK_SYSCALL diff --git a/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_linux.h b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_linux.h new file mode 100644 index 000000000..cbf37825d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/malloc_hook_mmap_linux.h @@ -0,0 +1,250 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat + +// We define mmap() and mmap64(), which somewhat reimplements libc's mmap +// syscall stubs. Unfortunately libc only exports the stubs via weak symbols +// (which we're overriding with our mmap64() and mmap() wrappers) so we can't +// just call through to them. + +#ifndef __linux +# error Should only be including malloc_hook_mmap_linux.h on linux systems. +#endif + +#include +#include +#include +#include + +// The x86-32 case and the x86-64 case differ: +// 32b has a mmap2() syscall, 64b does not. +// 64b and 32b have different calling conventions for mmap(). + +// I test for 64-bit first so I don't have to do things like +// '#if (defined(__mips__) && !defined(__MIPS64__))' as a mips32 check. +#if defined(__x86_64__) \ + || defined(__PPC64__) \ + || defined(__aarch64__) \ + || (defined(_MIPS_SIM) && (_MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32)) \ + || defined(__s390__) || (defined(__riscv) && __riscv_xlen == 64) \ + || defined(__e2k__) + +static inline void* do_mmap64(void *start, size_t length, + int prot, int flags, + int fd, off64_t offset) __THROW { +#if defined(__s390__) + long args[6] = { (long)start, (long)length, (long)prot, (long)flags, + (long)fd, (long)offset }; + return (void*)syscall(SYS_mmap, args); +#else + return (void*)syscall(SYS_mmap, start, length, prot, flags, fd, offset); +#endif +} + +#define MALLOC_HOOK_HAVE_DO_MMAP64 1 + +#elif defined(__i386__) || defined(__PPC__) || defined(__mips__) || \ + defined(__arm__) + +static inline void* do_mmap64(void *start, size_t length, + int prot, int flags, + int fd, off64_t offset) __THROW { + void *result; + + // Try mmap2() unless it's not supported + static bool have_mmap2 = true; + if (have_mmap2) { + static int pagesize = 0; + if (!pagesize) pagesize = getpagesize(); + + // Check that the offset is page aligned + if (offset & (pagesize - 1)) { + result = MAP_FAILED; + errno = EINVAL; + goto out; + } + + result = (void *)syscall(SYS_mmap2, + start, length, prot, flags, fd, + (off_t) (offset / pagesize)); + if (result != MAP_FAILED || errno != ENOSYS) goto out; + + // We don't have mmap2() after all - don't bother trying it in future + have_mmap2 = false; + } + + if (((off_t)offset) != offset) { + // If we're trying to map a 64-bit offset, fail now since we don't + // have 64-bit mmap() support. + result = MAP_FAILED; + errno = EINVAL; + goto out; + } + +#ifdef __NR_mmap + { + // Fall back to old 32-bit offset mmap() call + // Old syscall interface cannot handle six args, so pass in an array + int32 args[6] = { (int32) start, (int32) length, prot, flags, fd, + (int32)(off_t) offset }; + result = (void *)syscall(SYS_mmap, args); + } +#else + // Some Linux ports like ARM EABI Linux has no mmap, just mmap2. + result = MAP_FAILED; +#endif + + out: + return result; +} + +#define MALLOC_HOOK_HAVE_DO_MMAP64 1 + +#endif // #if defined(__x86_64__) + + +#ifdef MALLOC_HOOK_HAVE_DO_MMAP64 + +// We use do_mmap64 abstraction to put MallocHook::InvokeMmapHook +// calls right into mmap and mmap64, so that the stack frames in the caller's +// stack are at the same offsets for all the calls of memory allocating +// functions. + +// Put all callers of MallocHook::Invoke* in this module into +// malloc_hook section, +// so that MallocHook::GetCallerStackTrace can function accurately: + +// Make sure mmap64 and mmap doesn't get #define'd away by +# undef mmap64 +# undef mmap + +extern "C" { + void* mmap64(void *start, size_t length, int prot, int flags, + int fd, off64_t offset ) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* mmap(void *start, size_t length,int prot, int flags, + int fd, off_t offset) __THROW + ATTRIBUTE_SECTION(malloc_hook); + int munmap(void* start, size_t length) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* mremap(void* old_addr, size_t old_size, size_t new_size, + int flags, ...) __THROW + ATTRIBUTE_SECTION(malloc_hook); + void* sbrk(intptr_t increment) __THROW + ATTRIBUTE_SECTION(malloc_hook); +} + +extern "C" void* mmap64(void *start, size_t length, int prot, int flags, + int fd, off64_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, offset); + } + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +# if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) + +extern "C" void* mmap(void *start, size_t length, int prot, int flags, + int fd, off_t offset) __THROW { + MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset); + void *result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, + static_cast(offset)); // avoid sign extension + } + MallocHook::InvokeMmapHook(result, start, length, prot, flags, fd, offset); + return result; +} + +# endif // !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH) + +extern "C" int munmap(void* start, size_t length) __THROW { + MallocHook::InvokeMunmapHook(start, length); + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = syscall(SYS_munmap, start, length); + } + return result; +} + +extern "C" void* mremap(void* old_addr, size_t old_size, size_t new_size, + int flags, ...) __THROW { + va_list ap; + va_start(ap, flags); + void *new_address = va_arg(ap, void *); + va_end(ap); + void* result = (void*)syscall(SYS_mremap, old_addr, old_size, new_size, flags, + new_address); + MallocHook::InvokeMremapHook(result, old_addr, old_size, new_size, flags, + new_address); + return result; +} + +#ifdef HAVE___SBRK +// libc's version: +extern "C" void* __sbrk(intptr_t increment); + +extern "C" void* sbrk(intptr_t increment) __THROW { + MallocHook::InvokePreSbrkHook(increment); + void *result = __sbrk(increment); + MallocHook::InvokeSbrkHook(result, increment); + return result; +} + +#endif + +/*static*/void* MallocHook::UnhookedMMap(void *start, size_t length, int prot, + int flags, int fd, off_t offset) { + void* result; + if (!MallocHook::InvokeMmapReplacement( + start, length, prot, flags, fd, offset, &result)) { + result = do_mmap64(start, length, prot, flags, fd, offset); + } + return result; +} + +/*static*/int MallocHook::UnhookedMUnmap(void *start, size_t length) { + int result; + if (!MallocHook::InvokeMunmapReplacement(start, length, &result)) { + result = syscall(SYS_munmap, start, length); + } + return result; +} + +#undef MALLOC_HOOK_HAVE_DO_MMAP64 + +#endif // #ifdef MALLOC_HOOK_HAVE_DO_MMAP64 diff --git a/trunk/3rdparty/gperftools-2-fit/src/maybe_emergency_malloc.h b/trunk/3rdparty/gperftools-2-fit/src/maybe_emergency_malloc.h new file mode 100644 index 000000000..250ecf01a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/maybe_emergency_malloc.h @@ -0,0 +1,55 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2014, gperftools Contributors +// 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 MAYBE_EMERGENCY_MALLOC_H +#define MAYBE_EMERGENCY_MALLOC_H + +#include "config.h" + +#ifdef ENABLE_EMERGENCY_MALLOC + +#include "emergency_malloc.h" + +#else + +namespace tcmalloc { + static inline void *EmergencyMalloc(size_t size) {return NULL;} + static inline void EmergencyFree(void *p) {} + static inline void *EmergencyCalloc(size_t n, size_t elem_size) {return NULL;} + static inline void *EmergencyRealloc(void *old_ptr, size_t new_size) {return NULL;} + + static inline bool IsEmergencyPtr(const void *_ptr) { + return false; + } +} + +#endif // ENABLE_EMERGENCY_MALLOC + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.cc b/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.cc new file mode 100644 index 000000000..f973fbfc3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.cc @@ -0,0 +1,177 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Paul Menage +// +// Some wrappers for pthread functions so that we can be LD_PRELOADed +// against non-pthreads apps. +// +// This module will behave very strangely if some pthreads functions +// exist and others don't. + +#include "config.h" +#include +#include // for memcmp +#include // for __isthreaded on FreeBSD +// We don't actually need strings. But including this header seems to +// stop the compiler trying to short-circuit our pthreads existence +// tests and claiming that the address of a function is always +// non-zero. I have no idea why ... +#include +#include "maybe_threads.h" +#include "base/basictypes.h" +#include "base/logging.h" + +// __THROW is defined in glibc systems. It means, counter-intuitively, +// "This function will never throw an exception." It's an optional +// optimization tool, but we may need to use it to match glibc prototypes. +#ifndef __THROW // I guess we're not on a glibc system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +// These are the methods we're going to conditionally include. +extern "C" { + int pthread_key_create (pthread_key_t*, void (*)(void*)) + __THROW ATTRIBUTE_WEAK; + int pthread_key_delete (pthread_key_t) + __THROW ATTRIBUTE_WEAK; + void *pthread_getspecific(pthread_key_t) + __THROW ATTRIBUTE_WEAK; + int pthread_setspecific(pthread_key_t, const void*) + __THROW ATTRIBUTE_WEAK; + int pthread_once(pthread_once_t *, void (*)(void)) + ATTRIBUTE_WEAK; +#ifdef HAVE_FORK + int pthread_atfork(void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) + __THROW ATTRIBUTE_WEAK; +#endif +} + +#define MAX_PERTHREAD_VALS 16 +static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS]; +static int next_key; + +// NOTE: it's similar to bitcast defined in basic_types.h with +// exception of ignoring sizes mismatch +template +static T2 memcpy_cast(const T1 &input) { + T2 output; + size_t s = sizeof(input); + if (sizeof(output) < s) { + s = sizeof(output); + } + memcpy(&output, &input, s); + return output; +} + +int perftools_pthread_key_create(pthread_key_t *key, + void (*destr_function) (void *)) { + if (pthread_key_create) { + return pthread_key_create(key, destr_function); + } else { + assert(next_key < MAX_PERTHREAD_VALS); + *key = memcpy_cast(next_key++); + return 0; + } +} + +int perftools_pthread_key_delete(pthread_key_t key) { + if (pthread_key_delete) { + return pthread_key_delete(key); + } else { + return 0; + } +} + +void *perftools_pthread_getspecific(pthread_key_t key) { + if (pthread_getspecific) { + return pthread_getspecific(key); + } else { + return perftools_pthread_specific_vals[memcpy_cast(key)]; + } +} + +int perftools_pthread_setspecific(pthread_key_t key, void *val) { + if (pthread_setspecific) { + return pthread_setspecific(key, val); + } else { + perftools_pthread_specific_vals[memcpy_cast(key)] = val; + return 0; + } +} + + +static pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT; +int perftools_pthread_once(pthread_once_t *ctl, + void (*init_routine) (void)) { +#ifdef __FreeBSD__ + // On __FreeBSD__, calling pthread_once on a system that is not + // linked with -pthread is silently a noop. :-( Luckily, we have a + // workaround: FreeBSD exposes __isthreaded in , which is + // set to 1 when the first thread is spawned. So on those systems, + // we can use our own separate pthreads-once mechanism, which is + // used until __isthreaded is 1 (which will never be true if the app + // is not linked with -pthread). + static bool pthread_once_ran_before_threads = false; + if (pthread_once_ran_before_threads) { + return 0; + } + if (!__isthreaded) { + init_routine(); + pthread_once_ran_before_threads = true; + return 0; + } +#endif + if (pthread_once) { + return pthread_once(ctl, init_routine); + } else { + if (memcmp(ctl, &pthread_once_init, sizeof(*ctl)) == 0) { + init_routine(); + ++*(char*)(ctl); // make it so it's no longer equal to init + } + return 0; + } +} + +#ifdef HAVE_FORK + +void perftools_pthread_atfork(void (*before)(), + void (*parent_after)(), + void (*child_after)()) { + if (pthread_atfork) { + int rv = pthread_atfork(before, parent_after, child_after); + CHECK(rv == 0); + } +} + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.h b/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.h new file mode 100644 index 000000000..00f69690c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/maybe_threads.h @@ -0,0 +1,61 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Paul Menage + +//------------------------------------------------------------------- +// Some wrappers for pthread functions so that we can be LD_PRELOADed +// against non-pthreads apps. +//------------------------------------------------------------------- + +#ifndef GOOGLE_MAYBE_THREADS_H_ +#define GOOGLE_MAYBE_THREADS_H_ + +#ifdef HAVE_PTHREAD +#include +#endif + +int perftools_pthread_key_create(pthread_key_t *key, + void (*destr_function) (void *)); +int perftools_pthread_key_delete(pthread_key_t key); +void *perftools_pthread_getspecific(pthread_key_t key); +int perftools_pthread_setspecific(pthread_key_t key, void *val); +int perftools_pthread_once(pthread_once_t *ctl, + void (*init_routine) (void)); + +// Our wrapper for pthread_atfork. Does _nothing_ when there are no +// threads. See static_vars.cc:SetupAtForkLocksHandler for only user +// of this. +void perftools_pthread_atfork(void (*before)(), + void (*parent_after)(), + void (*child_after)()); + +#endif /* GOOGLE_MAYBE_THREADS_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/memfs_malloc.cc b/trunk/3rdparty/gperftools-2-fit/src/memfs_malloc.cc new file mode 100644 index 000000000..ef0ba5cca --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/memfs_malloc.cc @@ -0,0 +1,279 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 +#include // for errno, EINVAL +#include // for PRId64 +#include // for PATH_MAX +#include // for size_t, NULL +#ifdef HAVE_STDINT_H +#include // for int64_t, uintptr_t +#endif +#include // for snprintf +#include // for mkstemp +#include // for strerror +#include // for mmap, MAP_FAILED, etc +#include // for fstatfs, statfs +#include // for ftruncate, off_t, unlink +#include // for operator new +#include + +#include +#include "base/basictypes.h" +#include "base/googleinit.h" +#include "base/sysinfo.h" +#include "internal_logging.h" + +// TODO(sanjay): Move the code below into the tcmalloc namespace +using tcmalloc::kLog; +using tcmalloc::kCrash; +using tcmalloc::Log; +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"); +DEFINE_int64(memfs_malloc_limit_mb, + EnvToInt("TCMALLOC_MEMFS_LIMIT_MB", 0), + "Limit total allocation size to the " + "specified number of MiB. 0 == no limit."); +DEFINE_bool(memfs_malloc_abort_on_fail, + EnvToBool("TCMALLOC_MEMFS_ABORT_ON_FAIL", false), + "abort() whenever memfs_malloc fails to satisfy an allocation " + "for any reason."); +DEFINE_bool(memfs_malloc_ignore_mmap_fail, + EnvToBool("TCMALLOC_MEMFS_IGNORE_MMAP_FAIL", false), + "Ignore failures from mmap"); +DEFINE_bool(memfs_malloc_map_private, + EnvToBool("TCMALLOC_MEMFS_MAP_PRIVATE", false), + "Use MAP_PRIVATE with mmap"); +DEFINE_bool(memfs_malloc_disable_fallback, + EnvToBool("TCMALLOC_MEMFS_DISABLE_FALLBACK", false), + "If we run out of hugepage memory don't fallback to default " + "allocator."); + +// Hugetlbfs based allocator for tcmalloc +class HugetlbSysAllocator: public SysAllocator { +public: + explicit HugetlbSysAllocator(SysAllocator* fallback) + : failed_(true), // To disable allocator until Initialize() is called. + big_page_size_(0), + hugetlb_fd_(-1), + hugetlb_base_(0), + fallback_(fallback) { + } + + void* Alloc(size_t size, size_t *actual_size, size_t alignment); + bool Initialize(); + + bool failed_; // Whether failed to allocate memory. + +private: + void* AllocInternal(size_t size, size_t *actual_size, size_t alignment); + + int64 big_page_size_; + int hugetlb_fd_; // file descriptor for hugetlb + off_t hugetlb_base_; + + SysAllocator* fallback_; // Default system allocator to fall back to. +}; +static union { + char buf[sizeof(HugetlbSysAllocator)]; + void *ptr; +} hugetlb_space; + +// 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) { + if (!FLAGS_memfs_malloc_disable_fallback && failed_) { + return fallback_->Alloc(size, actual_size, alignment); + } + + // We don't respond to allocation requests smaller than big_page_size_ unless + // the caller is ok to take more than they asked for. Used by MetaDataAlloc. + if (!FLAGS_memfs_malloc_disable_fallback && + actual_size == NULL && size < big_page_size_) { + return fallback_->Alloc(size, actual_size, alignment); + } + + // Enforce huge page alignment. Be careful to deal with overflow. + size_t new_alignment = alignment; + if (new_alignment < big_page_size_) new_alignment = big_page_size_; + size_t aligned_size = ((size + new_alignment - 1) / + new_alignment) * new_alignment; + if (!FLAGS_memfs_malloc_disable_fallback && aligned_size < size) { + return fallback_->Alloc(size, actual_size, alignment); + } + + void* result = AllocInternal(aligned_size, actual_size, new_alignment); + if (result != NULL) { + return result; + } else if (FLAGS_memfs_malloc_disable_fallback) { + return NULL; + } + Log(kLog, __FILE__, __LINE__, + "HugetlbSysAllocator: (failed, allocated)", failed_, hugetlb_base_); + if (FLAGS_memfs_malloc_abort_on_fail) { + Log(kCrash, __FILE__, __LINE__, + "memfs_malloc_abort_on_fail is set"); + } + return fallback_->Alloc(size, actual_size, alignment); +} + +void* HugetlbSysAllocator::AllocInternal(size_t size, size_t* actual_size, + size_t alignment) { + // Ask for extra memory if alignment > pagesize + size_t extra = 0; + if (alignment > big_page_size_) { + extra = alignment - big_page_size_; + } + + // Test if this allocation would put us over the limit. + off_t limit = FLAGS_memfs_malloc_limit_mb*1024*1024; + if (limit > 0 && hugetlb_base_ + size + extra > limit) { + // Disable the allocator when there's less than one page left. + if (limit - hugetlb_base_ < big_page_size_) { + Log(kLog, __FILE__, __LINE__, "reached memfs_malloc_limit_mb"); + failed_ = true; + } + else { + Log(kLog, __FILE__, __LINE__, + "alloc too large (size, bytes left)", size, limit-hugetlb_base_); + } + return NULL; + } + + // 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) { + Log(kLog, __FILE__, __LINE__, + "ftruncate failed", strerror(errno)); + failed_ = true; + return NULL; + } + + // Note: size + extra does not overflow since: + // size + alignment < (1<(MAP_FAILED)) { + if (!FLAGS_memfs_malloc_ignore_mmap_fail) { + Log(kLog, __FILE__, __LINE__, + "mmap failed (size, error)", size + extra, strerror(errno)); + failed_ = true; + } + return NULL; + } + uintptr_t ptr = reinterpret_cast(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(ptr); +} + +bool HugetlbSysAllocator::Initialize() { + char path[PATH_MAX]; + const int pathlen = FLAGS_memfs_malloc_path.size(); + if (pathlen + 8 > sizeof(path)) { + Log(kCrash, __FILE__, __LINE__, "XX fatal: memfs_malloc_path too long"); + return false; + } + memcpy(path, FLAGS_memfs_malloc_path.data(), pathlen); + memcpy(path + pathlen, ".XXXXXX", 8); // Also copies terminating \0 + + int hugetlb_fd = mkstemp(path); + if (hugetlb_fd == -1) { + Log(kLog, __FILE__, __LINE__, + "warning: unable to create memfs_malloc_path", + path, strerror(errno)); + return false; + } + + // Cleanup memory on process exit + if (unlink(path) == -1) { + Log(kCrash, __FILE__, __LINE__, + "fatal: error unlinking memfs_malloc_path", path, strerror(errno)); + return false; + } + + // Use fstatfs to figure out the default page size for memfs + struct statfs sfs; + if (fstatfs(hugetlb_fd, &sfs) == -1) { + Log(kCrash, __FILE__, __LINE__, + "fatal: error fstatfs of memfs_malloc_path", strerror(errno)); + return false; + } + int64 page_size = sfs.f_bsize; + + hugetlb_fd_ = hugetlb_fd; + big_page_size_ = page_size; + failed_ = false; + return true; +} + +REGISTER_MODULE_INITIALIZER(memfs_malloc, { + if (FLAGS_memfs_malloc_path.length()) { + SysAllocator* alloc = MallocExtension::instance()->GetSystemAllocator(); + HugetlbSysAllocator* hp = + new (hugetlb_space.buf) HugetlbSysAllocator(alloc); + if (hp->Initialize()) { + MallocExtension::instance()->SetSystemAllocator(hp); + } + } +}); + +#endif /* ifdef __linux */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.cc b/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.cc new file mode 100644 index 000000000..5fb17d3ba --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.cc @@ -0,0 +1,838 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Maxim Lifantsev + */ + +// +// Background and key design points of MemoryRegionMap. +// +// MemoryRegionMap is a low-level module with quite atypical requirements that +// result in some degree of non-triviality of the implementation and design. +// +// MemoryRegionMap collects info about *all* memory regions created with +// mmap, munmap, mremap, sbrk. +// They key word above is 'all': all that are happening in a process +// during its lifetime frequently starting even before global object +// constructor execution. +// +// This is needed by the primary client of MemoryRegionMap: +// HeapLeakChecker uses the regions and the associated stack traces +// to figure out what part of the memory is the heap: +// if MemoryRegionMap were to miss some (early) regions, leak checking would +// stop working correctly. +// +// To accomplish the goal of functioning before/during global object +// constructor execution MemoryRegionMap is done as a singleton service +// that relies on own on-demand initialized static constructor-less data, +// and only relies on other low-level modules that can also function properly +// even before global object constructors run. +// +// Accomplishing the goal of collecting data about all mmap, munmap, mremap, +// sbrk occurrences is a more involved: conceptually to do this one needs to +// record some bits of data in particular about any mmap or sbrk call, +// but to do that one needs to allocate memory for that data at some point, +// but all memory allocations in the end themselves come from an mmap +// or sbrk call (that's how the address space of the process grows). +// +// Also note that we need to do all the above recording from +// within an mmap/sbrk hook which is sometimes/frequently is made by a memory +// allocator, including the allocator MemoryRegionMap itself must rely on. +// In the case of heap-checker usage this includes even the very first +// mmap/sbrk call happening in the program: heap-checker gets activated due to +// a link-time installed mmap/sbrk hook and it initializes MemoryRegionMap +// and asks it to record info about this very first call right from that +// very first hook invocation. +// +// MemoryRegionMap is doing its memory allocations via LowLevelAlloc: +// unlike more complex standard memory allocator, LowLevelAlloc cooperates with +// MemoryRegionMap by not holding any of its own locks while it calls mmap +// to get memory, thus we are able to call LowLevelAlloc from +// our mmap/sbrk hooks without causing a deadlock in it. +// For the same reason of deadlock prevention the locking in MemoryRegionMap +// itself is write-recursive which is an exception to Google's mutex usage. +// +// We still need to break the infinite cycle of mmap calling our hook, +// which asks LowLevelAlloc for memory to record this mmap, +// which (sometimes) causes mmap, which calls our hook, and so on. +// We do this as follows: on a recursive call of MemoryRegionMap's +// mmap/sbrk/mremap hook we record the data about the allocation in a +// static fixed-sized stack (saved_regions and saved_buckets), when the +// recursion unwinds but before returning from the outer hook call we unwind +// this stack and move the data from saved_regions and saved_buckets to its +// permanent place in the RegionSet and "bucket_table" respectively, +// which can cause more allocations and mmap-s and recursion and unwinding, +// but the whole process ends eventually due to the fact that for the small +// allocations we are doing LowLevelAlloc reuses one mmap call and parcels out +// the memory it created to satisfy several of our allocation requests. +// + +// ========================================================================= // + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif +#ifdef HAVE_MMAP +#include +#elif !defined(MAP_FAILED) +#define MAP_FAILED -1 // the only thing we need from mman.h +#endif +#ifdef HAVE_PTHREAD +#include // for pthread_t, pthread_self() +#endif +#include + +#include +#include + +#include "memory_region_map.h" + +#include "base/googleinit.h" +#include "base/logging.h" +#include "base/low_level_alloc.h" +#include "malloc_hook-inl.h" + +#include +#include + +// MREMAP_FIXED is a linux extension. How it's used in this file, +// setting it to 0 is equivalent to saying, "This feature isn't +// supported", which is right. +#ifndef MREMAP_FIXED +# define MREMAP_FIXED 0 +#endif + +using std::max; + +// ========================================================================= // + +int MemoryRegionMap::client_count_ = 0; +int MemoryRegionMap::max_stack_depth_ = 0; +MemoryRegionMap::RegionSet* MemoryRegionMap::regions_ = NULL; +LowLevelAlloc::Arena* MemoryRegionMap::arena_ = NULL; +SpinLock MemoryRegionMap::lock_(SpinLock::LINKER_INITIALIZED); +SpinLock MemoryRegionMap::owner_lock_( // ACQUIRED_AFTER(lock_) + SpinLock::LINKER_INITIALIZED); +int MemoryRegionMap::recursion_count_ = 0; // GUARDED_BY(owner_lock_) +pthread_t MemoryRegionMap::lock_owner_tid_; // GUARDED_BY(owner_lock_) +int64 MemoryRegionMap::map_size_ = 0; +int64 MemoryRegionMap::unmap_size_ = 0; +HeapProfileBucket** MemoryRegionMap::bucket_table_ = NULL; // GUARDED_BY(lock_) +int MemoryRegionMap::num_buckets_ = 0; // GUARDED_BY(lock_) +int MemoryRegionMap::saved_buckets_count_ = 0; // GUARDED_BY(lock_) +HeapProfileBucket MemoryRegionMap::saved_buckets_[20]; // GUARDED_BY(lock_) + +// GUARDED_BY(lock_) +const void* MemoryRegionMap::saved_buckets_keys_[20][kMaxStackDepth]; + +// ========================================================================= // + +// Simple hook into execution of global object constructors, +// so that we do not call pthread_self() when it does not yet work. +static bool libpthread_initialized = false; +REGISTER_MODULE_INITIALIZER(libpthread_initialized_setter, + libpthread_initialized = true); + +static inline bool current_thread_is(pthread_t should_be) { + // Before main() runs, there's only one thread, so we're always that thread + if (!libpthread_initialized) return true; + // this starts working only sometime well into global constructor execution: + return pthread_equal(pthread_self(), should_be); +} + +// ========================================================================= // + +// Constructor-less place-holder to store a RegionSet in. +union MemoryRegionMap::RegionSetRep { + char rep[sizeof(RegionSet)]; + void* align_it; // do not need a better alignment for 'rep' than this + RegionSet* region_set() { return reinterpret_cast(rep); } +}; + +// The bytes where MemoryRegionMap::regions_ will point to. +// We use RegionSetRep with noop c-tor so that global construction +// does not interfere. +static MemoryRegionMap::RegionSetRep regions_rep; + +// ========================================================================= // + +// Has InsertRegionLocked been called recursively +// (or rather should we *not* use regions_ to record a hooked mmap). +static bool recursive_insert = false; + +void MemoryRegionMap::Init(int max_stack_depth, bool use_buckets) { + RAW_VLOG(10, "MemoryRegionMap Init"); + RAW_CHECK(max_stack_depth >= 0, ""); + // Make sure we don't overflow the memory in region stacks: + RAW_CHECK(max_stack_depth <= kMaxStackDepth, + "need to increase kMaxStackDepth?"); + Lock(); + client_count_ += 1; + max_stack_depth_ = max(max_stack_depth_, max_stack_depth); + if (client_count_ > 1) { + // not first client: already did initialization-proper + Unlock(); + RAW_VLOG(10, "MemoryRegionMap Init increment done"); + return; + } + // Set our hooks and make sure they were installed: + RAW_CHECK(MallocHook::AddMmapHook(&MmapHook), ""); + RAW_CHECK(MallocHook::AddMremapHook(&MremapHook), ""); + RAW_CHECK(MallocHook::AddSbrkHook(&SbrkHook), ""); + RAW_CHECK(MallocHook::AddMunmapHook(&MunmapHook), ""); + // We need to set recursive_insert since the NewArena call itself + // will already do some allocations with mmap which our hooks will catch + // recursive_insert allows us to buffer info about these mmap calls. + // Note that Init() can be (and is) sometimes called + // already from within an mmap/sbrk hook. + recursive_insert = true; + arena_ = LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena()); + recursive_insert = false; + HandleSavedRegionsLocked(&InsertRegionLocked); // flush the buffered ones + // Can't instead use HandleSavedRegionsLocked(&DoInsertRegionLocked) before + // recursive_insert = false; as InsertRegionLocked will also construct + // regions_ on demand for us. + if (use_buckets) { + const int table_bytes = kHashTableSize * sizeof(*bucket_table_); + recursive_insert = true; + bucket_table_ = static_cast( + MyAllocator::Allocate(table_bytes)); + recursive_insert = false; + memset(bucket_table_, 0, table_bytes); + num_buckets_ = 0; + } + if (regions_ == NULL) { // init regions_ + InitRegionSetLocked(); + } + Unlock(); + RAW_VLOG(10, "MemoryRegionMap Init done"); +} + +bool MemoryRegionMap::Shutdown() { + RAW_VLOG(10, "MemoryRegionMap Shutdown"); + Lock(); + RAW_CHECK(client_count_ > 0, ""); + client_count_ -= 1; + if (client_count_ != 0) { // not last client; need not really shutdown + Unlock(); + RAW_VLOG(10, "MemoryRegionMap Shutdown decrement done"); + return true; + } + if (bucket_table_ != NULL) { + for (int i = 0; i < kHashTableSize; i++) { + for (HeapProfileBucket* curr = bucket_table_[i]; curr != 0; /**/) { + HeapProfileBucket* bucket = curr; + curr = curr->next; + MyAllocator::Free(bucket->stack, 0); + MyAllocator::Free(bucket, 0); + } + } + MyAllocator::Free(bucket_table_, 0); + num_buckets_ = 0; + bucket_table_ = NULL; + } + RAW_CHECK(MallocHook::RemoveMmapHook(&MmapHook), ""); + RAW_CHECK(MallocHook::RemoveMremapHook(&MremapHook), ""); + RAW_CHECK(MallocHook::RemoveSbrkHook(&SbrkHook), ""); + RAW_CHECK(MallocHook::RemoveMunmapHook(&MunmapHook), ""); + if (regions_) regions_->~RegionSet(); + regions_ = NULL; + bool deleted_arena = LowLevelAlloc::DeleteArena(arena_); + if (deleted_arena) { + arena_ = 0; + } else { + RAW_LOG(WARNING, "Can't delete LowLevelAlloc arena: it's being used"); + } + Unlock(); + RAW_VLOG(10, "MemoryRegionMap Shutdown done"); + return deleted_arena; +} + +bool MemoryRegionMap::IsRecordingLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + return client_count_ > 0; +} + +// Invariants (once libpthread_initialized is true): +// * While lock_ is not held, recursion_count_ is 0 (and +// lock_owner_tid_ is the previous owner, but we don't rely on +// that). +// * recursion_count_ and lock_owner_tid_ are only written while +// both lock_ and owner_lock_ are held. They may be read under +// just owner_lock_. +// * At entry and exit of Lock() and Unlock(), the current thread +// owns lock_ iff pthread_equal(lock_owner_tid_, pthread_self()) +// && recursion_count_ > 0. +void MemoryRegionMap::Lock() { + { + SpinLockHolder l(&owner_lock_); + if (recursion_count_ > 0 && current_thread_is(lock_owner_tid_)) { + RAW_CHECK(lock_.IsHeld(), "Invariants violated"); + recursion_count_++; + RAW_CHECK(recursion_count_ <= 5, + "recursive lock nesting unexpectedly deep"); + return; + } + } + lock_.Lock(); + { + SpinLockHolder l(&owner_lock_); + RAW_CHECK(recursion_count_ == 0, + "Last Unlock didn't reset recursion_count_"); + if (libpthread_initialized) + lock_owner_tid_ = pthread_self(); + recursion_count_ = 1; + } +} + +void MemoryRegionMap::Unlock() { + SpinLockHolder l(&owner_lock_); + RAW_CHECK(recursion_count_ > 0, "unlock when not held"); + RAW_CHECK(lock_.IsHeld(), + "unlock when not held, and recursion_count_ is wrong"); + RAW_CHECK(current_thread_is(lock_owner_tid_), "unlock by non-holder"); + recursion_count_--; + if (recursion_count_ == 0) { + lock_.Unlock(); + } +} + +bool MemoryRegionMap::LockIsHeld() { + SpinLockHolder l(&owner_lock_); + return lock_.IsHeld() && current_thread_is(lock_owner_tid_); +} + +const MemoryRegionMap::Region* +MemoryRegionMap::DoFindRegionLocked(uintptr_t addr) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + if (regions_ != NULL) { + Region sample; + sample.SetRegionSetKey(addr); + RegionSet::iterator region = regions_->lower_bound(sample); + if (region != regions_->end()) { + RAW_CHECK(addr <= region->end_addr, ""); + if (region->start_addr <= addr && addr < region->end_addr) { + return &(*region); + } + } + } + return NULL; +} + +bool MemoryRegionMap::FindRegion(uintptr_t addr, Region* result) { + Lock(); + const Region* region = DoFindRegionLocked(addr); + if (region != NULL) *result = *region; // create it as an independent copy + Unlock(); + return region != NULL; +} + +bool MemoryRegionMap::FindAndMarkStackRegion(uintptr_t stack_top, + Region* result) { + Lock(); + const Region* region = DoFindRegionLocked(stack_top); + if (region != NULL) { + RAW_VLOG(10, "Stack at %p is inside region %p..%p", + reinterpret_cast(stack_top), + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + const_cast(region)->set_is_stack(); // now we know + // cast is safe (set_is_stack does not change the set ordering key) + *result = *region; // create *result as an independent copy + } + Unlock(); + return region != NULL; +} + +HeapProfileBucket* MemoryRegionMap::GetBucket(int depth, + const void* const key[]) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + // Make hash-value + uintptr_t hash = 0; + for (int i = 0; i < depth; i++) { + hash += reinterpret_cast(key[i]); + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + + // Lookup stack trace in table + unsigned int hash_index = (static_cast(hash)) % kHashTableSize; + for (HeapProfileBucket* bucket = bucket_table_[hash_index]; + bucket != 0; + bucket = bucket->next) { + if ((bucket->hash == hash) && (bucket->depth == depth) && + std::equal(key, key + depth, bucket->stack)) { + return bucket; + } + } + + // Create new bucket + const size_t key_size = sizeof(key[0]) * depth; + HeapProfileBucket* bucket; + if (recursive_insert) { // recursion: save in saved_buckets_ + const void** key_copy = saved_buckets_keys_[saved_buckets_count_]; + std::copy(key, key + depth, key_copy); + bucket = &saved_buckets_[saved_buckets_count_]; + memset(bucket, 0, sizeof(*bucket)); + ++saved_buckets_count_; + bucket->stack = key_copy; + bucket->next = NULL; + } else { + recursive_insert = true; + const void** key_copy = static_cast( + MyAllocator::Allocate(key_size)); + recursive_insert = false; + std::copy(key, key + depth, key_copy); + recursive_insert = true; + bucket = static_cast( + MyAllocator::Allocate(sizeof(HeapProfileBucket))); + recursive_insert = false; + memset(bucket, 0, sizeof(*bucket)); + bucket->stack = key_copy; + bucket->next = bucket_table_[hash_index]; + } + bucket->hash = hash; + bucket->depth = depth; + bucket_table_[hash_index] = bucket; + ++num_buckets_; + return bucket; +} + +MemoryRegionMap::RegionIterator MemoryRegionMap::BeginRegionLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + RAW_CHECK(regions_ != NULL, ""); + return regions_->begin(); +} + +MemoryRegionMap::RegionIterator MemoryRegionMap::EndRegionLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + RAW_CHECK(regions_ != NULL, ""); + return regions_->end(); +} + +inline void MemoryRegionMap::DoInsertRegionLocked(const Region& region) { + RAW_VLOG(12, "Inserting region %p..%p from %p", + reinterpret_cast(region.start_addr), + reinterpret_cast(region.end_addr), + reinterpret_cast(region.caller())); + RegionSet::const_iterator i = regions_->lower_bound(region); + if (i != regions_->end() && i->start_addr <= region.start_addr) { + RAW_DCHECK(region.end_addr <= i->end_addr, ""); // lower_bound ensures this + return; // 'region' is a subset of an already recorded region; do nothing + // We can be stricter and allow this only when *i has been created via + // an mmap with MAP_NORESERVE flag set. + } + if (DEBUG_MODE) { + RAW_CHECK(i == regions_->end() || !region.Overlaps(*i), + "Wow, overlapping memory regions"); + Region sample; + sample.SetRegionSetKey(region.start_addr); + i = regions_->lower_bound(sample); + RAW_CHECK(i == regions_->end() || !region.Overlaps(*i), + "Wow, overlapping memory regions"); + } + region.AssertIsConsistent(); // just making sure + // This inserts and allocates permanent storage for region + // and its call stack data: it's safe to do it now: + regions_->insert(region); + RAW_VLOG(12, "Inserted region %p..%p :", + reinterpret_cast(region.start_addr), + reinterpret_cast(region.end_addr)); + if (VLOG_IS_ON(12)) LogAllLocked(); +} + +// These variables are local to MemoryRegionMap::InsertRegionLocked() +// and MemoryRegionMap::HandleSavedRegionsLocked() +// and are file-level to ensure that they are initialized at load time. + +// Number of unprocessed region inserts. +static int saved_regions_count = 0; + +// Unprocessed inserts (must be big enough to hold all allocations that can +// be caused by a InsertRegionLocked call). +// Region has no constructor, so that c-tor execution does not interfere +// with the any-time use of the static memory behind saved_regions. +static MemoryRegionMap::Region saved_regions[20]; + +inline void MemoryRegionMap::HandleSavedRegionsLocked( + void (*insert_func)(const Region& region)) { + while (saved_regions_count > 0) { + // Making a local-var copy of the region argument to insert_func + // including its stack (w/o doing any memory allocations) is important: + // in many cases the memory in saved_regions + // will get written-to during the (*insert_func)(r) call below. + Region r = saved_regions[--saved_regions_count]; + (*insert_func)(r); + } +} + +void MemoryRegionMap::RestoreSavedBucketsLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + while (saved_buckets_count_ > 0) { + HeapProfileBucket bucket = saved_buckets_[--saved_buckets_count_]; + unsigned int hash_index = + static_cast(bucket.hash) % kHashTableSize; + bool is_found = false; + for (HeapProfileBucket* curr = bucket_table_[hash_index]; + curr != 0; + curr = curr->next) { + if ((curr->hash == bucket.hash) && (curr->depth == bucket.depth) && + std::equal(bucket.stack, bucket.stack + bucket.depth, curr->stack)) { + curr->allocs += bucket.allocs; + curr->alloc_size += bucket.alloc_size; + curr->frees += bucket.frees; + curr->free_size += bucket.free_size; + is_found = true; + break; + } + } + if (is_found) continue; + + const size_t key_size = sizeof(bucket.stack[0]) * bucket.depth; + const void** key_copy = static_cast( + MyAllocator::Allocate(key_size)); + std::copy(bucket.stack, bucket.stack + bucket.depth, key_copy); + HeapProfileBucket* new_bucket = static_cast( + MyAllocator::Allocate(sizeof(HeapProfileBucket))); + memset(new_bucket, 0, sizeof(*new_bucket)); + new_bucket->hash = bucket.hash; + new_bucket->depth = bucket.depth; + new_bucket->stack = key_copy; + new_bucket->next = bucket_table_[hash_index]; + bucket_table_[hash_index] = new_bucket; + ++num_buckets_; + } +} + +inline void MemoryRegionMap::InitRegionSetLocked() { + RAW_VLOG(12, "Initializing region set"); + regions_ = regions_rep.region_set(); + recursive_insert = true; + new (regions_) RegionSet(); + HandleSavedRegionsLocked(&DoInsertRegionLocked); + recursive_insert = false; +} + +inline void MemoryRegionMap::InsertRegionLocked(const Region& region) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + // We can be called recursively, because RegionSet constructor + // and DoInsertRegionLocked() (called below) can call the allocator. + // recursive_insert tells us if that's the case. When this happens, + // region insertion information is recorded in saved_regions[], + // and taken into account when the recursion unwinds. + // Do the insert: + if (recursive_insert) { // recursion: save in saved_regions + RAW_VLOG(12, "Saving recursive insert of region %p..%p from %p", + reinterpret_cast(region.start_addr), + reinterpret_cast(region.end_addr), + reinterpret_cast(region.caller())); + RAW_CHECK(saved_regions_count < arraysize(saved_regions), ""); + // Copy 'region' to saved_regions[saved_regions_count] + // together with the contents of its call_stack, + // then increment saved_regions_count. + saved_regions[saved_regions_count++] = region; + } else { // not a recusrive call + if (regions_ == NULL) { // init regions_ + InitRegionSetLocked(); + } + recursive_insert = true; + // Do the actual insertion work to put new regions into regions_: + DoInsertRegionLocked(region); + HandleSavedRegionsLocked(&DoInsertRegionLocked); + recursive_insert = false; + } +} + +// We strip out different number of stack frames in debug mode +// because less inlining happens in that case +#ifdef NDEBUG +static const int kStripFrames = 1; +#else +static const int kStripFrames = 3; +#endif + +void MemoryRegionMap::RecordRegionAddition(const void* start, size_t size) { + // Record start/end info about this memory acquisition call in a new region: + Region region; + region.Create(start, size); + // First get the call stack info into the local varible 'region': + int depth = 0; + // NOTE: libunwind also does mmap and very much likely while holding + // it's own lock(s). So some threads may first take libunwind lock, + // and then take region map lock (necessary to record mmap done from + // inside libunwind). On the other hand other thread(s) may do + // normal mmap. Which would call this method to record it. Which + // would then proceed with installing that record to region map + // while holding region map lock. That may cause mmap from our own + // internal allocators, so attempt to unwind in this case may cause + // reverse order of taking libuwind and region map locks. Which is + // obvious deadlock. + // + // Thankfully, we can easily detect if we're holding region map lock + // and avoid recording backtrace in this (rare and largely + // irrelevant) case. By doing this we "declare" that thread needing + // both locks must take region map lock last. In other words we do + // not allow taking libuwind lock when we already have region map + // lock. Note, this is generally impossible when somebody tries to + // mix cpu profiling and heap checking/profiling, because cpu + // profiler grabs backtraces at arbitrary places. But at least such + // combination is rarer and less relevant. + if (max_stack_depth_ > 0 && !LockIsHeld()) { + depth = MallocHook::GetCallerStackTrace(const_cast(region.call_stack), + max_stack_depth_, kStripFrames + 1); + } + region.set_call_stack_depth(depth); // record stack info fully + RAW_VLOG(10, "New global region %p..%p from %p", + reinterpret_cast(region.start_addr), + reinterpret_cast(region.end_addr), + reinterpret_cast(region.caller())); + // Note: none of the above allocates memory. + Lock(); // recursively lock + map_size_ += size; + InsertRegionLocked(region); + // This will (eventually) allocate storage for and copy over the stack data + // from region.call_stack_data_ that is pointed by region.call_stack(). + if (bucket_table_ != NULL) { + HeapProfileBucket* b = GetBucket(depth, region.call_stack); + ++b->allocs; + b->alloc_size += size; + if (!recursive_insert) { + recursive_insert = true; + RestoreSavedBucketsLocked(); + recursive_insert = false; + } + } + Unlock(); +} + +void MemoryRegionMap::RecordRegionRemoval(const void* start, size_t size) { + Lock(); + if (recursive_insert) { + // First remove the removed region from saved_regions, if it's + // there, to prevent overrunning saved_regions in recursive + // map/unmap call sequences, and also from later inserting regions + // which have already been unmapped. + uintptr_t start_addr = reinterpret_cast(start); + uintptr_t end_addr = start_addr + size; + int put_pos = 0; + int old_count = saved_regions_count; + for (int i = 0; i < old_count; ++i, ++put_pos) { + Region& r = saved_regions[i]; + if (r.start_addr == start_addr && r.end_addr == end_addr) { + // An exact match, so it's safe to remove. + RecordRegionRemovalInBucket(r.call_stack_depth, r.call_stack, size); + --saved_regions_count; + --put_pos; + RAW_VLOG(10, ("Insta-Removing saved region %p..%p; " + "now have %d saved regions"), + reinterpret_cast(start_addr), + reinterpret_cast(end_addr), + saved_regions_count); + } else { + if (put_pos < i) { + saved_regions[put_pos] = saved_regions[i]; + } + } + } + } + if (regions_ == NULL) { // We must have just unset the hooks, + // but this thread was already inside the hook. + Unlock(); + return; + } + if (!recursive_insert) { + HandleSavedRegionsLocked(&InsertRegionLocked); + } + // first handle adding saved regions if any + uintptr_t start_addr = reinterpret_cast(start); + uintptr_t end_addr = start_addr + size; + // subtract start_addr, end_addr from all the regions + RAW_VLOG(10, "Removing global region %p..%p; have %zu regions", + reinterpret_cast(start_addr), + reinterpret_cast(end_addr), + regions_->size()); + Region sample; + sample.SetRegionSetKey(start_addr); + // Only iterate over the regions that might overlap start_addr..end_addr: + for (RegionSet::iterator region = regions_->lower_bound(sample); + region != regions_->end() && region->start_addr < end_addr; + /*noop*/) { + RAW_VLOG(13, "Looking at region %p..%p", + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + if (start_addr <= region->start_addr && + region->end_addr <= end_addr) { // full deletion + RAW_VLOG(12, "Deleting region %p..%p", + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + region->end_addr - region->start_addr); + RegionSet::iterator d = region; + ++region; + regions_->erase(d); + continue; + } else if (region->start_addr < start_addr && + end_addr < region->end_addr) { // cutting-out split + RAW_VLOG(12, "Splitting region %p..%p in two", + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + end_addr - start_addr); + // Make another region for the start portion: + // The new region has to be the start portion because we can't + // just modify region->end_addr as it's the sorting key. + Region r = *region; + r.set_end_addr(start_addr); + InsertRegionLocked(r); + // cut *region from start: + const_cast(*region).set_start_addr(end_addr); + } else if (end_addr > region->start_addr && + start_addr <= region->start_addr) { // cut from start + RAW_VLOG(12, "Start-chopping region %p..%p", + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + end_addr - region->start_addr); + const_cast(*region).set_start_addr(end_addr); + } else if (start_addr > region->start_addr && + start_addr < region->end_addr) { // cut from end + RAW_VLOG(12, "End-chopping region %p..%p", + reinterpret_cast(region->start_addr), + reinterpret_cast(region->end_addr)); + RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack, + region->end_addr - start_addr); + // Can't just modify region->end_addr (it's the sorting key): + Region r = *region; + r.set_end_addr(start_addr); + RegionSet::iterator d = region; + ++region; + // It's safe to erase before inserting since r is independent of *d: + // r contains an own copy of the call stack: + regions_->erase(d); + InsertRegionLocked(r); + continue; + } + ++region; + } + RAW_VLOG(12, "Removed region %p..%p; have %zu regions", + reinterpret_cast(start_addr), + reinterpret_cast(end_addr), + regions_->size()); + if (VLOG_IS_ON(12)) LogAllLocked(); + unmap_size_ += size; + Unlock(); +} + +void MemoryRegionMap::RecordRegionRemovalInBucket(int depth, + const void* const stack[], + size_t size) { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + if (bucket_table_ == NULL) return; + HeapProfileBucket* b = GetBucket(depth, stack); + ++b->frees; + b->free_size += 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%" PRIxPTR " by %p when RAW_VLOG uses a safe + // snprintf reimplementation that does not malloc to pretty-print NULL + RAW_VLOG(10, "MMap = 0x%" PRIxPTR " of %zu at %" PRIu64 " " + "prot %d flags %d fd %d offs %" PRId64, + reinterpret_cast(result), size, + reinterpret_cast(start), prot, flags, fd, + static_cast(offset)); + if (result != reinterpret_cast(MAP_FAILED) && size != 0) { + RecordRegionAddition(result, size); + } +} + +void MemoryRegionMap::MunmapHook(const void* ptr, size_t size) { + RAW_VLOG(10, "MUnmap of %p %zu", ptr, size); + if (size != 0) { + RecordRegionRemoval(ptr, size); + } +} + +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(10, "MRemap = 0x%" PRIxPTR " of 0x%" PRIxPTR " %zu " + "to %zu flags %d new_addr=0x%" PRIxPTR, + (uintptr_t)result, (uintptr_t)old_addr, + old_size, new_size, flags, + flags & MREMAP_FIXED ? (uintptr_t)new_addr : 0); + if (result != reinterpret_cast(-1)) { + RecordRegionRemoval(old_addr, old_size); + RecordRegionAddition(result, new_size); + } +} + +void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) { + RAW_VLOG(10, "Sbrk = 0x%" PRIxPTR " of %zd", (uintptr_t)result, increment); + if (result != reinterpret_cast(-1)) { + if (increment > 0) { + void* new_end = sbrk(0); + RecordRegionAddition(result, reinterpret_cast(new_end) - + reinterpret_cast(result)); + } else if (increment < 0) { + void* new_end = sbrk(0); + RecordRegionRemoval(new_end, reinterpret_cast(result) - + reinterpret_cast(new_end)); + } + } +} + +void MemoryRegionMap::LogAllLocked() { + RAW_CHECK(LockIsHeld(), "should be held (by this thread)"); + RAW_LOG(INFO, "List of regions:"); + uintptr_t previous = 0; + for (RegionSet::const_iterator r = regions_->begin(); + r != regions_->end(); ++r) { + RAW_LOG(INFO, "Memory region 0x%" PRIxPTR "..0x%" PRIxPTR " " + "from 0x%" PRIxPTR " stack=%d", + r->start_addr, r->end_addr, r->caller(), r->is_stack); + RAW_CHECK(previous < r->end_addr, "wow, we messed up the set order"); + // this must be caused by uncontrolled recursive operations on regions_ + previous = r->end_addr; + } + RAW_LOG(INFO, "End of regions list"); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.h b/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.h new file mode 100644 index 000000000..c21fac3b3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/memory_region_map.h @@ -0,0 +1,416 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Maxim Lifantsev + */ + +#ifndef BASE_MEMORY_REGION_MAP_H_ +#define BASE_MEMORY_REGION_MAP_H_ + +#include + +#ifdef HAVE_PTHREAD +#include +#endif +#include +#include +#include "base/stl_allocator.h" +#include "base/spinlock.h" +#include "base/thread_annotations.h" +#include "base/low_level_alloc.h" +#include "heap-profile-stats.h" + +// TODO(maxim): add a unittest: +// execute a bunch of mmaps and compare memory map what strace logs +// execute a bunch of mmap/munmup and compare memory map with +// own accounting of what those mmaps generated + +// Thread-safe class to collect and query the map of all memory regions +// in a process that have been created with mmap, munmap, mremap, sbrk. +// For each memory region, we keep track of (and provide to users) +// the stack trace that allocated that memory region. +// The recorded stack trace depth is bounded by +// a user-supplied max_stack_depth parameter of Init(). +// After initialization with Init() +// (which can happened even before global object constructor execution) +// we collect the map by installing and monitoring MallocHook-s +// to mmap, munmap, mremap, sbrk. +// At any time one can query this map via provided interface. +// For more details on the design of MemoryRegionMap +// see the comment at the top of our .cc file. +class MemoryRegionMap { + private: + // Max call stack recording depth supported by Init(). Set it to be + // high enough for all our clients. Note: we do not define storage + // for this (doing that requires special handling in windows), so + // don't take the address of it! + static const int kMaxStackDepth = 32; + + // Size of the hash table of buckets. A structure of the bucket table is + // described in heap-profile-stats.h. + static const int kHashTableSize = 179999; + + public: + // interface ================================================================ + + // Every client of MemoryRegionMap must call Init() before first use, + // and Shutdown() after last use. This allows us to reference count + // this (singleton) class properly. MemoryRegionMap assumes it's the + // only client of MallocHooks, so a client can only register other + // MallocHooks after calling Init() and must unregister them before + // calling Shutdown(). + + // Initialize this module to record memory allocation stack traces. + // Stack traces that have more than "max_stack_depth" frames + // are automatically shrunk to "max_stack_depth" when they are recorded. + // Init() can be called more than once w/o harm, largest max_stack_depth + // will be the effective one. + // When "use_buckets" is true, then counts of mmap and munmap sizes will be + // recorded with each stack trace. If Init() is called more than once, then + // counting will be effective after any call contained "use_buckets" of true. + // It will install mmap, munmap, mremap, sbrk hooks + // and initialize arena_ and our hook and locks, hence one can use + // MemoryRegionMap::Lock()/Unlock() to manage the locks. + // Uses Lock/Unlock inside. + static void Init(int max_stack_depth, bool use_buckets); + + // Try to shutdown this module undoing what Init() did. + // Returns true iff could do full shutdown (or it was not attempted). + // Full shutdown is attempted when the number of Shutdown() calls equals + // the number of Init() calls. + static bool Shutdown(); + + // Return true if MemoryRegionMap is initialized and recording, i.e. when + // then number of Init() calls are more than the number of Shutdown() calls. + static bool IsRecordingLocked(); + + // Locks to protect our internal data structures. + // These also protect use of arena_ if our Init() has been done. + // The lock is recursive. + static void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_); + static void Unlock() UNLOCK_FUNCTION(lock_); + + // Returns true when the lock is held by this thread (for use in RAW_CHECK-s). + static bool LockIsHeld(); + + // Locker object that acquires the MemoryRegionMap::Lock + // for the duration of its lifetime (a C++ scope). + class LockHolder { + public: + LockHolder() { Lock(); } + ~LockHolder() { Unlock(); } + private: + DISALLOW_COPY_AND_ASSIGN(LockHolder); + }; + + // A memory region that we know about through malloc_hook-s. + // This is essentially an interface through which MemoryRegionMap + // exports the collected data to its clients. Thread-compatible. + struct Region { + uintptr_t start_addr; // region start address + uintptr_t end_addr; // region end address + int call_stack_depth; // number of caller stack frames that we saved + const void* call_stack[kMaxStackDepth]; // caller address stack array + // filled to call_stack_depth size + bool is_stack; // does this region contain a thread's stack: + // a user of MemoryRegionMap supplies this info + + // Convenience accessor for call_stack[0], + // i.e. (the program counter of) the immediate caller + // of this region's allocation function, + // but it also returns NULL when call_stack_depth is 0, + // i.e whe we weren't able to get the call stack. + // This usually happens in recursive calls, when the stack-unwinder + // calls mmap() which in turn calls the stack-unwinder. + uintptr_t caller() const { + return reinterpret_cast(call_stack_depth >= 1 + ? call_stack[0] : NULL); + } + + // Return true iff this region overlaps region x. + bool Overlaps(const Region& x) const { + return start_addr < x.end_addr && end_addr > x.start_addr; + } + + private: // helpers for MemoryRegionMap + friend class MemoryRegionMap; + + // The ways we create Region-s: + void Create(const void* start, size_t size) { + start_addr = reinterpret_cast(start); + end_addr = start_addr + size; + is_stack = false; // not a stack till marked such + call_stack_depth = 0; + AssertIsConsistent(); + } + void set_call_stack_depth(int depth) { + RAW_DCHECK(call_stack_depth == 0, ""); // only one such set is allowed + call_stack_depth = depth; + AssertIsConsistent(); + } + + // The ways we modify Region-s: + void set_is_stack() { is_stack = true; } + void set_start_addr(uintptr_t addr) { + start_addr = addr; + AssertIsConsistent(); + } + void set_end_addr(uintptr_t addr) { + end_addr = addr; + AssertIsConsistent(); + } + + // Verifies that *this contains consistent data, crashes if not the case. + void AssertIsConsistent() const { + RAW_DCHECK(start_addr < end_addr, ""); + RAW_DCHECK(call_stack_depth >= 0 && + call_stack_depth <= kMaxStackDepth, ""); + } + + // Post-default construction helper to make a Region suitable + // for searching in RegionSet regions_. + void SetRegionSetKey(uintptr_t addr) { + // make sure *this has no usable data: + if (DEBUG_MODE) memset(this, 0xFF, sizeof(*this)); + end_addr = addr; + } + + // Note: call_stack[kMaxStackDepth] as a member lets us make Region + // a simple self-contained struct with correctly behaving bit-vise copying. + // This simplifies the code of this module but wastes some memory: + // in most-often use case of this module (leak checking) + // only one call_stack element out of kMaxStackDepth is actually needed. + // Making the storage for call_stack variable-sized, + // substantially complicates memory management for the Region-s: + // as they need to be created and manipulated for some time + // w/o any memory allocations, yet are also given out to the users. + }; + + // Find the region that covers addr and write its data into *result if found, + // in which case *result gets filled so that it stays fully functional + // even when the underlying region gets removed from MemoryRegionMap. + // Returns success. Uses Lock/Unlock inside. + static bool FindRegion(uintptr_t addr, Region* result); + + // Find the region that contains stack_top, mark that region as + // a stack region, and write its data into *result if found, + // in which case *result gets filled so that it stays fully functional + // even when the underlying region gets removed from MemoryRegionMap. + // Returns success. Uses Lock/Unlock inside. + static bool FindAndMarkStackRegion(uintptr_t stack_top, Region* result); + + // Iterate over the buckets which store mmap and munmap counts per stack + // trace. It calls "callback" for each bucket, and passes "arg" to it. + template + static void IterateBuckets(void (*callback)(const HeapProfileBucket*, Type), + Type arg); + + // Get the bucket whose caller stack trace is "key". The stack trace is + // used to a depth of "depth" at most. The requested bucket is created if + // needed. + // The bucket table is described in heap-profile-stats.h. + static HeapProfileBucket* GetBucket(int depth, const void* const key[]); + + private: // our internal types ============================================== + + // Region comparator for sorting with STL + struct RegionCmp { + bool operator()(const Region& x, const Region& y) const { + return x.end_addr < y.end_addr; + } + }; + + // We allocate STL objects in our own arena. + struct MyAllocator { + static void *Allocate(size_t n) { + return LowLevelAlloc::AllocWithArena(n, arena_); + } + static void Free(const void *p, size_t /* n */) { + LowLevelAlloc::Free(const_cast(p)); + } + }; + + // Set of the memory regions + typedef std::set > RegionSet; + + public: // more in-depth interface ========================================== + + // STL iterator with values of Region + typedef RegionSet::const_iterator RegionIterator; + + // Return the begin/end iterators to all the regions. + // These need Lock/Unlock protection around their whole usage (loop). + // Even when the same thread causes modifications during such a loop + // (which are permitted due to recursive locking) + // the loop iterator will still be valid as long as its region + // has not been deleted, but EndRegionLocked should be + // re-evaluated whenever the set of regions has changed. + static RegionIterator BeginRegionLocked(); + static RegionIterator EndRegionLocked(); + + // Return the accumulated sizes of mapped and unmapped regions. + static int64 MapSize() { return map_size_; } + static int64 UnmapSize() { return unmap_size_; } + + // Effectively private type from our .cc ================================= + // public to let us declare global objects: + union RegionSetRep; + + private: + // representation =========================================================== + + // Counter of clients of this module that have called Init(). + static int client_count_; + + // Maximal number of caller stack frames to save (>= 0). + static int max_stack_depth_; + + // Arena used for our allocations in regions_. + static LowLevelAlloc::Arena* arena_; + + // Set of the mmap/sbrk/mremap-ed memory regions + // To be accessed *only* when Lock() is held. + // Hence we protect the non-recursive lock used inside of arena_ + // with our recursive Lock(). This lets a user prevent deadlocks + // when threads are stopped by TCMalloc_ListAllProcessThreads at random spots + // simply by acquiring our recursive Lock() before that. + static RegionSet* regions_; + + // Lock to protect regions_ and buckets_ variables and the data behind. + static SpinLock lock_; + // Lock to protect the recursive lock itself. + static SpinLock owner_lock_; + + // Recursion count for the recursive lock. + static int recursion_count_; + // The thread id of the thread that's inside the recursive lock. + static pthread_t lock_owner_tid_; + + // Total size of all mapped pages so far + static int64 map_size_; + // Total size of all unmapped pages so far + static int64 unmap_size_; + + // Bucket hash table which is described in heap-profile-stats.h. + static HeapProfileBucket** bucket_table_ GUARDED_BY(lock_); + static int num_buckets_ GUARDED_BY(lock_); + + // The following members are local to MemoryRegionMap::GetBucket() + // and MemoryRegionMap::HandleSavedBucketsLocked() + // and are file-level to ensure that they are initialized at load time. + // + // These are used as temporary storage to break the infinite cycle of mmap + // calling our hook which (sometimes) causes mmap. It must be a static + // fixed-size array. The size 20 is just an expected value for safety. + // The details are described in memory_region_map.cc. + + // Number of unprocessed bucket inserts. + static int saved_buckets_count_ GUARDED_BY(lock_); + + // Unprocessed inserts (must be big enough to hold all mmaps that can be + // caused by a GetBucket call). + // Bucket has no constructor, so that c-tor execution does not interfere + // with the any-time use of the static memory behind saved_buckets. + static HeapProfileBucket saved_buckets_[20] GUARDED_BY(lock_); + + static const void* saved_buckets_keys_[20][kMaxStackDepth] GUARDED_BY(lock_); + + // helpers ================================================================== + + // Helper for FindRegion and FindAndMarkStackRegion: + // returns the region covering 'addr' or NULL; assumes our lock_ is held. + static const Region* DoFindRegionLocked(uintptr_t addr); + + // Verifying wrapper around regions_->insert(region) + // To be called to do InsertRegionLocked's work only! + inline static void DoInsertRegionLocked(const Region& region); + // Handle regions saved by InsertRegionLocked into a tmp static array + // by calling insert_func on them. + inline static void HandleSavedRegionsLocked( + void (*insert_func)(const Region& region)); + + // Restore buckets saved in a tmp static array by GetBucket to the bucket + // table where all buckets eventually should be. + static void RestoreSavedBucketsLocked(); + + // Initialize RegionSet regions_. + inline static void InitRegionSetLocked(); + + // Wrapper around DoInsertRegionLocked + // that handles the case of recursive allocator calls. + inline static void InsertRegionLocked(const Region& region); + + // Record addition of a memory region at address "start" of size "size" + // (called from our mmap/mremap/sbrk hooks). + 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(const void* start, size_t size); + + // Record deletion of a memory region of size "size" in a bucket whose + // caller stack trace is "key". The stack trace is used to a depth of + // "depth" at most. + static void RecordRegionRemovalInBucket(int depth, + const void* const key[], + size_t size); + + // Hooks for MallocHook + static void MmapHook(const void* result, + const void* start, size_t size, + int prot, int flags, + int fd, off_t offset); + 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 + static void LogAllLocked(); + + DISALLOW_COPY_AND_ASSIGN(MemoryRegionMap); +}; + +template +void MemoryRegionMap::IterateBuckets( + void (*callback)(const HeapProfileBucket*, Type), Type callback_arg) { + for (int index = 0; index < kHashTableSize; index++) { + for (HeapProfileBucket* bucket = bucket_table_[index]; + bucket != NULL; + bucket = bucket->next) { + callback(bucket, callback_arg); + } + } +} + +#endif // BASE_MEMORY_REGION_MAP_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/packed-cache-inl.h b/trunk/3rdparty/gperftools-2-fit/src/packed-cache-inl.h new file mode 100644 index 000000000..7c216e5ae --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/packed-cache-inl.h @@ -0,0 +1,216 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Geoff Pike +// +// This file provides a minimal cache that can hold a pair +// with little if any wasted space. The types of the key and value +// must be unsigned integral types or at least have unsigned semantics +// for >>, casting, and similar operations. +// +// Synchronization is not provided. However, the cache is implemented +// as an array of cache entries whose type is chosen at compile time. +// If a[i] is atomic on your hardware for the chosen array type then +// raciness will not necessarily lead to bugginess. The cache entries +// must be large enough to hold a partial key and a value packed +// together. The partial keys are bit strings of length +// kKeybits - kHashbits, and the values are bit strings of length kValuebits. +// +// In an effort to use minimal space, every cache entry represents +// some pair; the class provides no way to mark a cache +// entry as empty or uninitialized. In practice, you may want to have +// reserved keys or values to get around this limitation. For example, in +// tcmalloc's PageID-to-sizeclass cache, a value of 0 is used as +// "unknown sizeclass." +// +// Usage Considerations +// -------------------- +// +// kHashbits controls the size of the cache. The best value for +// kHashbits will of course depend on the application. Perhaps try +// tuning the value of kHashbits by measuring different values on your +// favorite benchmark. Also remember not to be a pig; other +// programs that need resources may suffer if you are. +// +// The main uses for this class will be when performance is +// critical and there's a convenient type to hold the cache's +// entries. As described above, the number of bits required +// for a cache entry is (kKeybits - kHashbits) + kValuebits. Suppose +// kKeybits + kValuebits is 43. Then it probably makes sense to +// chose kHashbits >= 11 so that cache entries fit in a uint32. +// +// On the other hand, suppose kKeybits = kValuebits = 64. Then +// using this class may be less worthwhile. You'll probably +// be using 128 bits for each entry anyway, so maybe just pick +// a hash function, H, and use an array indexed by H(key): +// void Put(K key, V value) { a_[H(key)] = pair(key, value); } +// V GetOrDefault(K key, V default) { const pair &p = a_[H(key)]; ... } +// etc. +// +// Further Details +// --------------- +// +// For caches used only by one thread, the following is true: +// 1. For a cache c, +// (c.Put(key, value), c.GetOrDefault(key, 0)) == value +// and +// (c.Put(key, value), <...>, c.GetOrDefault(key, 0)) == value +// if the elided code contains no c.Put calls. +// +// 2. Has(key) will return false if no pair with that key +// has ever been Put. However, a newly initialized cache will have +// some pairs already present. When you create a new +// cache, you must specify an "initial value." The initialization +// procedure is equivalent to Clear(initial_value), which is +// equivalent to Put(k, initial_value) for all keys k from 0 to +// 2^kHashbits - 1. +// +// 3. If key and key' differ then the only way Put(key, value) may +// cause Has(key') to change is that Has(key') may change from true to +// false. Furthermore, a Put() call that doesn't change Has(key') +// doesn't change GetOrDefault(key', ...) either. +// +// Implementation details: +// +// This is a direct-mapped cache with 2^kHashbits entries; the hash +// function simply takes the low bits of the key. We store whole keys +// if a whole key plus a whole value fits in an entry. Otherwise, an +// entry is the high bits of a key and a value, packed together. +// E.g., a 20 bit key and a 7 bit value only require a uint16 for each +// entry if kHashbits >= 11. +// +// Alternatives to this scheme will be added as needed. + +#ifndef TCMALLOC_PACKED_CACHE_INL_H_ +#define TCMALLOC_PACKED_CACHE_INL_H_ + +#include "config.h" +#include // for size_t +#ifdef HAVE_STDINT_H +#include // for uintptr_t +#endif +#include "base/basictypes.h" +#include "common.h" +#include "internal_logging.h" + +// A safe way of doing "(1 << n) - 1" -- without worrying about overflow +// Note this will all be resolved to a constant expression at compile-time +#define N_ONES_(IntType, N) \ + ( (N) == 0 ? 0 : ((static_cast(1) << ((N)-1))-1 + \ + (static_cast(1) << ((N)-1))) ) + +// The types K and V provide upper bounds on the number of valid keys +// and values, but we explicitly require the keys to be less than +// 2^kKeybits and the values to be less than 2^kValuebits. The size +// of the table is controlled by kHashbits, and the type of each entry +// in the cache is uintptr_t (native machine word). See also the big +// comment at the top of the file. +template +class PackedCache { + public: + typedef uintptr_t T; + typedef uintptr_t K; + typedef uint32 V; +#ifdef TCMALLOC_SMALL_BUT_SLOW + // Decrease the size map cache if running in the small memory mode. + static const int kHashbits = 12; +#else + static const int kHashbits = 16; +#endif + static const int kValuebits = 7; + // one bit after value bits + static const int kInvalidMask = 0x80; + + explicit PackedCache() { + COMPILE_ASSERT(kKeybits + kValuebits + 1 <= 8 * sizeof(T), use_whole_keys); + COMPILE_ASSERT(kHashbits <= kKeybits, hash_function); + COMPILE_ASSERT(kHashbits >= kValuebits + 1, small_values_space); + Clear(); + } + + bool TryGet(K key, V* out) const { + // As with other code in this class, we touch array_ as few times + // as we can. Assuming entries are read atomically then certain + // races are harmless. + ASSERT(key == (key & kKeyMask)); + T hash = Hash(key); + T expected_entry = key; + expected_entry &= ~N_ONES_(T, kHashbits); + T entry = array_[hash]; + entry ^= expected_entry; + if (PREDICT_FALSE(entry >= (1 << kValuebits))) { + return false; + } + *out = static_cast(entry); + return true; + } + + void Clear() { + // sets 'invalid' bit in every byte, include value byte + memset(const_cast(array_), kInvalidMask, sizeof(array_)); + } + + void Put(K key, V value) { + ASSERT(key == (key & kKeyMask)); + ASSERT(value == (value & kValueMask)); + array_[Hash(key)] = KeyToUpper(key) | value; + } + + void Invalidate(K key) { + ASSERT(key == (key & kKeyMask)); + array_[Hash(key)] = KeyToUpper(key) | kInvalidMask; + } + + private: + // we just wipe all hash bits out of key. I.e. clear lower + // kHashbits. We rely on compiler knowing value of Hash(k). + static T KeyToUpper(K k) { + return static_cast(k) ^ Hash(k); + } + + static T Hash(K key) { + return static_cast(key) & N_ONES_(size_t, kHashbits); + } + + // For masking a K. + static const K kKeyMask = N_ONES_(K, kKeybits); + + // For masking a V or a T. + static const V kValueMask = N_ONES_(V, kValuebits); + + // array_ is the cache. Its elements are volatile because any + // thread can write any array element at any time. + volatile T array_[1 << kHashbits]; +}; + +#undef N_ONES_ + +#endif // TCMALLOC_PACKED_CACHE_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/page_heap.cc b/trunk/3rdparty/gperftools-2-fit/src/page_heap.cc new file mode 100644 index 000000000..44ad65447 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/page_heap.cc @@ -0,0 +1,718 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#include +#ifdef HAVE_INTTYPES_H +#include // for PRIuPTR +#endif +#include // for ENOMEM, errno +#include // for MallocRange, etc +#include "base/basictypes.h" +#include "base/commandlineflags.h" +#include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc +#include "page_heap_allocator.h" // for PageHeapAllocator +#include "static_vars.h" // for Static +#include "system-alloc.h" // for TCMalloc_SystemAlloc, etc + +DEFINE_double(tcmalloc_release_rate, + EnvToDouble("TCMALLOC_RELEASE_RATE", 1.0), + "Rate at which we release unused memory to the system. " + "Zero means we never release memory back to the system. " + "Increase this flag to return memory faster; decrease it " + "to return memory slower. Reasonable rates are in the " + "range [0,10]"); + +DEFINE_int64(tcmalloc_heap_limit_mb, + EnvToInt("TCMALLOC_HEAP_LIMIT_MB", 0), + "Limit total size of the process heap to the " + "specified number of MiB. " + "When we approach the limit the memory is released " + "to the system more aggressively (more minor page faults). " + "Zero means to allocate as long as system allows."); + +namespace tcmalloc { + +PageHeap::PageHeap() + : pagemap_(MetaDataAlloc), + scavenge_counter_(0), + // Start scavenging at kMaxPages list + release_index_(kMaxPages), + aggressive_decommit_(false) { + COMPILE_ASSERT(kClassSizesMax <= (1 << PageMapCache::kValuebits), valuebits); + for (int i = 0; i < kMaxPages; i++) { + DLL_Init(&free_[i].normal); + DLL_Init(&free_[i].returned); + } +} + +Span* PageHeap::SearchFreeAndLargeLists(Length n) { + ASSERT(Check()); + ASSERT(n > 0); + + // Find first size >= n that has a non-empty list + for (Length s = n; s <= kMaxPages; s++) { + Span* ll = &free_[s - 1].normal; + // If we're lucky, ll is non-empty, meaning it has a suitable span. + if (!DLL_IsEmpty(ll)) { + ASSERT(ll->next->location == Span::ON_NORMAL_FREELIST); + return Carve(ll->next, n); + } + // Alternatively, maybe there's a usable returned span. + ll = &free_[s - 1].returned; + if (!DLL_IsEmpty(ll)) { + // We did not call EnsureLimit before, to avoid releasing the span + // that will be taken immediately back. + // Calling EnsureLimit here is not very expensive, as it fails only if + // there is no more normal spans (and it fails efficiently) + // or SystemRelease does not work (there is probably no returned spans). + if (EnsureLimit(n)) { + // ll may have became empty due to coalescing + if (!DLL_IsEmpty(ll)) { + ASSERT(ll->next->location == Span::ON_RETURNED_FREELIST); + return Carve(ll->next, n); + } + } + } + } + // No luck in free lists, our last chance is in a larger class. + return AllocLarge(n); // May be NULL +} + +static const size_t kForcedCoalesceInterval = 128*1024*1024; + +Span* PageHeap::New(Length n) { + ASSERT(Check()); + ASSERT(n > 0); + + Span* result = SearchFreeAndLargeLists(n); + if (result != NULL) + return result; + + if (stats_.free_bytes != 0 && stats_.unmapped_bytes != 0 + && stats_.free_bytes + stats_.unmapped_bytes >= stats_.system_bytes / 4 + && (stats_.system_bytes / kForcedCoalesceInterval + != (stats_.system_bytes + (n << kPageShift)) / kForcedCoalesceInterval)) { + // We're about to grow heap, but there are lots of free pages. + // tcmalloc's design decision to keep unmapped and free spans + // separately and never coalesce them means that sometimes there + // can be free pages span of sufficient size, but it consists of + // "segments" of different type so page heap search cannot find + // it. In order to prevent growing heap and wasting memory in such + // case we're going to unmap all free pages. So that all free + // spans are maximally coalesced. + // + // We're also limiting 'rate' of going into this path to be at + // most once per 128 megs of heap growth. Otherwise programs that + // grow heap frequently (and that means by small amount) could be + // penalized with higher count of minor page faults. + // + // See also large_heap_fragmentation_unittest.cc and + // https://code.google.com/p/gperftools/issues/detail?id=368 + ReleaseAtLeastNPages(static_cast(0x7fffffff)); + + // then try again. If we are forced to grow heap because of large + // spans fragmentation and not because of problem described above, + // then at the very least we've just unmapped free but + // insufficiently big large spans back to OS. So in case of really + // unlucky memory fragmentation we'll be consuming virtual address + // space, but not real memory + result = SearchFreeAndLargeLists(n); + if (result != NULL) return result; + } + + // Grow the heap and try again. + if (!GrowHeap(n)) { + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); + ASSERT(Check()); + // underlying SysAllocator likely set ENOMEM but we can get here + // due to EnsureLimit so we set it here too. + // + // Setting errno to ENOMEM here allows us to avoid dealing with it + // in fast-path. + errno = ENOMEM; + return NULL; + } + return SearchFreeAndLargeLists(n); +} + +Span* PageHeap::AllocLarge(Length n) { + Span *best = NULL; + Span *best_normal = NULL; + + // Create a Span to use as an upper bound. + Span bound; + bound.start = 0; + bound.length = n; + + // First search the NORMAL spans.. + SpanSet::iterator place = large_normal_.upper_bound(SpanPtrWithLength(&bound)); + if (place != large_normal_.end()) { + best = place->span; + best_normal = best; + ASSERT(best->location == Span::ON_NORMAL_FREELIST); + } + + // Try to find better fit from RETURNED spans. + place = large_returned_.upper_bound(SpanPtrWithLength(&bound)); + if (place != large_returned_.end()) { + Span *c = place->span; + ASSERT(c->location == Span::ON_RETURNED_FREELIST); + if (best_normal == NULL + || c->length < best->length + || (c->length == best->length && c->start < best->start)) + best = place->span; + } + + if (best == best_normal) { + return best == NULL ? NULL : Carve(best, n); + } + + // best comes from RETURNED set. + + if (EnsureLimit(n, false)) { + return Carve(best, n); + } + + if (EnsureLimit(n, true)) { + // best could have been destroyed by coalescing. + // best_normal is not a best-fit, and it could be destroyed as well. + // We retry, the limit is already ensured: + return AllocLarge(n); + } + + // If best_normal existed, EnsureLimit would succeeded: + ASSERT(best_normal == NULL); + // We are not allowed to take best from returned list. + return NULL; +} + +Span* PageHeap::Split(Span* span, Length n) { + ASSERT(0 < n); + ASSERT(n < span->length); + ASSERT(span->location == Span::IN_USE); + ASSERT(span->sizeclass == 0); + + const int extra = span->length - n; + Span* leftover = NewSpan(span->start + n, extra); + ASSERT(leftover->location == Span::IN_USE); + RecordSpan(leftover); + pagemap_.set(span->start + n - 1, span); // Update map from pageid to span + span->length = n; + + return leftover; +} + +void PageHeap::CommitSpan(Span* span) { + ++stats_.commit_count; + + TCMalloc_SystemCommit(reinterpret_cast(span->start << kPageShift), + static_cast(span->length << kPageShift)); + stats_.committed_bytes += span->length << kPageShift; + stats_.total_commit_bytes += (span->length << kPageShift); +} + +bool PageHeap::DecommitSpan(Span* span) { + ++stats_.decommit_count; + + bool rv = TCMalloc_SystemRelease(reinterpret_cast(span->start << kPageShift), + static_cast(span->length << kPageShift)); + if (rv) { + stats_.committed_bytes -= span->length << kPageShift; + stats_.total_decommit_bytes += (span->length << kPageShift); + } + + return rv; +} + +Span* PageHeap::Carve(Span* span, Length n) { + ASSERT(n > 0); + ASSERT(span->location != Span::IN_USE); + const int old_location = span->location; + RemoveFromFreeList(span); + span->location = Span::IN_USE; + + const int extra = span->length - n; + ASSERT(extra >= 0); + if (extra > 0) { + Span* leftover = NewSpan(span->start + n, extra); + leftover->location = old_location; + RecordSpan(leftover); + + // The previous span of |leftover| was just splitted -- no need to + // coalesce them. The next span of |leftover| was not previously coalesced + // with |span|, i.e. is NULL or has got location other than |old_location|. +#ifndef NDEBUG + const PageID p = leftover->start; + const Length len = leftover->length; + Span* next = GetDescriptor(p+len); + ASSERT (next == NULL || + next->location == Span::IN_USE || + next->location != leftover->location); +#endif + + PrependToFreeList(leftover); // Skip coalescing - no candidates possible + span->length = n; + pagemap_.set(span->start + n - 1, span); + } + ASSERT(Check()); + if (old_location == Span::ON_RETURNED_FREELIST) { + // We need to recommit this address space. + CommitSpan(span); + } + ASSERT(span->location == Span::IN_USE); + ASSERT(span->length == n); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); + return span; +} + +void PageHeap::Delete(Span* span) { + ASSERT(Check()); + ASSERT(span->location == Span::IN_USE); + ASSERT(span->length > 0); + ASSERT(GetDescriptor(span->start) == span); + ASSERT(GetDescriptor(span->start + span->length - 1) == span); + const Length n = span->length; + span->sizeclass = 0; + span->sample = 0; + span->location = Span::ON_NORMAL_FREELIST; + MergeIntoFreeList(span); // Coalesces if possible + IncrementalScavenge(n); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); + ASSERT(Check()); +} + +// Given span we're about to free and other span (still on free list), +// checks if 'other' span is mergable with 'span'. If it is, removes +// other span from free list, performs aggressive decommit if +// necessary and returns 'other' span. Otherwise 'other' span cannot +// be merged and is left untouched. In that case NULL is returned. +Span* PageHeap::CheckAndHandlePreMerge(Span* span, Span* other) { + if (other == NULL) { + return other; + } + // if we're in aggressive decommit mode and span is decommitted, + // then we try to decommit adjacent span. + if (aggressive_decommit_ && other->location == Span::ON_NORMAL_FREELIST + && span->location == Span::ON_RETURNED_FREELIST) { + bool worked = DecommitSpan(other); + if (!worked) { + return NULL; + } + } else if (other->location != span->location) { + return NULL; + } + + RemoveFromFreeList(other); + return other; +} + +void PageHeap::MergeIntoFreeList(Span* span) { + ASSERT(span->location != Span::IN_USE); + + // Coalesce -- we guarantee that "p" != 0, so no bounds checking + // necessary. We do not bother resetting the stale pagemap + // entries for the pieces we are merging together because we only + // care about the pagemap entries for the boundaries. + // + // Note: depending on aggressive_decommit_ mode we allow only + // similar spans to be coalesced. + // + // The following applies if aggressive_decommit_ is enabled: + // + // TODO(jar): "Always decommit" causes some extra calls to commit when we are + // called in GrowHeap() during an allocation :-/. We need to eval the cost of + // that oscillation, and possibly do something to reduce it. + + // TODO(jar): We need a better strategy for deciding to commit, or decommit, + // based on memory usage and free heap sizes. + + const PageID p = span->start; + const Length n = span->length; + + if (aggressive_decommit_ && span->location == Span::ON_NORMAL_FREELIST) { + if (DecommitSpan(span)) { + span->location = Span::ON_RETURNED_FREELIST; + } + } + + Span* prev = CheckAndHandlePreMerge(span, GetDescriptor(p-1)); + if (prev != NULL) { + // Merge preceding span into this span + ASSERT(prev->start + prev->length == p); + const Length len = prev->length; + DeleteSpan(prev); + span->start -= len; + span->length += len; + pagemap_.set(span->start, span); + } + Span* next = CheckAndHandlePreMerge(span, GetDescriptor(p+n)); + if (next != NULL) { + // Merge next span into this span + ASSERT(next->start == p+n); + const Length len = next->length; + DeleteSpan(next); + span->length += len; + pagemap_.set(span->start + span->length - 1, span); + } + + PrependToFreeList(span); +} + +void PageHeap::PrependToFreeList(Span* span) { + ASSERT(span->location != Span::IN_USE); + if (span->location == Span::ON_NORMAL_FREELIST) + stats_.free_bytes += (span->length << kPageShift); + else + stats_.unmapped_bytes += (span->length << kPageShift); + + if (span->length > kMaxPages) { + SpanSet *set = &large_normal_; + if (span->location == Span::ON_RETURNED_FREELIST) + set = &large_returned_; + std::pair p = + set->insert(SpanPtrWithLength(span)); + ASSERT(p.second); // We never have duplicates since span->start is unique. + span->SetSpanSetIterator(p.first); + return; + } + + SpanList* list = &free_[span->length - 1]; + if (span->location == Span::ON_NORMAL_FREELIST) { + DLL_Prepend(&list->normal, span); + } else { + DLL_Prepend(&list->returned, span); + } +} + +void PageHeap::RemoveFromFreeList(Span* span) { + ASSERT(span->location != Span::IN_USE); + if (span->location == Span::ON_NORMAL_FREELIST) { + stats_.free_bytes -= (span->length << kPageShift); + } else { + stats_.unmapped_bytes -= (span->length << kPageShift); + } + if (span->length > kMaxPages) { + SpanSet *set = &large_normal_; + if (span->location == Span::ON_RETURNED_FREELIST) + set = &large_returned_; + SpanSet::iterator iter = span->ExtractSpanSetIterator(); + ASSERT(iter->span == span); + ASSERT(set->find(SpanPtrWithLength(span)) == iter); + set->erase(iter); + } else { + DLL_Remove(span); + } +} + +void PageHeap::IncrementalScavenge(Length n) { + // Fast path; not yet time to release memory + scavenge_counter_ -= n; + if (scavenge_counter_ >= 0) return; // Not yet time to scavenge + + const double rate = FLAGS_tcmalloc_release_rate; + if (rate <= 1e-6) { + // Tiny release rate means that releasing is disabled. + scavenge_counter_ = kDefaultReleaseDelay; + return; + } + + ++stats_.scavenge_count; + + Length released_pages = ReleaseAtLeastNPages(1); + + if (released_pages == 0) { + // Nothing to scavenge, delay for a while. + scavenge_counter_ = kDefaultReleaseDelay; + } else { + // Compute how long to wait until we return memory. + // FLAGS_tcmalloc_release_rate==1 means wait for 1000 pages + // after releasing one page. + const double mult = 1000.0 / rate; + double wait = mult * static_cast(released_pages); + if (wait > kMaxReleaseDelay) { + // Avoid overflow and bound to reasonable range. + wait = kMaxReleaseDelay; + } + scavenge_counter_ = static_cast(wait); + } +} + +Length PageHeap::ReleaseSpan(Span* s) { + ASSERT(s->location == Span::ON_NORMAL_FREELIST); + + if (DecommitSpan(s)) { + RemoveFromFreeList(s); + const Length n = s->length; + s->location = Span::ON_RETURNED_FREELIST; + MergeIntoFreeList(s); // Coalesces if possible. + return n; + } + + return 0; +} + +Length PageHeap::ReleaseAtLeastNPages(Length num_pages) { + Length released_pages = 0; + + // Round robin through the lists of free spans, releasing a + // span from each list. Stop after releasing at least num_pages + // or when there is nothing more to release. + while (released_pages < num_pages && stats_.free_bytes > 0) { + for (int i = 0; i < kMaxPages+1 && released_pages < num_pages; + i++, release_index_++) { + Span *s; + if (release_index_ > kMaxPages) release_index_ = 0; + + if (release_index_ == kMaxPages) { + if (large_normal_.empty()) { + continue; + } + s = (large_normal_.begin())->span; + } else { + SpanList* slist = &free_[release_index_]; + if (DLL_IsEmpty(&slist->normal)) { + continue; + } + s = slist->normal.prev; + } + // TODO(todd) if the remaining number of pages to release + // is significantly smaller than s->length, and s is on the + // large freelist, should we carve s instead of releasing? + // the whole thing? + Length released_len = ReleaseSpan(s); + // Some systems do not support release + if (released_len == 0) return released_pages; + released_pages += released_len; + } + } + return released_pages; +} + +bool PageHeap::EnsureLimit(Length n, bool withRelease) +{ + Length limit = (FLAGS_tcmalloc_heap_limit_mb*1024*1024) >> kPageShift; + if (limit == 0) return true; //there is no limit + + // We do not use stats_.system_bytes because it does not take + // MetaDataAllocs into account. + Length takenPages = TCMalloc_SystemTaken >> kPageShift; + //XXX takenPages may be slightly bigger than limit for two reasons: + //* MetaDataAllocs ignore the limit (it is not easy to handle + // out of memory there) + //* sys_alloc may round allocation up to huge page size, + // although smaller limit was ensured + + ASSERT(takenPages >= stats_.unmapped_bytes >> kPageShift); + takenPages -= stats_.unmapped_bytes >> kPageShift; + + if (takenPages + n > limit && withRelease) { + takenPages -= ReleaseAtLeastNPages(takenPages + n - limit); + } + + return takenPages + n <= limit; +} + +void PageHeap::RegisterSizeClass(Span* span, uint32 sc) { + // Associate span object with all interior pages as well + ASSERT(span->location == Span::IN_USE); + ASSERT(GetDescriptor(span->start) == span); + ASSERT(GetDescriptor(span->start+span->length-1) == span); + span->sizeclass = sc; + for (Length i = 1; i < span->length-1; i++) { + pagemap_.set(span->start+i, span); + } +} + +void PageHeap::GetSmallSpanStats(SmallSpanStats* result) { + for (int i = 0; i < kMaxPages; i++) { + result->normal_length[i] = DLL_Length(&free_[i].normal); + result->returned_length[i] = DLL_Length(&free_[i].returned); + } +} + +void PageHeap::GetLargeSpanStats(LargeSpanStats* result) { + result->spans = 0; + result->normal_pages = 0; + result->returned_pages = 0; + for (SpanSet::iterator it = large_normal_.begin(); it != large_normal_.end(); ++it) { + result->normal_pages += it->length; + result->spans++; + } + for (SpanSet::iterator it = large_returned_.begin(); it != large_returned_.end(); ++it) { + result->returned_pages += it->length; + result->spans++; + } +} + +bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) { + Span* span = reinterpret_cast(pagemap_.Next(start)); + if (span == NULL) { + return false; + } + r->address = span->start << kPageShift; + r->length = span->length << kPageShift; + r->fraction = 0; + switch (span->location) { + case Span::IN_USE: + r->type = base::MallocRange::INUSE; + r->fraction = 1; + if (span->sizeclass > 0) { + // Only some of the objects in this span may be in use. + const size_t osize = Static::sizemap()->class_to_size(span->sizeclass); + r->fraction = (1.0 * osize * span->refcount) / r->length; + } + break; + case Span::ON_NORMAL_FREELIST: + r->type = base::MallocRange::FREE; + break; + case Span::ON_RETURNED_FREELIST: + r->type = base::MallocRange::UNMAPPED; + break; + default: + r->type = base::MallocRange::UNKNOWN; + break; + } + return true; +} + +static void RecordGrowth(size_t growth) { + StackTrace* t = Static::stacktrace_allocator()->New(); + t->depth = GetStackTrace(t->stack, kMaxStackDepth-1, 3); + t->size = growth; + t->stack[kMaxStackDepth-1] = reinterpret_cast(Static::growth_stacks()); + Static::set_growth_stacks(t); +} + +bool PageHeap::GrowHeap(Length n) { + ASSERT(kMaxPages >= kMinSystemAlloc); + if (n > kMaxValidPages) return false; + Length ask = (n>kMinSystemAlloc) ? n : static_cast(kMinSystemAlloc); + size_t actual_size; + void* ptr = NULL; + if (EnsureLimit(ask)) { + ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize); + } + if (ptr == NULL) { + if (n < ask) { + // Try growing just "n" pages + ask = n; + if (EnsureLimit(ask)) { + ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize); + } + } + if (ptr == NULL) return false; + } + ask = actual_size >> kPageShift; + RecordGrowth(ask << kPageShift); + + ++stats_.reserve_count; + ++stats_.commit_count; + + uint64_t old_system_bytes = stats_.system_bytes; + stats_.system_bytes += (ask << kPageShift); + stats_.committed_bytes += (ask << kPageShift); + + stats_.total_commit_bytes += (ask << kPageShift); + stats_.total_reserve_bytes += (ask << kPageShift); + + const PageID p = reinterpret_cast(ptr) >> kPageShift; + ASSERT(p > 0); + + // If we have already a lot of pages allocated, just pre allocate a bunch of + // memory for the page map. This prevents fragmentation by pagemap metadata + // when a program keeps allocating and freeing large blocks. + + if (old_system_bytes < kPageMapBigAllocationThreshold + && stats_.system_bytes >= kPageMapBigAllocationThreshold) { + pagemap_.PreallocateMoreMemory(); + } + + // Make sure pagemap_ has entries for all of the new pages. + // Plus ensure one before and one after so coalescing code + // does not need bounds-checking. + if (pagemap_.Ensure(p-1, ask+2)) { + // Pretend the new area is allocated and then Delete() it to cause + // any necessary coalescing to occur. + Span* span = NewSpan(p, ask); + RecordSpan(span); + Delete(span); + ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes); + ASSERT(Check()); + return true; + } else { + // We could not allocate memory within "pagemap_" + // TODO: Once we can return memory to the system, return the new span + return false; + } +} + +bool PageHeap::Check() { + return true; +} + +bool PageHeap::CheckExpensive() { + bool result = Check(); + CheckSet(&large_normal_, kMaxPages + 1, Span::ON_NORMAL_FREELIST); + CheckSet(&large_returned_, kMaxPages + 1, Span::ON_RETURNED_FREELIST); + for (int s = 1; s <= kMaxPages; s++) { + CheckList(&free_[s - 1].normal, s, s, Span::ON_NORMAL_FREELIST); + CheckList(&free_[s - 1].returned, s, s, Span::ON_RETURNED_FREELIST); + } + return result; +} + +bool PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, + int freelist) { + for (Span* s = list->next; s != list; s = s->next) { + CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED + CHECK_CONDITION(s->length >= min_pages); + CHECK_CONDITION(s->length <= max_pages); + CHECK_CONDITION(GetDescriptor(s->start) == s); + CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); + } + return true; +} + +bool PageHeap::CheckSet(SpanSet* spanset, Length min_pages,int freelist) { + for (SpanSet::iterator it = spanset->begin(); it != spanset->end(); ++it) { + Span* s = it->span; + CHECK_CONDITION(s->length == it->length); + CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED + CHECK_CONDITION(s->length >= min_pages); + CHECK_CONDITION(GetDescriptor(s->start) == s); + CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); + } + return true; +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/page_heap.h b/trunk/3rdparty/gperftools-2-fit/src/page_heap.h new file mode 100644 index 000000000..bf50394fa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/page_heap.h @@ -0,0 +1,358 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#ifndef TCMALLOC_PAGE_HEAP_H_ +#define TCMALLOC_PAGE_HEAP_H_ + +#include +#include // for size_t +#ifdef HAVE_STDINT_H +#include // for uint64_t, int64_t, uint16_t +#endif +#include +#include "base/basictypes.h" +#include "common.h" +#include "packed-cache-inl.h" +#include "pagemap.h" +#include "span.h" + +// We need to dllexport PageHeap just for the unittest. MSVC complains +// that we don't dllexport the PageHeap members, but we don't need to +// test those, so I just suppress this warning. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +// This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if +// you're porting to a system where you really can't get a stacktrace. +// Because we control the definition of GetStackTrace, all clients of +// GetStackTrace should #include us rather than stacktrace.h. +#ifdef NO_TCMALLOC_SAMPLES + // We use #define so code compiles even if you #include stacktrace.h somehow. +# define GetStackTrace(stack, depth, skip) (0) +#else +# include +#endif + +namespace base { +struct MallocRange; +} + +namespace tcmalloc { + +// ------------------------------------------------------------------------- +// Map from page-id to per-page data +// ------------------------------------------------------------------------- + +// We use PageMap2<> for 32-bit and PageMap3<> for 64-bit machines. +// We also use a simple one-level cache for hot PageID-to-sizeclass mappings, +// because sometimes the sizeclass is all the information we need. + +// Selector class -- general selector uses 3-level map +template class MapSelector { + public: + typedef TCMalloc_PageMap3 Type; +}; + +#ifndef TCMALLOC_SMALL_BUT_SLOW +// x86-64 and arm64 are using 48 bits of address space. So we can use +// just two level map, but since initial ram consumption of this mode +// is a bit on the higher side, we opt-out of it in +// TCMALLOC_SMALL_BUT_SLOW mode. +template <> class MapSelector<48> { + public: + typedef TCMalloc_PageMap2<48-kPageShift> Type; +}; + +#endif // TCMALLOC_SMALL_BUT_SLOW + +// A two-level map for 32-bit machines +template <> class MapSelector<32> { + public: + typedef TCMalloc_PageMap2<32-kPageShift> Type; +}; + +// ------------------------------------------------------------------------- +// Page-level allocator +// * Eager coalescing +// +// Heap for page-level allocation. We allow allocating and freeing a +// contiguous runs of pages (called a "span"). +// ------------------------------------------------------------------------- + +class PERFTOOLS_DLL_DECL PageHeap { + public: + PageHeap(); + + // Allocate a run of "n" pages. Returns zero if out of memory. + // Caller should not pass "n == 0" -- instead, n should have + // been rounded up already. + Span* New(Length n); + + // Delete the span "[p, p+n-1]". + // REQUIRES: span was returned by earlier call to New() and + // has not yet been deleted. + void Delete(Span* span); + + // Mark an allocated span as being used for small objects of the + // specified size-class. + // REQUIRES: span was returned by an earlier call to New() + // and has not yet been deleted. + void RegisterSizeClass(Span* span, uint32 sc); + + // Split an allocated span into two spans: one of length "n" pages + // followed by another span of length "span->length - n" pages. + // Modifies "*span" to point to the first span of length "n" pages. + // Returns a pointer to the second span. + // + // REQUIRES: "0 < n < span->length" + // REQUIRES: span->location == IN_USE + // REQUIRES: span->sizeclass == 0 + Span* Split(Span* span, Length n); + + // Return the descriptor for the specified page. Returns NULL if + // this PageID was not allocated previously. + inline ATTRIBUTE_ALWAYS_INLINE + Span* GetDescriptor(PageID p) const { + return reinterpret_cast(pagemap_.get(p)); + } + + // If this page heap is managing a range with starting page # >= start, + // store info about the range in *r and return true. Else return false. + bool GetNextRange(PageID start, base::MallocRange* r); + + // Page heap statistics + struct Stats { + Stats() : system_bytes(0), free_bytes(0), unmapped_bytes(0), committed_bytes(0), + scavenge_count(0), commit_count(0), total_commit_bytes(0), + decommit_count(0), total_decommit_bytes(0), + reserve_count(0), total_reserve_bytes(0) {} + uint64_t system_bytes; // Total bytes allocated from system + uint64_t free_bytes; // Total bytes on normal freelists + uint64_t unmapped_bytes; // Total bytes on returned freelists + uint64_t committed_bytes; // Bytes committed, always <= system_bytes_. + + uint64_t scavenge_count; // Number of times scavagened flush pages + + uint64_t commit_count; // Number of virtual memory commits + uint64_t total_commit_bytes; // Bytes committed in lifetime of process + uint64_t decommit_count; // Number of virtual memory decommits + uint64_t total_decommit_bytes; // Bytes decommitted in lifetime of process + + uint64_t reserve_count; // Number of virtual memory reserves + uint64_t total_reserve_bytes; // Bytes reserved in lifetime of process + }; + inline Stats stats() const { return stats_; } + + struct SmallSpanStats { + // For each free list of small spans, the length (in spans) of the + // normal and returned free lists for that size. + // + // NOTE: index 'i' accounts the number of spans of length 'i + 1'. + int64 normal_length[kMaxPages]; + int64 returned_length[kMaxPages]; + }; + void GetSmallSpanStats(SmallSpanStats* result); + + // Stats for free large spans (i.e., spans with more than kMaxPages pages). + struct LargeSpanStats { + int64 spans; // Number of such spans + int64 normal_pages; // Combined page length of normal large spans + int64 returned_pages; // Combined page length of unmapped spans + }; + void GetLargeSpanStats(LargeSpanStats* result); + + bool Check(); + // Like Check() but does some more comprehensive checking. + bool CheckExpensive(); + bool CheckList(Span* list, Length min_pages, Length max_pages, + int freelist); // ON_NORMAL_FREELIST or ON_RETURNED_FREELIST + bool CheckSet(SpanSet *s, Length min_pages, int freelist); + + // Try to release at least num_pages for reuse by the OS. Returns + // the actual number of pages released, which may be less than + // num_pages if there weren't enough pages to release. The result + // may also be larger than num_pages since page_heap might decide to + // release one large range instead of fragmenting it into two + // smaller released and unreleased ranges. + Length ReleaseAtLeastNPages(Length num_pages); + + // Reads and writes to pagemap_cache_ do not require locking. + bool TryGetSizeClass(PageID p, uint32* out) const { + return pagemap_cache_.TryGet(p, out); + } + void SetCachedSizeClass(PageID p, uint32 cl) { + ASSERT(cl != 0); + pagemap_cache_.Put(p, cl); + } + void InvalidateCachedSizeClass(PageID p) { pagemap_cache_.Invalidate(p); } + uint32 GetSizeClassOrZero(PageID p) const { + uint32 cached_value; + if (!TryGetSizeClass(p, &cached_value)) { + cached_value = 0; + } + return cached_value; + } + + bool GetAggressiveDecommit(void) {return aggressive_decommit_;} + void SetAggressiveDecommit(bool aggressive_decommit) { + aggressive_decommit_ = aggressive_decommit; + } + + private: + // Allocates a big block of memory for the pagemap once we reach more than + // 128MB + static const size_t kPageMapBigAllocationThreshold = 128 << 20; + + // Minimum number of pages to fetch from system at a time. Must be + // significantly bigger than kBlockSize to amortize system-call + // overhead, and also to reduce external fragementation. Also, we + // should keep this value big because various incarnations of Linux + // have small limits on the number of mmap() regions per + // address-space. + // REQUIRED: kMinSystemAlloc <= kMaxPages; + static const int kMinSystemAlloc = kMaxPages; + + // Never delay scavenging for more than the following number of + // deallocated pages. With 4K pages, this comes to 4GB of + // deallocation. + static const int kMaxReleaseDelay = 1 << 20; + + // If there is nothing to release, wait for so many pages before + // scavenging again. With 4K pages, this comes to 1GB of memory. + static const int kDefaultReleaseDelay = 1 << 18; + + // Pick the appropriate map and cache types based on pointer size + typedef MapSelector::Type PageMap; + typedef PackedCache PageMapCache; + mutable PageMapCache pagemap_cache_; + PageMap pagemap_; + + // We segregate spans of a given size into two circular linked + // lists: one for normal spans, and one for spans whose memory + // has been returned to the system. + struct SpanList { + Span normal; + Span returned; + }; + + // Sets of spans with length > kMaxPages. + // + // Rather than using a linked list, we use sets here for efficient + // best-fit search. + SpanSet large_normal_; + SpanSet large_returned_; + + // Array mapping from span length to a doubly linked list of free spans + // + // NOTE: index 'i' stores spans of length 'i + 1'. + SpanList free_[kMaxPages]; + + // Statistics on system, free, and unmapped bytes + Stats stats_; + + Span* SearchFreeAndLargeLists(Length n); + + bool GrowHeap(Length n); + + // REQUIRES: span->length >= n + // REQUIRES: span->location != IN_USE + // Remove span from its free list, and move any leftover part of + // span into appropriate free lists. Also update "span" to have + // length exactly "n" and mark it as non-free so it can be returned + // to the client. After all that, decrease free_pages_ by n and + // return span. + Span* Carve(Span* span, Length n); + + void RecordSpan(Span* span) { + pagemap_.set(span->start, span); + if (span->length > 1) { + pagemap_.set(span->start + span->length - 1, span); + } + } + + // Allocate a large span of length == n. If successful, returns a + // span of exactly the specified length. Else, returns NULL. + Span* AllocLarge(Length n); + + // Coalesce span with neighboring spans if possible, prepend to + // appropriate free list, and adjust stats. + void MergeIntoFreeList(Span* span); + + // Commit the span. + void CommitSpan(Span* span); + + // Decommit the span. + bool DecommitSpan(Span* span); + + // Prepends span to appropriate free list, and adjusts stats. + void PrependToFreeList(Span* span); + + // Removes span from its free list, and adjust stats. + void RemoveFromFreeList(Span* span); + + // Incrementally release some memory to the system. + // IncrementalScavenge(n) is called whenever n pages are freed. + void IncrementalScavenge(Length n); + + // Attempts to decommit 's' and move it to the returned freelist. + // + // Returns the length of the Span or zero if release failed. + // + // REQUIRES: 's' must be on the NORMAL freelist. + Length ReleaseSpan(Span *s); + + // Checks if we are allowed to take more memory from the system. + // If limit is reached and allowRelease is true, tries to release + // some unused spans. + bool EnsureLimit(Length n, bool allowRelease = true); + + Span* CheckAndHandlePreMerge(Span *span, Span *other); + + // Number of pages to deallocate before doing more scavenging + int64_t scavenge_counter_; + + // Index of last free list where we released memory to the OS. + int release_index_; + + bool aggressive_decommit_; +}; + +} // namespace tcmalloc + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // TCMALLOC_PAGE_HEAP_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/page_heap_allocator.h b/trunk/3rdparty/gperftools-2-fit/src/page_heap_allocator.h new file mode 100644 index 000000000..3fecabdeb --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/page_heap_allocator.h @@ -0,0 +1,179 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#ifndef TCMALLOC_PAGE_HEAP_ALLOCATOR_H_ +#define TCMALLOC_PAGE_HEAP_ALLOCATOR_H_ + +#include // for NULL, size_t + +#include "common.h" // for MetaDataAlloc +#include "internal_logging.h" // for ASSERT + +namespace tcmalloc { + +// Simple allocator for objects of a specified type. External locking +// is required before accessing one of these objects. +template +class PageHeapAllocator { + public: + // We use an explicit Init function because these variables are statically + // allocated and their constructors might not have run by the time some + // other static variable tries to allocate memory. + void Init() { + ASSERT(sizeof(T) <= kAllocIncrement); + inuse_ = 0; + free_area_ = NULL; + free_avail_ = 0; + free_list_ = NULL; + // Reserve some space at the beginning to avoid fragmentation. + Delete(New()); + } + + T* New() { + // Consult free list + void* result; + if (free_list_ != NULL) { + result = free_list_; + free_list_ = *(reinterpret_cast(result)); + } else { + if (free_avail_ < sizeof(T)) { + // Need more room. We assume that MetaDataAlloc returns + // suitably aligned memory. + free_area_ = reinterpret_cast(MetaDataAlloc(kAllocIncrement)); + if (free_area_ == NULL) { + Log(kCrash, __FILE__, __LINE__, + "FATAL ERROR: Out of memory trying to allocate internal " + "tcmalloc data (bytes, object-size)", + kAllocIncrement, sizeof(T)); + } + free_avail_ = kAllocIncrement; + } + result = free_area_; + free_area_ += sizeof(T); + free_avail_ -= sizeof(T); + } + inuse_++; + return reinterpret_cast(result); + } + + void Delete(T* p) { + *(reinterpret_cast(p)) = free_list_; + free_list_ = p; + inuse_--; + } + + int inuse() const { return inuse_; } + + private: + // How much to allocate from system at a time + static const int kAllocIncrement = 128 << 10; + + // Free area from which to carve new objects + char* free_area_; + size_t free_avail_; + + // Free list of already carved objects + void* free_list_; + + // Number of allocated but unfreed objects + int inuse_; +}; + +// STL-compatible allocator which forwards allocations to a PageHeapAllocator. +// +// Like PageHeapAllocator, this requires external synchronization. To avoid multiple +// separate STLPageHeapAllocator from sharing the same underlying PageHeapAllocator, +// the |LockingTag| template argument should be used. Template instantiations with +// different locking tags can safely be used concurrently. +template +class STLPageHeapAllocator { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + template struct rebind { + typedef STLPageHeapAllocator other; + }; + + STLPageHeapAllocator() { } + STLPageHeapAllocator(const STLPageHeapAllocator&) { } + template STLPageHeapAllocator(const STLPageHeapAllocator&) { } + ~STLPageHeapAllocator() { } + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + void construct(pointer p, const T& val) { ::new(p) T(val); } + void construct(pointer p) { ::new(p) T(); } + void destroy(pointer p) { p->~T(); } + + // There's no state, so these allocators are always equal + bool operator==(const STLPageHeapAllocator&) const { return true; } + bool operator!=(const STLPageHeapAllocator&) const { return false; } + + pointer allocate(size_type n, const void* = 0) { + if (!underlying_.initialized) { + underlying_.allocator.Init(); + underlying_.initialized = true; + } + + CHECK_CONDITION(n == 1); + return underlying_.allocator.New(); + } + void deallocate(pointer p, size_type n) { + CHECK_CONDITION(n == 1); + underlying_.allocator.Delete(p); + } + + private: + struct Storage { + explicit Storage(base::LinkerInitialized x) {} + PageHeapAllocator allocator; + bool initialized; + }; + static Storage underlying_; +}; + +template +typename STLPageHeapAllocator::Storage STLPageHeapAllocator::underlying_(base::LINKER_INITIALIZED); + +} // namespace tcmalloc + +#endif // TCMALLOC_PAGE_HEAP_ALLOCATOR_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/pagemap.h b/trunk/3rdparty/gperftools-2-fit/src/pagemap.h new file mode 100644 index 000000000..dfa336c5f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/pagemap.h @@ -0,0 +1,328 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// A data structure used by the caching malloc. It maps from page# to +// a pointer that contains info about that page. We use two +// representations: one for 32-bit addresses, and another for 64 bit +// addresses. Both representations provide the same interface. The +// first representation is implemented as a flat array, the seconds as +// a three-level radix tree that strips away approximately 1/3rd of +// the bits every time. +// +// The BITS parameter should be the number of bits required to hold +// a page number. E.g., with 32 bit pointers and 4K pages (i.e., +// page offset fits in lower 12 bits), BITS == 20. + +#ifndef TCMALLOC_PAGEMAP_H_ +#define TCMALLOC_PAGEMAP_H_ + +#include "config.h" + +#include // for NULL, size_t +#include // for memset +#if defined HAVE_STDINT_H +#include +#elif defined HAVE_INTTYPES_H +#include +#else +#include +#endif +#include "internal_logging.h" // for ASSERT + +// Single-level array +template +class TCMalloc_PageMap1 { + private: + static const int LENGTH = 1 << BITS; + + void** array_; + + public: + typedef uintptr_t Number; + + explicit TCMalloc_PageMap1(void* (*allocator)(size_t)) { + array_ = reinterpret_cast((*allocator)(sizeof(void*) << BITS)); + memset(array_, 0, sizeof(void*) << BITS); + } + + // Ensure that the map contains initialized entries "x .. x+n-1". + // Returns true if successful, false if we could not allocate memory. + bool Ensure(Number x, size_t n) { + // Nothing to do since flat array was allocated at start. All + // that's left is to check for overflow (that is, we don't want to + // ensure a number y where array_[y] would be an out-of-bounds + // access). + return n <= LENGTH - x; // an overflow-free way to do "x + n <= LENGTH" + } + + void PreallocateMoreMemory() {} + + // Return the current value for KEY. Returns NULL if not yet set, + // or if k is out of range. + ATTRIBUTE_ALWAYS_INLINE + void* get(Number k) const { + if ((k >> BITS) > 0) { + return NULL; + } + return array_[k]; + } + + // REQUIRES "k" is in range "[0,2^BITS-1]". + // REQUIRES "k" has been ensured before. + // + // Sets the value 'v' for key 'k'. + void set(Number k, void* v) { + array_[k] = v; + } + + // Return the first non-NULL pointer found in this map for + // a page number >= k. Returns NULL if no such number is found. + void* Next(Number k) const { + while (k < (1 << BITS)) { + if (array_[k] != NULL) return array_[k]; + k++; + } + return NULL; + } +}; + +// Two-level radix tree +template +class TCMalloc_PageMap2 { + private: + static const int LEAF_BITS = (BITS + 1) / 2; + static const int LEAF_LENGTH = 1 << LEAF_BITS; + + static const int ROOT_BITS = BITS - LEAF_BITS; + static const int ROOT_LENGTH = 1 << ROOT_BITS; + + // Leaf node + struct Leaf { + void* values[LEAF_LENGTH]; + }; + + Leaf* root_[ROOT_LENGTH]; // Pointers to child nodes + void* (*allocator_)(size_t); // Memory allocator + + public: + typedef uintptr_t Number; + + explicit TCMalloc_PageMap2(void* (*allocator)(size_t)) { + allocator_ = allocator; + memset(root_, 0, sizeof(root_)); + } + + ATTRIBUTE_ALWAYS_INLINE + void* get(Number k) const { + const Number i1 = k >> LEAF_BITS; + const Number i2 = k & (LEAF_LENGTH-1); + if ((k >> BITS) > 0 || root_[i1] == NULL) { + return NULL; + } + return root_[i1]->values[i2]; + } + + void set(Number k, void* v) { + const Number i1 = k >> LEAF_BITS; + const Number i2 = k & (LEAF_LENGTH-1); + ASSERT(i1 < ROOT_LENGTH); + root_[i1]->values[i2] = v; + } + + bool Ensure(Number start, size_t n) { + for (Number key = start; key <= start + n - 1; ) { + const Number i1 = key >> LEAF_BITS; + + // Check for overflow + if (i1 >= ROOT_LENGTH) + return false; + + // Make 2nd level node if necessary + if (root_[i1] == NULL) { + Leaf* leaf = reinterpret_cast((*allocator_)(sizeof(Leaf))); + if (leaf == NULL) return false; + memset(leaf, 0, sizeof(*leaf)); + root_[i1] = leaf; + } + + // Advance key past whatever is covered by this leaf node + key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; + } + return true; + } + + void PreallocateMoreMemory() { + // Allocate enough to keep track of all possible pages + if (BITS < 20) { + Ensure(0, Number(1) << BITS); + } + } + + void* Next(Number k) const { + while (k < (Number(1) << BITS)) { + const Number i1 = k >> LEAF_BITS; + Leaf* leaf = root_[i1]; + if (leaf != NULL) { + // Scan forward in leaf + for (Number i2 = k & (LEAF_LENGTH - 1); i2 < LEAF_LENGTH; i2++) { + if (leaf->values[i2] != NULL) { + return leaf->values[i2]; + } + } + } + // Skip to next top-level entry + k = (i1 + 1) << LEAF_BITS; + } + return NULL; + } +}; + +// Three-level radix tree +template +class TCMalloc_PageMap3 { + private: + // How many bits should we consume at each interior level + static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up + static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; + + // How many bits should we consume at leaf level + static const int LEAF_BITS = BITS - 2*INTERIOR_BITS; + static const int LEAF_LENGTH = 1 << LEAF_BITS; + + // Interior node + struct Node { + Node* ptrs[INTERIOR_LENGTH]; + }; + + // Leaf node + struct Leaf { + void* values[LEAF_LENGTH]; + }; + + Node root_; // Root of radix tree + void* (*allocator_)(size_t); // Memory allocator + + Node* NewNode() { + Node* result = reinterpret_cast((*allocator_)(sizeof(Node))); + if (result != NULL) { + memset(result, 0, sizeof(*result)); + } + return result; + } + + public: + typedef uintptr_t Number; + + explicit TCMalloc_PageMap3(void* (*allocator)(size_t)) { + allocator_ = allocator; + memset(&root_, 0, sizeof(root_)); + } + + ATTRIBUTE_ALWAYS_INLINE + void* get(Number k) const { + const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); + const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); + const Number i3 = k & (LEAF_LENGTH-1); + if ((k >> BITS) > 0 || + root_.ptrs[i1] == NULL || root_.ptrs[i1]->ptrs[i2] == NULL) { + return NULL; + } + return reinterpret_cast(root_.ptrs[i1]->ptrs[i2])->values[i3]; + } + + void set(Number k, void* v) { + ASSERT(k >> BITS == 0); + const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); + const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); + const Number i3 = k & (LEAF_LENGTH-1); + reinterpret_cast(root_.ptrs[i1]->ptrs[i2])->values[i3] = v; + } + + bool Ensure(Number start, size_t n) { + for (Number key = start; key <= start + n - 1; ) { + const Number i1 = key >> (LEAF_BITS + INTERIOR_BITS); + const Number i2 = (key >> LEAF_BITS) & (INTERIOR_LENGTH-1); + + // Check for overflow + if (i1 >= INTERIOR_LENGTH || i2 >= INTERIOR_LENGTH) + return false; + + // Make 2nd level node if necessary + if (root_.ptrs[i1] == NULL) { + Node* n = NewNode(); + if (n == NULL) return false; + root_.ptrs[i1] = n; + } + + // Make leaf node if necessary + if (root_.ptrs[i1]->ptrs[i2] == NULL) { + Leaf* leaf = reinterpret_cast((*allocator_)(sizeof(Leaf))); + if (leaf == NULL) return false; + memset(leaf, 0, sizeof(*leaf)); + root_.ptrs[i1]->ptrs[i2] = reinterpret_cast(leaf); + } + + // Advance key past whatever is covered by this leaf node + key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; + } + return true; + } + + void PreallocateMoreMemory() { + } + + void* Next(Number k) const { + while (k < (Number(1) << BITS)) { + const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); + const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); + if (root_.ptrs[i1] == NULL) { + // Advance to next top-level entry + k = (i1 + 1) << (LEAF_BITS + INTERIOR_BITS); + } else { + Leaf* leaf = reinterpret_cast(root_.ptrs[i1]->ptrs[i2]); + if (leaf != NULL) { + for (Number i3 = (k & (LEAF_LENGTH-1)); i3 < LEAF_LENGTH; i3++) { + if (leaf->values[i3] != NULL) { + return leaf->values[i3]; + } + } + } + // Advance to next interior entry + k = ((k >> LEAF_BITS) + 1) << LEAF_BITS; + } + } + return NULL; + } +}; + +#endif // TCMALLOC_PAGEMAP_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/pprof b/trunk/3rdparty/gperftools-2-fit/src/pprof new file mode 100755 index 000000000..3a816c62e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/pprof @@ -0,0 +1,5580 @@ +#! /usr/bin/env perl + +# Copyright (c) 1998-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. + +# --- +# Program for printing the profile generated by common/profiler.cc, +# or by the heap profiler (common/debugallocation.cc) +# +# The profile contains a sequence of entries of the form: +# +# This program parses the profile, and generates user-readable +# output. +# +# Examples: +# +# % tools/pprof "program" "profile" +# Enters "interactive" mode +# +# % tools/pprof --text "program" "profile" +# Generates one line per procedure +# +# % tools/pprof --gv "program" "profile" +# Generates annotated call-graph and displays via "gv" +# +# % tools/pprof --gv --focus=Mutex "program" "profile" +# Restrict to code paths that involve an entry that matches "Mutex" +# +# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile" +# Restrict to code paths that involve an entry that matches "Mutex" +# and does not match "string" +# +# % tools/pprof --list=IBF_CheckDocid "program" "profile" +# Generates disassembly listing of all routines with at least one +# sample that match the --list= pattern. The listing is +# annotated with the flat and cumulative sample counts at each line. +# +# % tools/pprof --disasm=IBF_CheckDocid "program" "profile" +# Generates disassembly listing of all routines with at least one +# sample that match the --disasm= pattern. The listing is +# annotated with the flat and cumulative sample counts at each PC value. +# +# TODO: Use color to indicate files? + +use strict; +use warnings; +use Getopt::Long; +use Cwd; +use POSIX; + +my $PPROF_VERSION = "2.0"; + +# These are the object tools we use which can come from a +# user-specified location using --tools, from the PPROF_TOOLS +# environment variable, or from the environment. +my %obj_tool_map = ( + "objdump" => "objdump", + "nm" => "nm", + "addr2line" => "addr2line", + "c++filt" => "c++filt", + ## ConfigureObjTools may add architecture-specific entries: + #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables + #"addr2line_pdb" => "addr2line-pdb", # ditto + #"otool" => "otool", # equivalent of objdump on OS X +); +# NOTE: these are lists, so you can put in commandline flags if you want. +my @DOT = ("dot"); # leave non-absolute, since it may be in /usr/local +my @GV = ("gv"); +my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread +my @KCACHEGRIND = ("kcachegrind"); +my @PS2PDF = ("ps2pdf"); +# These are used for dynamic profiles +my @URL_FETCHER = ("curl", "-s"); + +# These are the web pages that servers need to support for dynamic profiles +my $HEAP_PAGE = "/pprof/heap"; +my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#" +my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param + # ?seconds=#&event=x&period=n +my $GROWTH_PAGE = "/pprof/growth"; +my $CONTENTION_PAGE = "/pprof/contention"; +my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter +my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?"; +my $CENSUSPROFILE_PAGE = "/pprof/censusprofile(?:\\?.*)?"; # must support cgi-param + # "?seconds=#", + # "?tags_regexp=#" and + # "?type=#". +my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST +my $PROGRAM_NAME_PAGE = "/pprof/cmdline"; + +# These are the web pages that can be named on the command line. +# All the alternatives must begin with /. +my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" . + "$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" . + "$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)"; + +# default binary name +my $UNKNOWN_BINARY = "(unknown)"; + +# There is a pervasive dependency on the length (in hex characters, +# i.e., nibbles) of an address, distinguishing between 32-bit and +# 64-bit profiles. To err on the safe size, default to 64-bit here: +my $address_length = 16; + +my $dev_null = "/dev/null"; +if (! -e $dev_null && $^O =~ /MSWin/) { # $^O is the OS perl was built for + $dev_null = "nul"; +} + +# A list of paths to search for shared object files +my @prefix_list = (); + +# Special routine name that should not have any symbols. +# Used as separator to parse "addr2line -i" output. +my $sep_symbol = '_fini'; +my $sep_address = undef; + +my @stackTraces; + +##### Argument parsing ##### + +sub usage_string { + return < + is a space separated list of profile names. +$0 [options] + is a list of profile files where each file contains + the necessary symbol mappings as well as profile data (likely generated + with --raw). +$0 [options] + is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE + + Each name can be: + /path/to/profile - a path to a profile file + host:port[/] - a location of a service to get profile from + + The / can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile, + $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, + $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. + For instance: + $0 http://myserver.com:80$HEAP_PAGE + If / is omitted, the service defaults to $PROFILE_PAGE (cpu profiling). +$0 --symbols + Maps addresses to symbol names. In this mode, stdin should be a + list of library mappings, in the same format as is found in the heap- + and cpu-profile files (this loosely matches that of /proc/self/maps + on linux), followed by a list of hex addresses to map, one per line. + + For more help with querying remote servers, including how to add the + necessary server-side support code, see this filename (or one like it): + + /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html + +Options: + --cum Sort by cumulative data + --base= Subtract from before display + --interactive Run in interactive mode (interactive "help" gives help) [default] + --seconds= Length of time for dynamic profiles [default=30 secs] + --add_lib= Read additional symbols and line info from the given library + --lib_prefix= Comma separated list of library path prefixes + --no_strip_temp Do not strip template arguments from function names + +Reporting Granularity: + --addresses Report at address level + --lines Report at source line level + --functions Report at function level [default] + --files Report at source file level + +Output type: + --text Generate text report + --stacks Generate stack traces similar to the heap profiler (requires --text) + --callgrind Generate callgrind format to stdout + --gv Generate Postscript and display + --evince Generate PDF and display + --web Generate SVG and display + --list= Generate source listing of matching routines + --disasm= Generate disassembly of matching routines + --symbols Print demangled symbol names found at given addresses + --dot Generate DOT file to stdout + --ps Generate Postscript to stdout + --pdf Generate PDF to stdout + --svg Generate SVG to stdout + --gif Generate GIF to stdout + --raw Generate symbolized pprof data (useful with remote fetch) + --collapsed Generate collapsed stacks for building flame graphs + (see http://www.brendangregg.com/flamegraphs.html) + +Heap-Profile Options: + --inuse_space Display in-use (mega)bytes [default] + --inuse_objects Display in-use objects + --alloc_space Display allocated (mega)bytes + --alloc_objects Display allocated objects + --show_bytes Display space in bytes + --drop_negative Ignore negative differences + +Contention-profile options: + --total_delay Display total delay at each region [default] + --contentions Display number of delays at each region + --mean_delay Display mean delay at each region + +Call-graph Options: + --nodecount= Show at most so many nodes [default=80] + --nodefraction= Hide nodes below *total [default=.005] + --edgefraction= Hide edges below *total [default=.001] + --maxdegree= Max incoming/outgoing edges per node [default=8] + --focus= Focus on nodes matching + --ignore= Ignore nodes matching + --scale= Set GV scaling [default=0] + --heapcheck Make nodes with non-0 object counts + (i.e. direct leak generators) more visible + +Miscellaneous: + --no-auto-signal-frm Automatically drop 2nd frame that is always same (cpu-only) + (assuming that it is artifact of bad stack captures + which include signal handler frames) + --show_addresses Always show addresses when applicable + --tools=[,...] \$PATH for object tool pathnames + --test Run unit tests + --help This message + --version Version information + +Environment Variables: + PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof + PPROF_TOOLS Prefix for object tools pathnames + +Examples: + +$0 /bin/ls ls.prof + Enters "interactive" mode +$0 --text /bin/ls ls.prof + Outputs one line per procedure +$0 --web /bin/ls ls.prof + Displays annotated call-graph in web browser +$0 --gv /bin/ls ls.prof + Displays annotated call-graph via 'gv' +$0 --gv --focus=Mutex /bin/ls ls.prof + Restricts to code paths including a .*Mutex.* entry +$0 --gv --focus=Mutex --ignore=string /bin/ls ls.prof + Code paths including Mutex but not string +$0 --list=getdir /bin/ls ls.prof + (Per-line) annotated source listing for getdir() +$0 --disasm=getdir /bin/ls ls.prof + (Per-PC) annotated disassembly for getdir() + +$0 http://localhost:1234/ + Enters "interactive" mode +$0 --text localhost:1234 + Outputs one line per procedure for localhost:1234 +$0 --raw localhost:1234 > ./local.raw +$0 --text ./local.raw + Fetches a remote profile for later analysis and then + analyzes it in text mode. +EOF +} + +sub version_string { + return < \$main::opt_help, + "version!" => \$main::opt_version, + "show_addresses!"=> \$main::opt_show_addresses, + "no-auto-signal-frm!"=> \$main::opt_no_auto_signal_frames, + "cum!" => \$main::opt_cum, + "base=s" => \$main::opt_base, + "seconds=i" => \$main::opt_seconds, + "add_lib=s" => \$main::opt_lib, + "lib_prefix=s" => \$main::opt_lib_prefix, + "functions!" => \$main::opt_functions, + "lines!" => \$main::opt_lines, + "addresses!" => \$main::opt_addresses, + "files!" => \$main::opt_files, + "text!" => \$main::opt_text, + "stacks!" => \$main::opt_stacks, + "callgrind!" => \$main::opt_callgrind, + "list=s" => \$main::opt_list, + "disasm=s" => \$main::opt_disasm, + "symbols!" => \$main::opt_symbols, + "gv!" => \$main::opt_gv, + "evince!" => \$main::opt_evince, + "web!" => \$main::opt_web, + "dot!" => \$main::opt_dot, + "ps!" => \$main::opt_ps, + "pdf!" => \$main::opt_pdf, + "svg!" => \$main::opt_svg, + "gif!" => \$main::opt_gif, + "raw!" => \$main::opt_raw, + "collapsed!" => \$main::opt_collapsed, + "interactive!" => \$main::opt_interactive, + "nodecount=i" => \$main::opt_nodecount, + "nodefraction=f" => \$main::opt_nodefraction, + "edgefraction=f" => \$main::opt_edgefraction, + "maxdegree=i" => \$main::opt_maxdegree, + "focus=s" => \$main::opt_focus, + "ignore=s" => \$main::opt_ignore, + "scale=i" => \$main::opt_scale, + "heapcheck" => \$main::opt_heapcheck, + "inuse_space!" => \$main::opt_inuse_space, + "inuse_objects!" => \$main::opt_inuse_objects, + "alloc_space!" => \$main::opt_alloc_space, + "alloc_objects!" => \$main::opt_alloc_objects, + "show_bytes!" => \$main::opt_show_bytes, + "drop_negative!" => \$main::opt_drop_negative, + "total_delay!" => \$main::opt_total_delay, + "contentions!" => \$main::opt_contentions, + "mean_delay!" => \$main::opt_mean_delay, + "tools=s" => \$main::opt_tools, + "no_strip_temp!" => \$main::opt_no_strip_temp, + "test!" => \$main::opt_test, + "debug!" => \$main::opt_debug, + # Undocumented flags used only by unittests: + "test_stride=i" => \$main::opt_test_stride, + ) || usage("Invalid option(s)"); + + # Deal with the standard --help and --version + if ($main::opt_help) { + print usage_string(); + exit(0); + } + + if ($main::opt_version) { + print version_string(); + exit(0); + } + + # Disassembly/listing/symbols mode requires address-level info + if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) { + $main::opt_functions = 0; + $main::opt_lines = 0; + $main::opt_addresses = 1; + $main::opt_files = 0; + } + + # Check heap-profiling flags + if ($main::opt_inuse_space + + $main::opt_inuse_objects + + $main::opt_alloc_space + + $main::opt_alloc_objects > 1) { + usage("Specify at most on of --inuse/--alloc options"); + } + + # Check output granularities + my $grains = + $main::opt_functions + + $main::opt_lines + + $main::opt_addresses + + $main::opt_files + + 0; + if ($grains > 1) { + usage("Only specify one output granularity option"); + } + if ($grains == 0) { + $main::opt_functions = 1; + } + + # Check output modes + my $modes = + $main::opt_text + + $main::opt_callgrind + + ($main::opt_list eq '' ? 0 : 1) + + ($main::opt_disasm eq '' ? 0 : 1) + + ($main::opt_symbols == 0 ? 0 : 1) + + $main::opt_gv + + $main::opt_evince + + $main::opt_web + + $main::opt_dot + + $main::opt_ps + + $main::opt_pdf + + $main::opt_svg + + $main::opt_gif + + $main::opt_raw + + $main::opt_collapsed + + $main::opt_interactive + + 0; + if ($modes > 1) { + usage("Only specify one output mode"); + } + if ($modes == 0) { + if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode + $main::opt_interactive = 1; + } else { + $main::opt_text = 1; + } + } + + if ($main::opt_test) { + RunUnitTests(); + # Should not return + exit(1); + } + + # Binary name and profile arguments list + $main::prog = ""; + @main::pfile_args = (); + + # Remote profiling without a binary (using $SYMBOL_PAGE instead) + if (@ARGV > 0) { + if (IsProfileURL($ARGV[0])) { + printf STDERR "Using remote profile at $ARGV[0].\n"; + $main::use_symbol_page = 1; + } elsif (IsSymbolizedProfileFile($ARGV[0])) { + $main::use_symbolized_profile = 1; + $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file + } + } + + if ($main::use_symbol_page || $main::use_symbolized_profile) { + # We don't need a binary! + my %disabled = ('--lines' => $main::opt_lines, + '--disasm' => $main::opt_disasm); + for my $option (keys %disabled) { + usage("$option cannot be used without a binary") if $disabled{$option}; + } + # Set $main::prog later... + scalar(@ARGV) || usage("Did not specify profile file"); + } elsif ($main::opt_symbols) { + # --symbols needs a binary-name (to run nm on, etc) but not profiles + $main::prog = shift(@ARGV) || usage("Did not specify program"); + } else { + $main::prog = shift(@ARGV) || usage("Did not specify program"); + scalar(@ARGV) || usage("Did not specify profile file"); + } + + # Parse profile file/location arguments + foreach my $farg (@ARGV) { + if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) { + my $machine = $1; + my $num_machines = $2; + my $path = $3; + for (my $i = 0; $i < $num_machines; $i++) { + unshift(@main::pfile_args, "$i.$machine$path"); + } + } else { + unshift(@main::pfile_args, $farg); + } + } + + if ($main::use_symbol_page) { + unless (IsProfileURL($main::pfile_args[0])) { + error("The first profile should be a remote form to use $SYMBOL_PAGE\n"); + } + CheckSymbolPage(); + $main::prog = FetchProgramName(); + } elsif (!$main::use_symbolized_profile) { # may not need objtools! + ConfigureObjTools($main::prog) + } + + # Break the opt_lib_prefix into the prefix_list array + @prefix_list = split (',', $main::opt_lib_prefix); + + # Remove trailing / from the prefixes, in the list to prevent + # searching things like /my/path//lib/mylib.so + foreach (@prefix_list) { + s|/+$||; + } +} + +sub Main() { + Init(); + $main::collected_profile = undef; + @main::profile_files = (); + $main::op_time = time(); + + # Printing symbols is special and requires a lot less info that most. + if ($main::opt_symbols) { + PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin + return; + } + + # Fetch all profile data + FetchDynamicProfiles(); + + # this will hold symbols that we read from the profile files + my $symbol_map = {}; + + # Read one profile, pick the last item on the list + my $data = ReadProfile($main::prog, pop(@main::profile_files)); + my $profile = $data->{profile}; + my $pcs = $data->{pcs}; + my $libs = $data->{libs}; # Info about main program and shared libraries + $symbol_map = MergeSymbols($symbol_map, $data->{symbols}); + + # Add additional profiles, if available. + if (scalar(@main::profile_files) > 0) { + foreach my $pname (@main::profile_files) { + my $data2 = ReadProfile($main::prog, $pname); + $profile = AddProfile($profile, $data2->{profile}); + $pcs = AddPcs($pcs, $data2->{pcs}); + $symbol_map = MergeSymbols($symbol_map, $data2->{symbols}); + } + } + + # Subtract base from profile, if specified + if ($main::opt_base ne '') { + my $base = ReadProfile($main::prog, $main::opt_base); + $profile = SubtractProfile($profile, $base->{profile}); + $pcs = AddPcs($pcs, $base->{pcs}); + $symbol_map = MergeSymbols($symbol_map, $base->{symbols}); + } + + # Get total data in profile + my $total = TotalProfile($profile); + + # Collect symbols + my $symbols; + if ($main::use_symbolized_profile) { + $symbols = FetchSymbols($pcs, $symbol_map); + } elsif ($main::use_symbol_page) { + $symbols = FetchSymbols($pcs); + } else { + # TODO(csilvers): $libs uses the /proc/self/maps data from profile1, + # which may differ from the data from subsequent profiles, especially + # if they were run on different machines. Use appropriate libs for + # each pc somehow. + $symbols = ExtractSymbols($libs, $pcs); + } + + # Remove uniniteresting stack items + $profile = RemoveUninterestingFrames($symbols, $profile); + + # Focus? + if ($main::opt_focus ne '') { + $profile = FocusProfile($symbols, $profile, $main::opt_focus); + } + + # Ignore? + if ($main::opt_ignore ne '') { + $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore); + } + + my $calls = ExtractCalls($symbols, $profile); + + # Reduce profiles to required output granularity, and also clean + # each stack trace so a given entry exists at most once. + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + # Print + if (!$main::opt_interactive) { + if ($main::opt_disasm) { + PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm); + } elsif ($main::opt_list) { + PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0); + } elsif ($main::opt_text) { + # Make sure the output is empty when have nothing to report + # (only matters when --heapcheck is given but we must be + # compatible with old branches that did not pass --heapcheck always): + if ($total != 0) { + printf("Total: %s %s\n", Unparse($total), Units()); + } + if ($main::opt_stacks) { + printf("Stacks:\n\n"); + PrintStacksForText($symbols, $profile); + } + PrintText($symbols, $flat, $cumulative, -1); + } elsif ($main::opt_raw) { + PrintSymbolizedProfile($symbols, $profile, $main::prog); + } elsif ($main::opt_collapsed) { + PrintCollapsedStacks($symbols, $profile); + } elsif ($main::opt_callgrind) { + PrintCallgrind($calls); + } else { + if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { + if ($main::opt_gv) { + RunGV(TempName($main::next_tmpfile, "ps"), ""); + } elsif ($main::opt_evince) { + RunEvince(TempName($main::next_tmpfile, "pdf"), ""); + } elsif ($main::opt_web) { + my $tmp = TempName($main::next_tmpfile, "svg"); + RunWeb($tmp); + # The command we run might hand the file name off + # to an already running browser instance and then exit. + # Normally, we'd remove $tmp on exit (right now), + # but fork a child to remove $tmp a little later, so that the + # browser has time to load it first. + delete $main::tempnames{$tmp}; + if (fork() == 0) { + sleep 5; + unlink($tmp); + exit(0); + } + } + } else { + cleanup(); + exit(1); + } + } + } else { + InteractiveMode($profile, $symbols, $libs, $total); + } + + cleanup(); + exit(0); +} + +##### Entry Point ##### + +Main(); + +# Temporary code to detect if we're running on a Goobuntu system. +# These systems don't have the right stuff installed for the special +# Readline libraries to work, so as a temporary workaround, we default +# to using the normal stdio code, rather than the fancier readline-based +# code +sub ReadlineMightFail { + if (-e '/lib/libtermcap.so.2') { + return 0; # libtermcap exists, so readline should be okay + } else { + return 1; + } +} + +sub RunGV { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + if (!system(ShellEscape(@GV, "--version") . " >$dev_null 2>&1")) { + # Options using double dash are supported by this gv version. + # Also, turn on noantialias to better handle bug in gv for + # postscript files with large dimensions. + # TODO: Maybe we should not pass the --noantialias flag + # if the gv version is known to work properly without the flag. + system(ShellEscape(@GV, "--scale=$main::opt_scale", "--noantialias", $fname) + . $bg); + } else { + # Old gv version - only supports options that use single dash. + print STDERR ShellEscape(@GV, "-scale", $main::opt_scale) . "\n"; + system(ShellEscape(@GV, "-scale", "$main::opt_scale", $fname) . $bg); + } +} + +sub RunEvince { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + system(ShellEscape(@EVINCE, $fname) . $bg); +} + +sub RunWeb { + my $fname = shift; + print STDERR "Loading web page file:///$fname\n"; + + if (`uname` =~ /Darwin/) { + # OS X: open will use standard preference for SVG files. + system("/usr/bin/open", $fname); + return; + } + + if (`uname` =~ /MINGW/) { + # Windows(MinGW): open will use standard preference for SVG files. + system("cmd", "/c", "start", $fname); + return; + } + + # Some kind of Unix; try generic symlinks, then specific browsers. + # (Stop once we find one.) + # Works best if the browser is already running. + my @alt = ( + "/etc/alternatives/gnome-www-browser", + "/etc/alternatives/x-www-browser", + "google-chrome", + "firefox", + ); + foreach my $b (@alt) { + if (system($b, $fname) == 0) { + return; + } + } + + print STDERR "Could not load web browser.\n"; +} + +sub RunKcachegrind { + my $fname = shift; + my $bg = shift; # "" or " &" if we should run in background + print STDERR "Starting '@KCACHEGRIND " . $fname . $bg . "'\n"; + system(ShellEscape(@KCACHEGRIND, $fname) . $bg); +} + + +##### Interactive helper routines ##### + +sub InteractiveMode { + $| = 1; # Make output unbuffered for interactive mode + my ($orig_profile, $symbols, $libs, $total) = @_; + + print STDERR "Welcome to pprof! For help, type 'help'.\n"; + + # Use ReadLine if it's installed and input comes from a console. + if ( -t STDIN && + !ReadlineMightFail() && + defined(eval {require Term::ReadLine}) ) { + my $term = new Term::ReadLine 'pprof'; + while ( defined ($_ = $term->readline('(pprof) '))) { + $term->addhistory($_) if /\S/; + if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { + last; # exit when we get an interactive command to quit + } + } + } else { # don't have readline + while (1) { + print STDERR "(pprof) "; + $_ = ; + last if ! defined $_ ; + s/\r//g; # turn windows-looking lines into unix-looking lines + + # Save some flags that might be reset by InteractiveCommand() + my $save_opt_lines = $main::opt_lines; + + if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { + last; # exit when we get an interactive command to quit + } + + # Restore flags + $main::opt_lines = $save_opt_lines; + } + } +} + +# Takes two args: orig profile, and command to run. +# Returns 1 if we should keep going, or 0 if we were asked to quit +sub InteractiveCommand { + my($orig_profile, $symbols, $libs, $total, $command) = @_; + $_ = $command; # just to make future m//'s easier + if (!defined($_)) { + print STDERR "\n"; + return 0; + } + if (m/^\s*quit/) { + return 0; + } + if (m/^\s*help/) { + InteractiveHelpMessage(); + return 1; + } + # Clear all the mode options -- mode is controlled by "$command" + $main::opt_text = 0; + $main::opt_callgrind = 0; + $main::opt_disasm = 0; + $main::opt_list = 0; + $main::opt_gv = 0; + $main::opt_evince = 0; + $main::opt_cum = 0; + + if (m/^\s*(text|top)(\d*)\s*(.*)/) { + $main::opt_text = 1; + + my $line_limit = ($2 ne "") ? int($2) : 10; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($3); + + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintText($symbols, $flat, $cumulative, $line_limit); + return 1; + } + if (m/^\s*callgrind\s*([^ \n]*)/) { + $main::opt_callgrind = 1; + + # Get derived profiles + my $calls = ExtractCalls($symbols, $orig_profile); + my $filename = $1; + if ( $1 eq '' ) { + $filename = TempName($main::next_tmpfile, "callgrind"); + } + PrintCallgrind($calls, $filename); + if ( $1 eq '' ) { + RunKcachegrind($filename, " & "); + $main::next_tmpfile++; + } + + return 1; + } + if (m/^\s*(web)?list\s*(.+)/) { + my $html = (defined($1) && ($1 eq "web")); + $main::opt_list = 1; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($2); + + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintListing($total, $libs, $flat, $cumulative, $routine, $html); + return 1; + } + if (m/^\s*disasm\s*(.+)/) { + $main::opt_disasm = 1; + + my $routine; + my $ignore; + ($routine, $ignore) = ParseInteractiveArgs($1); + + # Process current profile to account for various settings + my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + PrintDisassembly($libs, $flat, $cumulative, $routine); + return 1; + } + if (m/^\s*(gv|web|evince)\s*(.*)/) { + $main::opt_gv = 0; + $main::opt_evince = 0; + $main::opt_web = 0; + if ($1 eq "gv") { + $main::opt_gv = 1; + } elsif ($1 eq "evince") { + $main::opt_evince = 1; + } elsif ($1 eq "web") { + $main::opt_web = 1; + } + + my $focus; + my $ignore; + ($focus, $ignore) = ParseInteractiveArgs($2); + + # Process current profile to account for various settings + my $profile = ProcessProfile($total, $orig_profile, $symbols, + $focus, $ignore); + my $reduced = ReduceProfile($symbols, $profile); + + # Get derived profiles + my $flat = FlatProfile($reduced); + my $cumulative = CumulativeProfile($reduced); + + if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { + if ($main::opt_gv) { + RunGV(TempName($main::next_tmpfile, "ps"), " &"); + } elsif ($main::opt_evince) { + RunEvince(TempName($main::next_tmpfile, "pdf"), " &"); + } elsif ($main::opt_web) { + RunWeb(TempName($main::next_tmpfile, "svg")); + } + $main::next_tmpfile++; + } + return 1; + } + if (m/^\s*$/) { + return 1; + } + print STDERR "Unknown command: try 'help'.\n"; + return 1; +} + + +sub ProcessProfile { + my $total_count = shift; + my $orig_profile = shift; + my $symbols = shift; + my $focus = shift; + my $ignore = shift; + + # Process current profile to account for various settings + my $profile = $orig_profile; + printf("Total: %s %s\n", Unparse($total_count), Units()); + if ($focus ne '') { + $profile = FocusProfile($symbols, $profile, $focus); + my $focus_count = TotalProfile($profile); + printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n", + $focus, + Unparse($focus_count), Units(), + Unparse($total_count), ($focus_count*100.0) / $total_count); + } + if ($ignore ne '') { + $profile = IgnoreProfile($symbols, $profile, $ignore); + my $ignore_count = TotalProfile($profile); + printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n", + $ignore, + Unparse($ignore_count), Units(), + Unparse($total_count), + ($ignore_count*100.0) / $total_count); + } + + return $profile; +} + +sub InteractiveHelpMessage { + print STDERR <{$k}; + my @addrs = split(/\n/, $k); + if ($#addrs >= 0) { + my $depth = $#addrs + 1; + # int(foo / 2**32) is the only reliable way to get rid of bottom + # 32 bits on both 32- and 64-bit systems. + if ($big_endian) { + print pack('L*', int($count / 2**32), $count & 0xFFFFFFFF); + print pack('L*', int($depth / 2**32), $depth & 0xFFFFFFFF); + } + else { + print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32)); + print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32)); + } + + foreach my $full_addr (@addrs) { + my $addr = $full_addr; + $addr =~ s/0x0*//; # strip off leading 0x, zeroes + if (length($addr) > 16) { + print STDERR "Invalid address in profile: $full_addr\n"; + next; + } + my $low_addr = substr($addr, -8); # get last 8 hex chars + my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars + if ($big_endian) { + print pack('L*', hex('0x' . $high_addr), hex('0x' . $low_addr)); + } + else { + print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr)); + } + } + } + } +} + +# Print symbols and profile data +sub PrintSymbolizedProfile { + my $symbols = shift; + my $profile = shift; + my $prog = shift; + + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + + print '--- ', $symbol_marker, "\n"; + if (defined($prog)) { + print 'binary=', $prog, "\n"; + } + while (my ($pc, $name) = each(%{$symbols})) { + my $sep = ' '; + print '0x', $pc; + # We have a list of function names, which include the inlined + # calls. They are separated (and terminated) by --, which is + # illegal in function names. + for (my $j = 2; $j <= $#{$name}; $j += 3) { + print $sep, $name->[$j]; + $sep = '--'; + } + print "\n"; + } + print '---', "\n"; + + $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $profile_marker = $&; + print '--- ', $profile_marker, "\n"; + if (defined($main::collected_profile)) { + # if used with remote fetch, simply dump the collected profile to output. + open(SRC, "<$main::collected_profile"); + while () { + print $_; + } + close(SRC); + } else { + # dump a cpu-format profile to standard out + PrintProfileData($profile); + } +} + +# Print text output +sub PrintText { + my $symbols = shift; + my $flat = shift; + my $cumulative = shift; + my $line_limit = shift; + + if ($main::opt_stacks && @stackTraces) { + foreach (sort { (split " ", $b)[1] <=> (split " ", $a)[1]; } @stackTraces) { + print "$_\n" if $main::opt_debug; + my ($n1, $s1, $n2, $s2, @addrs) = split; + print "Leak of $s1 bytes in $n1 objects allocated from:\n"; + foreach my $pcstr (@addrs) { + $pcstr =~ s/^0x//; + my $sym; + if (! defined $symbols->{$pcstr}) { + $sym = "unknown"; + } else { + $sym = "$symbols->{$pcstr}[0] $symbols->{$pcstr}[1]"; + } + print "\t@ $pcstr $sym\n"; + } + } + print "\n"; + } + + my $total = TotalProfile($flat); + + # Which profile to sort by? + my $s = $main::opt_cum ? $cumulative : $flat; + + my $running_sum = 0; + my $lines = 0; + foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b } + keys(%{$cumulative})) { + my $f = GetEntry($flat, $k); + my $c = GetEntry($cumulative, $k); + $running_sum += $f; + + my $sym = $k; + if (exists($symbols->{$k})) { + $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1]; + if ($main::opt_addresses) { + $sym = $k . " " . $sym; + } + } + + if ($f != 0 || $c != 0) { + printf("%8s %6s %6s %8s %6s %s\n", + Unparse($f), + Percent($f, $total), + Percent($running_sum, $total), + Unparse($c), + Percent($c, $total), + $sym); + } + $lines++; + last if ($line_limit >= 0 && $lines >= $line_limit); + } +} + +# Callgrind format has a compression for repeated function and file +# names. You show the name the first time, and just use its number +# subsequently. This can cut down the file to about a third or a +# quarter of its uncompressed size. $key and $val are the key/value +# pair that would normally be printed by callgrind; $map is a map from +# value to number. +sub CompressedCGName { + my($key, $val, $map) = @_; + my $idx = $map->{$val}; + # For very short keys, providing an index hurts rather than helps. + if (length($val) <= 3) { + return "$key=$val\n"; + } elsif (defined($idx)) { + return "$key=($idx)\n"; + } else { + # scalar(keys $map) gives the number of items in the map. + $idx = scalar(keys(%{$map})) + 1; + $map->{$val} = $idx; + return "$key=($idx) $val\n"; + } +} + +# Print the call graph in a way that's suiteable for callgrind. +sub PrintCallgrind { + my $calls = shift; + my $filename; + my %filename_to_index_map; + my %fnname_to_index_map; + + if ($main::opt_interactive) { + $filename = shift; + print STDERR "Writing callgrind file to '$filename'.\n" + } else { + $filename = "&STDOUT"; + } + open(CG, ">$filename"); + print CG ("events: Hits\n\n"); + foreach my $call ( map { $_->[0] } + sort { $a->[1] cmp $b ->[1] || + $a->[2] <=> $b->[2] } + map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; + [$_, $1, $2] } + keys %$calls ) { + my $count = int($calls->{$call}); + $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; + my ( $caller_file, $caller_line, $caller_function, + $callee_file, $callee_line, $callee_function ) = + ( $1, $2, $3, $5, $6, $7 ); + + # TODO(csilvers): for better compression, collect all the + # caller/callee_files and functions first, before printing + # anything, and only compress those referenced more than once. + print CG CompressedCGName("fl", $caller_file, \%filename_to_index_map); + print CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map); + if (defined $6) { + print CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map); + print CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map); + print CG ("calls=$count $callee_line\n"); + } + print CG ("$caller_line $count\n\n"); + } +} + +# Print disassembly for all all routines that match $main::opt_disasm +sub PrintDisassembly { + my $libs = shift; + my $flat = shift; + my $cumulative = shift; + my $disasm_opts = shift; + + my $total = TotalProfile($flat); + + foreach my $lib (@{$libs}) { + my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts); + my $offset = AddressSub($lib->[1], $lib->[3]); + foreach my $routine (sort ByName keys(%{$symbol_table})) { + my $start_addr = $symbol_table->{$routine}->[0]; + my $end_addr = $symbol_table->{$routine}->[1]; + # See if there are any samples in this routine + my $length = hex(AddressSub($end_addr, $start_addr)); + my $addr = AddressAdd($start_addr, $offset); + for (my $i = 0; $i < $length; $i++) { + if (defined($cumulative->{$addr})) { + PrintDisassembledFunction($lib->[0], $offset, + $routine, $flat, $cumulative, + $start_addr, $end_addr, $total); + last; + } + $addr = AddressInc($addr); + } + } + } +} + +# Return reference to array of tuples of the form: +# [start_address, filename, linenumber, instruction, limit_address] +# E.g., +# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"] +sub Disassemble { + my $prog = shift; + my $offset = shift; + my $start_addr = shift; + my $end_addr = shift; + + my $objdump = $obj_tool_map{"objdump"}; + my $cmd = ShellEscape($objdump, "-C", "-d", "-l", "--no-show-raw-insn", + "--start-address=0x$start_addr", + "--stop-address=0x$end_addr", $prog); + open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); + my @result = (); + my $filename = ""; + my $linenumber = -1; + my $last = ["", "", "", ""]; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + chop; + if (m|\s*([^:\s]+):(\d+)\s*$|) { + # Location line of the form: + # : + $filename = $1; + $linenumber = $2; + } elsif (m/^ +([0-9a-f]+):\s*(.*)/) { + # Disassembly line -- zero-extend address to full length + my $addr = HexExtend($1); + my $k = AddressAdd($addr, $offset); + $last->[4] = $k; # Store ending address for previous instruction + $last = [$k, $filename, $linenumber, $2, $end_addr]; + push(@result, $last); + } + } + close(OBJDUMP); + return @result; +} + +# The input file should contain lines of the form /proc/maps-like +# output (same format as expected from the profiles) or that looks +# like hex addresses (like "0xDEADBEEF"). We will parse all +# /proc/maps output, and for all the hex addresses, we will output +# "short" symbol names, one per line, in the same order as the input. +sub PrintSymbols { + my $maps_and_symbols_file = shift; + + # ParseLibraries expects pcs to be in a set. Fine by us... + my @pclist = (); # pcs in sorted order + my $pcs = {}; + my $map = ""; + foreach my $line (<$maps_and_symbols_file>) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ($line =~ /\b(0x[0-9a-f]+)\b/i) { + push(@pclist, HexExtend($1)); + $pcs->{$pclist[-1]} = 1; + } else { + $map .= $line; + } + } + + my $libs = ParseLibraries($main::prog, $map, $pcs); + my $symbols = ExtractSymbols($libs, $pcs); + + foreach my $pc (@pclist) { + # ->[0] is the shortname, ->[2] is the full name + print(($symbols->{$pc}->[0] || "??") . "\n"); + } +} + + +# For sorting functions by name +sub ByName { + return ShortFunctionName($a) cmp ShortFunctionName($b); +} + +# Print source-listing for all all routines that match $list_opts +sub PrintListing { + my $total = shift; + my $libs = shift; + my $flat = shift; + my $cumulative = shift; + my $list_opts = shift; + my $html = shift; + + my $output = \*STDOUT; + my $fname = ""; + + if ($html) { + # Arrange to write the output to a temporary file + $fname = TempName($main::next_tmpfile, "html"); + $main::next_tmpfile++; + if (!open(TEMP, ">$fname")) { + print STDERR "$fname: $!\n"; + return; + } + $output = \*TEMP; + print $output HtmlListingHeader(); + printf $output ("
%s
Total: %s %s
\n", + $main::prog, Unparse($total), Units()); + } + + my $listed = 0; + foreach my $lib (@{$libs}) { + my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts); + my $offset = AddressSub($lib->[1], $lib->[3]); + foreach my $routine (sort ByName keys(%{$symbol_table})) { + # Print if there are any samples in this routine + my $start_addr = $symbol_table->{$routine}->[0]; + my $end_addr = $symbol_table->{$routine}->[1]; + my $length = hex(AddressSub($end_addr, $start_addr)); + my $addr = AddressAdd($start_addr, $offset); + for (my $i = 0; $i < $length; $i++) { + if (defined($cumulative->{$addr})) { + $listed += PrintSource( + $lib->[0], $offset, + $routine, $flat, $cumulative, + $start_addr, $end_addr, + $html, + $output); + last; + } + $addr = AddressInc($addr); + } + } + } + + if ($html) { + if ($listed > 0) { + print $output HtmlListingFooter(); + close($output); + RunWeb($fname); + } else { + close($output); + unlink($fname); + } + } +} + +sub HtmlListingHeader { + return <<'EOF'; + + + +Pprof listing + + + + +EOF +} + +sub HtmlListingFooter { + return <<'EOF'; + + +EOF +} + +sub HtmlEscape { + my $text = shift; + $text =~ s/&/&/g; + $text =~ s//>/g; + return $text; +} + +# Returns the indentation of the line, if it has any non-whitespace +# characters. Otherwise, returns -1. +sub Indentation { + my $line = shift; + if (m/^(\s*)\S/) { + return length($1); + } else { + return -1; + } +} + +# If the symbol table contains inlining info, Disassemble() may tag an +# instruction with a location inside an inlined function. But for +# source listings, we prefer to use the location in the function we +# are listing. So use MapToSymbols() to fetch full location +# information for each instruction and then pick out the first +# location from a location list (location list contains callers before +# callees in case of inlining). +# +# After this routine has run, each entry in $instructions contains: +# [0] start address +# [1] filename for function we are listing +# [2] line number for function we are listing +# [3] disassembly +# [4] limit address +# [5] most specific filename (may be different from [1] due to inlining) +# [6] most specific line number (may be different from [2] due to inlining) +sub GetTopLevelLineNumbers { + my ($lib, $offset, $instructions) = @_; + my $pcs = []; + for (my $i = 0; $i <= $#{$instructions}; $i++) { + push(@{$pcs}, $instructions->[$i]->[0]); + } + my $symbols = {}; + MapToSymbols($lib, $offset, $pcs, $symbols); + for (my $i = 0; $i <= $#{$instructions}; $i++) { + my $e = $instructions->[$i]; + push(@{$e}, $e->[1]); + push(@{$e}, $e->[2]); + my $addr = $e->[0]; + my $sym = $symbols->{$addr}; + if (defined($sym)) { + if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) { + $e->[1] = $1; # File name + $e->[2] = $2; # Line number + } + } + } +} + +# Print source-listing for one routine +sub PrintSource { + my $prog = shift; + my $offset = shift; + my $routine = shift; + my $flat = shift; + my $cumulative = shift; + my $start_addr = shift; + my $end_addr = shift; + my $html = shift; + my $output = shift; + + # Disassemble all instructions (just to get line numbers) + my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); + GetTopLevelLineNumbers($prog, $offset, \@instructions); + + # Hack 1: assume that the first source file encountered in the + # disassembly contains the routine + my $filename = undef; + for (my $i = 0; $i <= $#instructions; $i++) { + if ($instructions[$i]->[2] >= 0) { + $filename = $instructions[$i]->[1]; + last; + } + } + if (!defined($filename)) { + print STDERR "no filename found in $routine\n"; + return 0; + } + + # Hack 2: assume that the largest line number from $filename is the + # end of the procedure. This is typically safe since if P1 contains + # an inlined call to P2, then P2 usually occurs earlier in the + # source file. If this does not work, we might have to compute a + # density profile or just print all regions we find. + my $lastline = 0; + for (my $i = 0; $i <= $#instructions; $i++) { + my $f = $instructions[$i]->[1]; + my $l = $instructions[$i]->[2]; + if (($f eq $filename) && ($l > $lastline)) { + $lastline = $l; + } + } + + # Hack 3: assume the first source location from "filename" is the start of + # the source code. + my $firstline = 1; + for (my $i = 0; $i <= $#instructions; $i++) { + if ($instructions[$i]->[1] eq $filename) { + $firstline = $instructions[$i]->[2]; + last; + } + } + + # Hack 4: Extend last line forward until its indentation is less than + # the indentation we saw on $firstline + my $oldlastline = $lastline; + { + if (!open(FILE, "<$filename")) { + print STDERR "$filename: $!\n"; + return 0; + } + my $l = 0; + my $first_indentation = -1; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + $l++; + my $indent = Indentation($_); + if ($l >= $firstline) { + if ($first_indentation < 0 && $indent >= 0) { + $first_indentation = $indent; + last if ($first_indentation == 0); + } + } + if ($l >= $lastline && $indent >= 0) { + if ($indent >= $first_indentation) { + $lastline = $l+1; + } else { + last; + } + } + } + close(FILE); + } + + # Assign all samples to the range $firstline,$lastline, + # Hack 4: If an instruction does not occur in the range, its samples + # are moved to the next instruction that occurs in the range. + my $samples1 = {}; # Map from line number to flat count + my $samples2 = {}; # Map from line number to cumulative count + my $running1 = 0; # Unassigned flat counts + my $running2 = 0; # Unassigned cumulative counts + my $total1 = 0; # Total flat counts + my $total2 = 0; # Total cumulative counts + my %disasm = (); # Map from line number to disassembly + my $running_disasm = ""; # Unassigned disassembly + my $skip_marker = "---\n"; + if ($html) { + $skip_marker = ""; + for (my $l = $firstline; $l <= $lastline; $l++) { + $disasm{$l} = ""; + } + } + my $last_dis_filename = ''; + my $last_dis_linenum = -1; + my $last_touched_line = -1; # To detect gaps in disassembly for a line + foreach my $e (@instructions) { + # Add up counts for all address that fall inside this instruction + my $c1 = 0; + my $c2 = 0; + for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { + $c1 += GetEntry($flat, $a); + $c2 += GetEntry($cumulative, $a); + } + + if ($html) { + my $dis = sprintf(" %6s %6s \t\t%8s: %s ", + HtmlPrintNumber($c1), + HtmlPrintNumber($c2), + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); + + # Append the most specific source line associated with this instruction + if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) }; + $dis = HtmlEscape($dis); + my $f = $e->[5]; + my $l = $e->[6]; + if ($f ne $last_dis_filename) { + $dis .= sprintf("%s:%d", + HtmlEscape(CleanFileName($f)), $l); + } elsif ($l ne $last_dis_linenum) { + # De-emphasize the unchanged file name portion + $dis .= sprintf("%s" . + ":%d", + HtmlEscape(CleanFileName($f)), $l); + } else { + # De-emphasize the entire location + $dis .= sprintf("%s:%d", + HtmlEscape(CleanFileName($f)), $l); + } + $last_dis_filename = $f; + $last_dis_linenum = $l; + $running_disasm .= $dis; + $running_disasm .= "\n"; + } + + $running1 += $c1; + $running2 += $c2; + $total1 += $c1; + $total2 += $c2; + my $file = $e->[1]; + my $line = $e->[2]; + if (($file eq $filename) && + ($line >= $firstline) && + ($line <= $lastline)) { + # Assign all accumulated samples to this line + AddEntry($samples1, $line, $running1); + AddEntry($samples2, $line, $running2); + $running1 = 0; + $running2 = 0; + if ($html) { + if ($line != $last_touched_line && $disasm{$line} ne '') { + $disasm{$line} .= "\n"; + } + $disasm{$line} .= $running_disasm; + $running_disasm = ''; + $last_touched_line = $line; + } + } + } + + # Assign any leftover samples to $lastline + AddEntry($samples1, $lastline, $running1); + AddEntry($samples2, $lastline, $running2); + if ($html) { + if ($lastline != $last_touched_line && $disasm{$lastline} ne '') { + $disasm{$lastline} .= "\n"; + } + $disasm{$lastline} .= $running_disasm; + } + + if ($html) { + printf $output ( + "

%s

%s\n
\n" .
+      "Total:%6s %6s (flat / cumulative %s)\n",
+      HtmlEscape(ShortFunctionName($routine)),
+      HtmlEscape(CleanFileName($filename)),
+      Unparse($total1),
+      Unparse($total2),
+      Units());
+  } else {
+    printf $output (
+      "ROUTINE ====================== %s in %s\n" .
+      "%6s %6s Total %s (flat / cumulative)\n",
+      ShortFunctionName($routine),
+      CleanFileName($filename),
+      Unparse($total1),
+      Unparse($total2),
+      Units());
+  }
+  if (!open(FILE, "<$filename")) {
+    print STDERR "$filename: $!\n";
+    return 0;
+  }
+  my $l = 0;
+  while () {
+    s/\r//g;         # turn windows-looking lines into unix-looking lines
+    $l++;
+    if ($l >= $firstline - 5 &&
+        (($l <= $oldlastline + 5) || ($l <= $lastline))) {
+      chop;
+      my $text = $_;
+      if ($l == $firstline) { print $output $skip_marker; }
+      my $n1 = GetEntry($samples1, $l);
+      my $n2 = GetEntry($samples2, $l);
+      if ($html) {
+        # Emit a span that has one of the following classes:
+        #    livesrc -- has samples
+        #    deadsrc -- has disassembly, but with no samples
+        #    nop     -- has no matching disasembly
+        # Also emit an optional span containing disassembly.
+        my $dis = $disasm{$l};
+        my $asm = "";
+        if (defined($dis) && $dis ne '') {
+          $asm = "" . $dis . "";
+        }
+        my $source_class = (($n1 + $n2 > 0) 
+                            ? "livesrc" 
+                            : (($asm ne "") ? "deadsrc" : "nop"));
+        printf $output (
+          "%5d " .
+          "%6s %6s %s%s\n",
+          $l, $source_class,
+          HtmlPrintNumber($n1),
+          HtmlPrintNumber($n2),
+          HtmlEscape($text),
+          $asm);
+      } else {
+        printf $output(
+          "%6s %6s %4d: %s\n",
+          UnparseAlt($n1),
+          UnparseAlt($n2),
+          $l,
+          $text);
+      }
+      if ($l == $lastline)  { print $output $skip_marker; }
+    };
+  }
+  close(FILE);
+  if ($html) {
+    print $output "
\n"; + } + return 1; +} + +# Return the source line for the specified file/linenumber. +# Returns undef if not found. +sub SourceLine { + my $file = shift; + my $line = shift; + + # Look in cache + if (!defined($main::source_cache{$file})) { + if (100 < scalar keys(%main::source_cache)) { + # Clear the cache when it gets too big + $main::source_cache = (); + } + + # Read all lines from the file + if (!open(FILE, "<$file")) { + print STDERR "$file: $!\n"; + $main::source_cache{$file} = []; # Cache the negative result + return undef; + } + my $lines = []; + push(@{$lines}, ""); # So we can use 1-based line numbers as indices + while () { + push(@{$lines}, $_); + } + close(FILE); + + # Save the lines in the cache + $main::source_cache{$file} = $lines; + } + + my $lines = $main::source_cache{$file}; + if (($line < 0) || ($line > $#{$lines})) { + return undef; + } else { + return $lines->[$line]; + } +} + +# Print disassembly for one routine with interspersed source if available +sub PrintDisassembledFunction { + my $prog = shift; + my $offset = shift; + my $routine = shift; + my $flat = shift; + my $cumulative = shift; + my $start_addr = shift; + my $end_addr = shift; + my $total = shift; + + # Disassemble all instructions + my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); + + # Make array of counts per instruction + my @flat_count = (); + my @cum_count = (); + my $flat_total = 0; + my $cum_total = 0; + foreach my $e (@instructions) { + # Add up counts for all address that fall inside this instruction + my $c1 = 0; + my $c2 = 0; + for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { + $c1 += GetEntry($flat, $a); + $c2 += GetEntry($cumulative, $a); + } + push(@flat_count, $c1); + push(@cum_count, $c2); + $flat_total += $c1; + $cum_total += $c2; + } + + # Print header with total counts + printf("ROUTINE ====================== %s\n" . + "%6s %6s %s (flat, cumulative) %.1f%% of total\n", + ShortFunctionName($routine), + Unparse($flat_total), + Unparse($cum_total), + Units(), + ($cum_total * 100.0) / $total); + + # Process instructions in order + my $current_file = ""; + for (my $i = 0; $i <= $#instructions; ) { + my $e = $instructions[$i]; + + # Print the new file name whenever we switch files + if ($e->[1] ne $current_file) { + $current_file = $e->[1]; + my $fname = $current_file; + $fname =~ s|^\./||; # Trim leading "./" + + # Shorten long file names + if (length($fname) >= 58) { + $fname = "..." . substr($fname, -55); + } + printf("-------------------- %s\n", $fname); + } + + # TODO: Compute range of lines to print together to deal with + # small reorderings. + my $first_line = $e->[2]; + my $last_line = $first_line; + my %flat_sum = (); + my %cum_sum = (); + for (my $l = $first_line; $l <= $last_line; $l++) { + $flat_sum{$l} = 0; + $cum_sum{$l} = 0; + } + + # Find run of instructions for this range of source lines + my $first_inst = $i; + while (($i <= $#instructions) && + ($instructions[$i]->[2] >= $first_line) && + ($instructions[$i]->[2] <= $last_line)) { + $e = $instructions[$i]; + $flat_sum{$e->[2]} += $flat_count[$i]; + $cum_sum{$e->[2]} += $cum_count[$i]; + $i++; + } + my $last_inst = $i - 1; + + # Print source lines + for (my $l = $first_line; $l <= $last_line; $l++) { + my $line = SourceLine($current_file, $l); + if (!defined($line)) { + $line = "?\n"; + next; + } else { + $line =~ s/^\s+//; + } + printf("%6s %6s %5d: %s", + UnparseAlt($flat_sum{$l}), + UnparseAlt($cum_sum{$l}), + $l, + $line); + } + + # Print disassembly + for (my $x = $first_inst; $x <= $last_inst; $x++) { + my $e = $instructions[$x]; + printf("%6s %6s %8s: %6s\n", + UnparseAlt($flat_count[$x]), + UnparseAlt($cum_count[$x]), + UnparseAddress($offset, $e->[0]), + CleanDisassembly($e->[3])); + } + } +} + +# Print DOT graph +sub PrintDot { + my $prog = shift; + my $symbols = shift; + my $raw = shift; + my $flat = shift; + my $cumulative = shift; + my $overall_total = shift; + + # Get total + my $local_total = TotalProfile($flat); + my $nodelimit = int($main::opt_nodefraction * $local_total); + my $edgelimit = int($main::opt_edgefraction * $local_total); + my $nodecount = $main::opt_nodecount; + + # Find nodes to include + my @list = (sort { abs(GetEntry($cumulative, $b)) <=> + abs(GetEntry($cumulative, $a)) + || $a cmp $b } + keys(%{$cumulative})); + my $last = $nodecount - 1; + if ($last > $#list) { + $last = $#list; + } + while (($last >= 0) && + (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) { + $last--; + } + if ($last < 0) { + print STDERR "No nodes to print\n"; + return 0; + } + + if ($nodelimit > 0 || $edgelimit > 0) { + printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n", + Unparse($nodelimit), Units(), + Unparse($edgelimit), Units()); + } + + # Open DOT output file + my $output; + my $escaped_dot = ShellEscape(@DOT); + my $escaped_ps2pdf = ShellEscape(@PS2PDF); + if ($main::opt_gv) { + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "ps")); + $output = "| $escaped_dot -Tps2 >$escaped_outfile"; + } elsif ($main::opt_evince) { + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "pdf")); + $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile"; + } elsif ($main::opt_ps) { + $output = "| $escaped_dot -Tps2"; + } elsif ($main::opt_pdf) { + $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - -"; + } elsif ($main::opt_web || $main::opt_svg) { + # We need to post-process the SVG, so write to a temporary file always. + my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "svg")); + $output = "| $escaped_dot -Tsvg >$escaped_outfile"; + } elsif ($main::opt_gif) { + $output = "| $escaped_dot -Tgif"; + } else { + $output = ">&STDOUT"; + } + open(DOT, $output) || error("$output: $!\n"); + + # Title + printf DOT ("digraph \"%s; %s %s\" {\n", + $prog, + Unparse($overall_total), + Units()); + if ($main::opt_pdf) { + # The output is more printable if we set the page size for dot. + printf DOT ("size=\"8,11\"\n"); + } + printf DOT ("node [width=0.375,height=0.25];\n"); + + # Print legend + printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," . + "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n", + $prog, + sprintf("Total %s: %s", Units(), Unparse($overall_total)), + sprintf("Focusing on: %s", Unparse($local_total)), + sprintf("Dropped nodes with <= %s abs(%s)", + Unparse($nodelimit), Units()), + sprintf("Dropped edges with <= %s %s", + Unparse($edgelimit), Units()) + ); + + # Print nodes + my %node = (); + my $nextnode = 1; + foreach my $a (@list[0..$last]) { + # Pick font size + my $f = GetEntry($flat, $a); + my $c = GetEntry($cumulative, $a); + + my $fs = 8; + if ($local_total > 0) { + $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total))); + } + + $node{$a} = $nextnode++; + my $sym = $a; + $sym =~ s/\s+/\\n/g; + $sym =~ s/::/\\n/g; + + # Extra cumulative info to print for non-leaves + my $extra = ""; + if ($f != $c) { + $extra = sprintf("\\rof %s (%s)", + Unparse($c), + Percent($c, $local_total)); + } + my $style = ""; + if ($main::opt_heapcheck) { + if ($f > 0) { + # make leak-causing nodes more visible (add a background) + $style = ",style=filled,fillcolor=gray" + } elsif ($f < 0) { + # make anti-leak-causing nodes (which almost never occur) + # stand out as well (triple border) + $style = ",peripheries=3" + } + } + + printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" . + "\",shape=box,fontsize=%.1f%s];\n", + $node{$a}, + $sym, + Unparse($f), + Percent($f, $local_total), + $extra, + $fs, + $style, + ); + } + + # Get edges and counts per edge + my %edge = (); + my $n; + my $fullname_to_shortname_map = {}; + FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); + foreach my $k (keys(%{$raw})) { + # TODO: omit low %age edges + $n = $raw->{$k}; + my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); + for (my $i = 1; $i <= $#translated; $i++) { + my $src = $translated[$i]; + my $dst = $translated[$i-1]; + #next if ($src eq $dst); # Avoid self-edges? + if (exists($node{$src}) && exists($node{$dst})) { + my $edge_label = "$src\001$dst"; + if (!exists($edge{$edge_label})) { + $edge{$edge_label} = 0; + } + $edge{$edge_label} += $n; + } + } + } + + # Print edges (process in order of decreasing counts) + my %indegree = (); # Number of incoming edges added per node so far + my %outdegree = (); # Number of outgoing edges added per node so far + foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) { + my @x = split(/\001/, $e); + $n = $edge{$e}; + + # Initialize degree of kept incoming and outgoing edges if necessary + my $src = $x[0]; + my $dst = $x[1]; + if (!exists($outdegree{$src})) { $outdegree{$src} = 0; } + if (!exists($indegree{$dst})) { $indegree{$dst} = 0; } + + my $keep; + if ($indegree{$dst} == 0) { + # Keep edge if needed for reachability + $keep = 1; + } elsif (abs($n) <= $edgelimit) { + # Drop if we are below --edgefraction + $keep = 0; + } elsif ($outdegree{$src} >= $main::opt_maxdegree || + $indegree{$dst} >= $main::opt_maxdegree) { + # Keep limited number of in/out edges per node + $keep = 0; + } else { + $keep = 1; + } + + if ($keep) { + $outdegree{$src}++; + $indegree{$dst}++; + + # Compute line width based on edge count + my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0); + if ($fraction > 1) { $fraction = 1; } + my $w = $fraction * 2; + if ($w < 1 && ($main::opt_web || $main::opt_svg)) { + # SVG output treats line widths < 1 poorly. + $w = 1; + } + + # Dot sometimes segfaults if given edge weights that are too large, so + # we cap the weights at a large value + my $edgeweight = abs($n) ** 0.7; + if ($edgeweight > 100000) { $edgeweight = 100000; } + $edgeweight = int($edgeweight); + + my $style = sprintf("setlinewidth(%f)", $w); + if ($x[1] =~ m/\(inline\)/) { + $style .= ",dashed"; + } + + # Use a slightly squashed function of the edge count as the weight + printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n", + $node{$x[0]}, + $node{$x[1]}, + Unparse($n), + $edgeweight, + $style); + } + } + + print DOT ("}\n"); + close(DOT); + + if ($main::opt_web || $main::opt_svg) { + # Rewrite SVG to be more usable inside web browser. + RewriteSvg(TempName($main::next_tmpfile, "svg")); + } + + return 1; +} + +sub RewriteSvg { + my $svgfile = shift; + + open(SVG, $svgfile) || die "open temp svg: $!"; + my @svg = ; + close(SVG); + unlink $svgfile; + my $svg = join('', @svg); + + # Dot's SVG output is + # + # + # + # ... + # + # + # + # Change it to + # + # + # $svg_javascript + # + # + # ... + # + # + # + + # Fix width, height; drop viewBox. + $svg =~ s/(?s) above first + my $svg_javascript = SvgJavascript(); + my $viewport = "\n"; + $svg =~ s/ above . + $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/; + $svg =~ s/$svgfile") || die "open $svgfile: $!"; + print SVG $svg; + close(SVG); + } +} + +sub SvgJavascript { + return <<'EOF'; + +EOF +} + +# Provides a map from fullname to shortname for cases where the +# shortname is ambiguous. The symlist has both the fullname and +# shortname for all symbols, which is usually fine, but sometimes -- +# such as overloaded functions -- two different fullnames can map to +# the same shortname. In that case, we use the address of the +# function to disambiguate the two. This function fills in a map that +# maps fullnames to modified shortnames in such cases. If a fullname +# is not present in the map, the 'normal' shortname provided by the +# symlist is the appropriate one to use. +sub FillFullnameToShortnameMap { + my $symbols = shift; + my $fullname_to_shortname_map = shift; + my $shortnames_seen_once = {}; + my $shortnames_seen_more_than_once = {}; + + foreach my $symlist (values(%{$symbols})) { + # TODO(csilvers): deal with inlined symbols too. + my $shortname = $symlist->[0]; + my $fullname = $symlist->[2]; + if ($fullname !~ /<[0-9a-fA-F]+>$/) { # fullname doesn't end in an address + next; # the only collisions we care about are when addresses differ + } + if (defined($shortnames_seen_once->{$shortname}) && + $shortnames_seen_once->{$shortname} ne $fullname) { + $shortnames_seen_more_than_once->{$shortname} = 1; + } else { + $shortnames_seen_once->{$shortname} = $fullname; + } + } + + foreach my $symlist (values(%{$symbols})) { + my $shortname = $symlist->[0]; + my $fullname = $symlist->[2]; + # TODO(csilvers): take in a list of addresses we care about, and only + # store in the map if $symlist->[1] is in that list. Saves space. + next if defined($fullname_to_shortname_map->{$fullname}); + if (defined($shortnames_seen_more_than_once->{$shortname})) { + if ($fullname =~ /<0*([^>]*)>$/) { # fullname has address at end of it + $fullname_to_shortname_map->{$fullname} = "$shortname\@$1"; + } + } + } +} + +# Return a small number that identifies the argument. +# Multiple calls with the same argument will return the same number. +# Calls with different arguments will return different numbers. +sub ShortIdFor { + my $key = shift; + my $id = $main::uniqueid{$key}; + if (!defined($id)) { + $id = keys(%main::uniqueid) + 1; + $main::uniqueid{$key} = $id; + } + return $id; +} + +# Translate a stack of addresses into a stack of symbols +sub TranslateStack { + my $symbols = shift; + my $fullname_to_shortname_map = shift; + my $k = shift; + + my @addrs = split(/\n/, $k); + my @result = (); + for (my $i = 0; $i <= $#addrs; $i++) { + my $a = $addrs[$i]; + + # Skip large addresses since they sometimes show up as fake entries on RH9 + if (length($a) > 8 && $a gt "7fffffffffffffff") { + next; + } + + if ($main::opt_disasm || $main::opt_list) { + # We want just the address for the key + push(@result, $a); + next; + } + + my $symlist = $symbols->{$a}; + if (!defined($symlist)) { + $symlist = [$a, "", $a]; + } + + # We can have a sequence of symbols for a particular entry + # (more than one symbol in the case of inlining). Callers + # come before callees in symlist, so walk backwards since + # the translated stack should contain callees before callers. + for (my $j = $#{$symlist}; $j >= 2; $j -= 3) { + my $func = $symlist->[$j-2]; + my $fileline = $symlist->[$j-1]; + my $fullfunc = $symlist->[$j]; + if (defined($fullname_to_shortname_map->{$fullfunc})) { + $func = $fullname_to_shortname_map->{$fullfunc}; + } + if ($j > 2) { + $func = "$func (inline)"; + } + + # Do not merge nodes corresponding to Callback::Run since that + # causes confusing cycles in dot display. Instead, we synthesize + # a unique name for this frame per caller. + if ($func =~ m/Callback.*::Run$/) { + my $caller = ($i > 0) ? $addrs[$i-1] : 0; + $func = "Run#" . ShortIdFor($caller); + } + + if ($main::opt_addresses) { + push(@result, "$a $func $fileline"); + } elsif ($main::opt_lines) { + if ($func eq '??' && $fileline eq '??:0') { + push(@result, "$a"); + } elsif (!$main::opt_show_addresses) { + push(@result, "$func $fileline"); + } else { + push(@result, "$func $fileline ($a)"); + } + } elsif ($main::opt_functions) { + if ($func eq '??') { + push(@result, "$a"); + } elsif (!$main::opt_show_addresses) { + push(@result, $func); + } else { + push(@result, "$func ($a)"); + } + } elsif ($main::opt_files) { + if ($fileline eq '??:0' || $fileline eq '') { + push(@result, "$a"); + } else { + my $f = $fileline; + $f =~ s/:\d+$//; + push(@result, $f); + } + } else { + push(@result, $a); + last; # Do not print inlined info + } + } + } + + # print join(",", @addrs), " => ", join(",", @result), "\n"; + return @result; +} + +# Generate percent string for a number and a total +sub Percent { + my $num = shift; + my $tot = shift; + if ($tot != 0) { + return sprintf("%.1f%%", $num * 100.0 / $tot); + } else { + return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf"); + } +} + +# Generate pretty-printed form of number +sub Unparse { + my $num = shift; + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + if ($main::opt_inuse_objects || $main::opt_alloc_objects) { + return sprintf("%d", $num); + } else { + if ($main::opt_show_bytes) { + return sprintf("%d", $num); + } else { + return sprintf("%.1f", $num / 1048576.0); + } + } + } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { + return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds + } else { + return sprintf("%d", $num); + } +} + +# Alternate pretty-printed form: 0 maps to "." +sub UnparseAlt { + my $num = shift; + if ($num == 0) { + return "."; + } else { + return Unparse($num); + } +} + +# Alternate pretty-printed form: 0 maps to "" +sub HtmlPrintNumber { + my $num = shift; + if ($num == 0) { + return ""; + } else { + return Unparse($num); + } +} + +# Return output units +sub Units { + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + if ($main::opt_inuse_objects || $main::opt_alloc_objects) { + return "objects"; + } else { + if ($main::opt_show_bytes) { + return "B"; + } else { + return "MB"; + } + } + } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { + return "seconds"; + } else { + return "samples"; + } +} + +##### Profile manipulation code ##### + +# Generate flattened profile: +# If count is charged to stack [a,b,c,d], in generated profile, +# it will be charged to [a] +sub FlatProfile { + my $profile = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + if ($#addrs >= 0) { + AddEntry($result, $addrs[0], $count); + } + } + return $result; +} + +# Generate cumulative profile: +# If count is charged to stack [a,b,c,d], in generated profile, +# it will be charged to [a], [b], [c], [d] +sub CumulativeProfile { + my $profile = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + foreach my $a (@addrs) { + AddEntry($result, $a, $count); + } + } + return $result; +} + +# If the second-youngest PC on the stack is always the same, returns +# that pc. Otherwise, returns undef. +sub IsSecondPcAlwaysTheSame { + my $profile = shift; + + my $second_pc = undef; + foreach my $k (keys(%{$profile})) { + my @addrs = split(/\n/, $k); + if ($#addrs < 1) { + return undef; + } + if (not defined $second_pc) { + $second_pc = $addrs[1]; + } else { + if ($second_pc ne $addrs[1]) { + return undef; + } + } + } + return $second_pc; +} + +sub ExtractSymbolLocationInlineStack { + my $symbols = shift; + my $address = shift; + my $stack = shift; + # 'addr2line' outputs "??:0" for unknown locations; we do the + # same to be consistent. + if (exists $symbols->{$address}) { + my @localinlinestack = @{$symbols->{$address}}; + for (my $i = $#localinlinestack; $i > 0; $i-=3) { + my $file = $localinlinestack[$i-1]; + my $fn = $localinlinestack[$i-2]; + if ($file eq "?" || $file eq ":0") { + $file = "??:0"; + } + my $suffix = "[inline]"; + if ($i == 2) { + $suffix = ""; + } + push (@$stack, $file.":".$fn.$suffix); + } + } + else { + push (@$stack, "??:0:unknown"); + } +} + +sub ExtractSymbolNameInlineStack { + my $symbols = shift; + my $address = shift; + + my @stack = (); + + if (exists $symbols->{$address}) { + my @localinlinestack = @{$symbols->{$address}}; + for (my $i = $#localinlinestack; $i > 0; $i-=3) { + my $file = $localinlinestack[$i-1]; + my $fn = $localinlinestack[$i-0]; + + if ($file eq "?" || $file eq ":0") { + $file = "??:0"; + } + if ($fn eq '??') { + # If we can't get the symbol name, at least use the file information. + $fn = $file; + } + my $suffix = "[inline]"; + if ($i == 2) { + $suffix = ""; + } + push (@stack, $fn.$suffix); + } + } + else { + # If we can't get a symbol name, at least fill in the address. + push (@stack, $address); + } + + return @stack; +} + +sub ExtractSymbolLocation { + my $symbols = shift; + my $address = shift; + # 'addr2line' outputs "??:0" for unknown locations; we do the + # same to be consistent. + my $location = "??:0:unknown"; + if (exists $symbols->{$address}) { + my $file = $symbols->{$address}->[1]; + if ($file eq "?" || $file eq ":0") { + $file = "??:0" + } + $location = $file . ":" . $symbols->{$address}->[0]; + } + return $location; +} + +# Extracts a graph of calls. +sub ExtractCalls { + my $symbols = shift; + my $profile = shift; + my $calls = {}; + while( my ($stack_trace, $count) = each %$profile ) { + my @address = split(/\n/, $stack_trace); + my @stack = (); + ExtractSymbolLocationInlineStack($symbols, $address[0], \@stack); + for (my $i = 1; $i <= $#address; $i++) { + ExtractSymbolLocationInlineStack($symbols, $address[$i], \@stack); + } + AddEntry($calls, $stack[0], $count); + for (my $i = 1; $i < $#address; $i++) { + AddEntry($calls, "$stack[$i] -> $stack[$i-1]", $count); + } + } + return $calls; +} + +sub PrintStacksForText { + my $symbols = shift; + my $profile = shift; + + while (my ($stack_trace, $count) = each %$profile) { + my @address = split(/\n/, $stack_trace); + for (my $i = 0; $i <= $#address; $i++) { + $address[$i] = sprintf("(%s) %s", $address[$i], ExtractSymbolLocation($symbols, $address[$i])); + } + printf("%-8d %s\n\n", $count, join("\n ", @address)); + } +} + +sub PrintCollapsedStacks { + my $symbols = shift; + my $profile = shift; + + while (my ($stack_trace, $count) = each %$profile) { + my @address = split(/\n/, $stack_trace); + my @names = reverse ( map { ExtractSymbolNameInlineStack($symbols, $_) } @address ); + printf("%s %d\n", join(";", @names), $count); + } +} + +sub RemoveUninterestingFrames { + my $symbols = shift; + my $profile = shift; + + # List of function names to skip + my %skip = (); + my $skip_regexp = 'NOMATCH'; + if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { + foreach my $name ('calloc', + 'cfree', + 'malloc', + 'free', + 'memalign', + 'posix_memalign', + 'pvalloc', + 'valloc', + 'realloc', + 'tc_calloc', + 'tc_cfree', + 'tc_malloc', + 'tc_free', + 'tc_memalign', + 'tc_posix_memalign', + 'tc_pvalloc', + 'tc_valloc', + 'tc_realloc', + 'tc_new', + 'tc_delete', + 'tc_newarray', + 'tc_deletearray', + 'tc_new_nothrow', + 'tc_newarray_nothrow', + 'do_malloc', + '::do_malloc', # new name -- got moved to an unnamed ns + '::do_malloc_or_cpp_alloc', + 'DoSampledAllocation', + 'simple_alloc::allocate', + '__malloc_alloc_template::allocate', + '__builtin_delete', + '__builtin_new', + '__builtin_vec_delete', + '__builtin_vec_new', + 'operator new', + 'operator new[]', + # The entry to our memory-allocation routines on OS X + 'malloc_zone_malloc', + 'malloc_zone_calloc', + 'malloc_zone_valloc', + 'malloc_zone_realloc', + 'malloc_zone_memalign', + 'malloc_zone_free', + # These mark the beginning/end of our custom sections + '__start_google_malloc', + '__stop_google_malloc', + '__start_malloc_hook', + '__stop_malloc_hook') { + $skip{$name} = 1; + $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything + } + # TODO: Remove TCMalloc once everything has been + # moved into the tcmalloc:: namespace and we have flushed + # old code out of the system. + $skip_regexp = "TCMalloc|^tcmalloc::"; + } elsif ($main::profile_type eq 'contention') { + foreach my $vname ('base::RecordLockProfileData', + 'base::SubmitMutexProfileData', + 'base::SubmitSpinLockProfileData', + 'Mutex::Unlock', + 'Mutex::UnlockSlow', + 'Mutex::ReaderUnlock', + 'MutexLock::~MutexLock', + 'SpinLock::Unlock', + 'SpinLock::SlowUnlock', + 'SpinLockHolder::~SpinLockHolder') { + $skip{$vname} = 1; + } + } elsif ($main::profile_type eq 'cpu' && !$main::opt_no_auto_signal_frames) { + # Drop signal handlers used for CPU profile collection + # TODO(dpeng): this should not be necessary; it's taken + # care of by the general 2nd-pc mechanism below. + foreach my $name ('ProfileData::Add', # historical + 'ProfileData::prof_handler', # historical + 'CpuProfiler::prof_handler', + '__FRAME_END__', + '__pthread_sighandler', + '__restore') { + $skip{$name} = 1; + } + } else { + # Nothing skipped for unknown types + } + + if ($main::profile_type eq 'cpu') { + # If all the second-youngest program counters are the same, + # this STRONGLY suggests that it is an artifact of measurement, + # i.e., stack frames pushed by the CPU profiler signal handler. + # Hence, we delete them. + # (The topmost PC is read from the signal structure, not from + # the stack, so it does not get involved.) + while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) { + my $result = {}; + my $func = ''; + if (exists($symbols->{$second_pc})) { + $second_pc = $symbols->{$second_pc}->[0]; + } + if ($main::opt_no_auto_signal_frames) { + print STDERR "All second stack frames are same: `$second_pc'.\nMight be stack trace capturing bug.\n"; + last; + } + print STDERR "Removing $second_pc from all stack traces.\n"; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my $topaddr = POSIX::strtoul($addrs[0], 16); + splice @addrs, 1, 1; + if ($#addrs > 1) { + my $subtopaddr = POSIX::strtoul($addrs[1], 16); + if ($subtopaddr + 1 == $topaddr) { + splice @addrs, 1, 1; + } + } + my $reduced_path = join("\n", @addrs); + AddEntry($result, $reduced_path, $count); + } + $profile = $result; + } + } + + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my @path = (); + foreach my $a (@addrs) { + if (exists($symbols->{$a})) { + my $func = $symbols->{$a}->[0]; + if ($skip{$func} || ($func =~ m/$skip_regexp/)) { + next; + } + } + push(@path, $a); + } + my $reduced_path = join("\n", @path); + AddEntry($result, $reduced_path, $count); + } + return $result; +} + +# Reduce profile to granularity given by user +sub ReduceProfile { + my $symbols = shift; + my $profile = shift; + my $result = {}; + my $fullname_to_shortname_map = {}; + FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); + my @path = (); + my %seen = (); + $seen{''} = 1; # So that empty keys are skipped + foreach my $e (@translated) { + # To avoid double-counting due to recursion, skip a stack-trace + # entry if it has already been seen + if (!$seen{$e}) { + $seen{$e} = 1; + push(@path, $e); + } + } + my $reduced_path = join("\n", @path); + AddEntry($result, $reduced_path, $count); + } + return $result; +} + +# Does the specified symbol array match the regexp? +sub SymbolMatches { + my $sym = shift; + my $re = shift; + if (defined($sym)) { + for (my $i = 0; $i < $#{$sym}; $i += 3) { + if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) { + return 1; + } + } + } + return 0; +} + +# Focus only on paths involving specified regexps +sub FocusProfile { + my $symbols = shift; + my $profile = shift; + my $focus = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + foreach my $a (@addrs) { + # Reply if it matches either the address/shortname/fileline + if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) { + AddEntry($result, $k, $count); + last; + } + } + } + return $result; +} + +# Focus only on paths not involving specified regexps +sub IgnoreProfile { + my $symbols = shift; + my $profile = shift; + my $ignore = shift; + my $result = {}; + foreach my $k (keys(%{$profile})) { + my $count = $profile->{$k}; + my @addrs = split(/\n/, $k); + my $matched = 0; + foreach my $a (@addrs) { + # Reply if it matches either the address/shortname/fileline + if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) { + $matched = 1; + last; + } + } + if (!$matched) { + AddEntry($result, $k, $count); + } + } + return $result; +} + +# Get total count in profile +sub TotalProfile { + my $profile = shift; + my $result = 0; + foreach my $k (keys(%{$profile})) { + $result += $profile->{$k}; + } + return $result; +} + +# Add A to B +sub AddProfile { + my $A = shift; + my $B = shift; + + my $R = {}; + # add all keys in A + foreach my $k (keys(%{$A})) { + my $v = $A->{$k}; + AddEntry($R, $k, $v); + } + # add all keys in B + foreach my $k (keys(%{$B})) { + my $v = $B->{$k}; + AddEntry($R, $k, $v); + } + return $R; +} + +# Merges symbol maps +sub MergeSymbols { + my $A = shift; + my $B = shift; + + my $R = {}; + foreach my $k (keys(%{$A})) { + $R->{$k} = $A->{$k}; + } + if (defined($B)) { + foreach my $k (keys(%{$B})) { + $R->{$k} = $B->{$k}; + } + } + return $R; +} + + +# Add A to B +sub AddPcs { + my $A = shift; + my $B = shift; + + my $R = {}; + # add all keys in A + foreach my $k (keys(%{$A})) { + $R->{$k} = 1 + } + # add all keys in B + foreach my $k (keys(%{$B})) { + $R->{$k} = 1 + } + return $R; +} + +# Subtract B from A +sub SubtractProfile { + my $A = shift; + my $B = shift; + + my $R = {}; + foreach my $k (keys(%{$A})) { + my $v = $A->{$k} - GetEntry($B, $k); + if ($v < 0 && $main::opt_drop_negative) { + $v = 0; + } + AddEntry($R, $k, $v); + } + if (!$main::opt_drop_negative) { + # Take care of when subtracted profile has more entries + foreach my $k (keys(%{$B})) { + if (!exists($A->{$k})) { + AddEntry($R, $k, 0 - $B->{$k}); + } + } + } + return $R; +} + +# Get entry from profile; zero if not present +sub GetEntry { + my $profile = shift; + my $k = shift; + if (exists($profile->{$k})) { + return $profile->{$k}; + } else { + return 0; + } +} + +# Add entry to specified profile +sub AddEntry { + my $profile = shift; + my $k = shift; + my $n = shift; + if (!exists($profile->{$k})) { + $profile->{$k} = 0; + } + $profile->{$k} += $n; +} + +# Add a stack of entries to specified profile, and add them to the $pcs +# list. +sub AddEntries { + my $profile = shift; + my $pcs = shift; + my $stack = shift; + my $count = shift; + my @k = (); + + foreach my $e (split(/\s+/, $stack)) { + my $pc = HexExtend($e); + $pcs->{$pc} = 1; + push @k, $pc; + } + AddEntry($profile, (join "\n", @k), $count); +} + +##### Code to profile a server dynamically ##### + +sub CheckSymbolPage { + my $url = SymbolPageURL(); + my $command = ShellEscape(@URL_FETCHER, $url); + open(SYMBOL, "$command |") or error($command); + my $line = ; + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + close(SYMBOL); + unless (defined($line)) { + error("$url doesn't exist\n"); + } + + if ($line =~ /^num_symbols:\s+(\d+)$/) { + if ($1 == 0) { + error("Stripped binary. No symbols available.\n"); + } + } else { + error("Failed to get the number of symbols from $url\n"); + } +} + +sub IsProfileURL { + my $profile_name = shift; + if (-f $profile_name) { + printf STDERR "Using local file $profile_name.\n"; + return 0; + } + return 1; +} + +sub ParseProfileURL { + my $profile_name = shift; + + if (!defined($profile_name) || $profile_name eq "") { + return (); + } + + # Split profile URL - matches all non-empty strings, so no test. + $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,; + + my $proto = $1 || "http://"; + my $hostport = $2; + my $prefix = $3; + my $profile = $4 || "/"; + + my $host = $hostport; + $host =~ s/:.*//; + + my $baseurl = "$proto$hostport$prefix"; + return ($host, $baseurl, $profile); +} + +# We fetch symbols from the first profile argument. +sub SymbolPageURL { + my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); + return "$baseURL$SYMBOL_PAGE"; +} + +sub FetchProgramName() { + my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); + my $url = "$baseURL$PROGRAM_NAME_PAGE"; + my $command_line = ShellEscape(@URL_FETCHER, $url); + open(CMDLINE, "$command_line |") or error($command_line); + my $cmdline = ; + $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines + close(CMDLINE); + error("Failed to get program name from $url\n") unless defined($cmdline); + $cmdline =~ s/\x00.+//; # Remove argv[1] and latters. + $cmdline =~ s!\n!!g; # Remove LFs. + return $cmdline; +} + +# Gee, curl's -L (--location) option isn't reliable at least +# with its 7.12.3 version. Curl will forget to post data if +# there is a redirection. This function is a workaround for +# curl. Redirection happens on borg hosts. +sub ResolveRedirectionForCurl { + my $url = shift; + my $command_line = ShellEscape(@URL_FETCHER, "--head", $url); + open(CMDLINE, "$command_line |") or error($command_line); + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (/^Location: (.*)/) { + $url = $1; + } + } + close(CMDLINE); + return $url; +} + +# Add a timeout flat to URL_FETCHER. Returns a new list. +sub AddFetchTimeout { + my $timeout = shift; + my @fetcher = @_; + if (defined($timeout)) { + if (join(" ", @fetcher) =~ m/\bcurl -s/) { + push(@fetcher, "--max-time", sprintf("%d", $timeout)); + } elsif (join(" ", @fetcher) =~ m/\brpcget\b/) { + push(@fetcher, sprintf("--deadline=%d", $timeout)); + } + } + return @fetcher; +} + +# Reads a symbol map from the file handle name given as $1, returning +# the resulting symbol map. Also processes variables relating to symbols. +# Currently, the only variable processed is 'binary=' which updates +# $main::prog to have the correct program name. +sub ReadSymbols { + my $in = shift; + my $map = {}; + while (<$in>) { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Removes all the leading zeroes from the symbols, see comment below. + if (m/^0x0*([0-9a-f]+)\s+(.+)/) { + $map->{$1} = $2; + } elsif (m/^---/) { + last; + } elsif (m/^([a-z][^=]*)=(.*)$/ ) { + my ($variable, $value) = ($1, $2); + for ($variable, $value) { + s/^\s+//; + s/\s+$//; + } + if ($variable eq "binary") { + if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) { + printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n", + $main::prog, $value); + } + $main::prog = $value; + } else { + printf STDERR ("Ignoring unknown variable in symbols list: " . + "'%s' = '%s'\n", $variable, $value); + } + } + } + return $map; +} + +# Fetches and processes symbols to prepare them for use in the profile output +# code. If the optional 'symbol_map' arg is not given, fetches symbols from +# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols +# are assumed to have already been fetched into 'symbol_map' and are simply +# extracted and processed. +sub FetchSymbols { + my $pcset = shift; + my $symbol_map = shift; + + my %seen = (); + my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq + + if (!defined($symbol_map)) { + my $post_data = join("+", sort((map {"0x" . "$_"} @pcs))); + + open(POSTFILE, ">$main::tmpfile_sym"); + print POSTFILE $post_data; + close(POSTFILE); + + my $url = SymbolPageURL(); + + my $command_line; + if (join(" ", @URL_FETCHER) =~ m/\bcurl -s/) { + $url = ResolveRedirectionForCurl($url); + $command_line = ShellEscape(@URL_FETCHER, "-d", "\@$main::tmpfile_sym", + $url); + } else { + $command_line = (ShellEscape(@URL_FETCHER, "--post", $url) + . " < " . ShellEscape($main::tmpfile_sym)); + } + # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols. + my $escaped_cppfilt = ShellEscape($obj_tool_map{"c++filt"}); + open(SYMBOL, "$command_line | $escaped_cppfilt |") or error($command_line); + $symbol_map = ReadSymbols(*SYMBOL{IO}); + close(SYMBOL); + } + + my $symbols = {}; + foreach my $pc (@pcs) { + my $fullname; + # For 64 bits binaries, symbols are extracted with 8 leading zeroes. + # Then /symbol reads the long symbols in as uint64, and outputs + # the result with a "0x%08llx" format which get rid of the zeroes. + # By removing all the leading zeroes in both $pc and the symbols from + # /symbol, the symbols match and are retrievable from the map. + my $shortpc = $pc; + $shortpc =~ s/^0*//; + # Each line may have a list of names, which includes the function + # and also other functions it has inlined. They are separated (in + # PrintSymbolizedProfile), by --, which is illegal in function names. + my $fullnames; + if (defined($symbol_map->{$shortpc})) { + $fullnames = $symbol_map->{$shortpc}; + } else { + $fullnames = "0x" . $pc; # Just use addresses + } + my $sym = []; + $symbols->{$pc} = $sym; + foreach my $fullname (split("--", $fullnames)) { + my $name = ShortFunctionName($fullname); + push(@{$sym}, $name, "?", $fullname); + } + } + return $symbols; +} + +sub BaseName { + my $file_name = shift; + $file_name =~ s!^.*/!!; # Remove directory name + return $file_name; +} + +sub MakeProfileBaseName { + my ($binary_name, $profile_name) = @_; + my ($host, $baseURL, $path) = ParseProfileURL($profile_name); + my $binary_shortname = BaseName($binary_name); + return sprintf("%s.%s.%s", + $binary_shortname, $main::op_time, $host); +} + +sub FetchDynamicProfile { + my $binary_name = shift; + my $profile_name = shift; + my $fetch_name_only = shift; + my $encourage_patience = shift; + + if (!IsProfileURL($profile_name)) { + return $profile_name; + } else { + my ($host, $baseURL, $path) = ParseProfileURL($profile_name); + if ($path eq "" || $path eq "/") { + # Missing type specifier defaults to cpu-profile + $path = $PROFILE_PAGE; + } + + my $profile_file = MakeProfileBaseName($binary_name, $profile_name); + + my $url = "$baseURL$path"; + my $fetch_timeout = undef; + if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) { + if ($path =~ m/[?]/) { + $url .= "&"; + } else { + $url .= "?"; + } + $url .= sprintf("seconds=%d", $main::opt_seconds); + $fetch_timeout = $main::opt_seconds * 1.01 + 60; + } else { + # For non-CPU profiles, we add a type-extension to + # the target profile file name. + my $suffix = $path; + $suffix =~ s,/,.,g; + $profile_file .= $suffix; + } + + my $profile_dir = $ENV{"PPROF_TMPDIR"} || ($ENV{HOME} . "/pprof"); + if (! -d $profile_dir) { + mkdir($profile_dir) + || die("Unable to create profile directory $profile_dir: $!\n"); + } + my $tmp_profile = "$profile_dir/.tmp.$profile_file"; + my $real_profile = "$profile_dir/$profile_file"; + + if ($fetch_name_only > 0) { + return $real_profile; + } + + my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER); + my $cmd = ShellEscape(@fetcher, $url) . " > " . ShellEscape($tmp_profile); + if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){ + print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n"; + if ($encourage_patience) { + print STDERR "Be patient...\n"; + } + } else { + print STDERR "Fetching $path profile from $url to\n ${real_profile}\n"; + } + + (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n"); + (system("mv", $tmp_profile, $real_profile) == 0) || error("Unable to rename profile\n"); + print STDERR "Wrote profile to $real_profile\n"; + $main::collected_profile = $real_profile; + return $main::collected_profile; + } +} + +# Collect profiles in parallel +sub FetchDynamicProfiles { + my $items = scalar(@main::pfile_args); + my $levels = log($items) / log(2); + + if ($items == 1) { + $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1); + } else { + # math rounding issues + if ((2 ** $levels) < $items) { + $levels++; + } + my $count = scalar(@main::pfile_args); + for (my $i = 0; $i < $count; $i++) { + $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0); + } + print STDERR "Fetching $count profiles, Be patient...\n"; + FetchDynamicProfilesRecurse($levels, 0, 0); + $main::collected_profile = join(" \\\n ", @main::profile_files); + } +} + +# Recursively fork a process to get enough processes +# collecting profiles +sub FetchDynamicProfilesRecurse { + my $maxlevel = shift; + my $level = shift; + my $position = shift; + + if (my $pid = fork()) { + $position = 0 | ($position << 1); + TryCollectProfile($maxlevel, $level, $position); + wait; + } else { + $position = 1 | ($position << 1); + TryCollectProfile($maxlevel, $level, $position); + cleanup(); + exit(0); + } +} + +# Collect a single profile +sub TryCollectProfile { + my $maxlevel = shift; + my $level = shift; + my $position = shift; + + if ($level >= ($maxlevel - 1)) { + if ($position < scalar(@main::pfile_args)) { + FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0); + } + } else { + FetchDynamicProfilesRecurse($maxlevel, $level+1, $position); + } +} + +##### Parsing code ##### + +# Provide a small streaming-read module to handle very large +# cpu-profile files. Stream in chunks along a sliding window. +# Provides an interface to get one 'slot', correctly handling +# endian-ness differences. A slot is one 32-bit or 64-bit word +# (depending on the input profile). We tell endianness and bit-size +# for the profile by looking at the first 8 bytes: in cpu profiles, +# the second slot is always 3 (we'll accept anything that's not 0). +BEGIN { + package CpuProfileStream; + + sub new { + my ($class, $file, $fname) = @_; + my $self = { file => $file, + base => 0, + stride => 512 * 1024, # must be a multiple of bitsize/8 + slots => [], + unpack_code => "", # N for big-endian, V for little + perl_is_64bit => 1, # matters if profile is 64-bit + }; + bless $self, $class; + # Let unittests adjust the stride + if ($main::opt_test_stride > 0) { + $self->{stride} = $main::opt_test_stride; + } + # Read the first two slots to figure out bitsize and endianness. + my $slots = $self->{slots}; + my $str; + read($self->{file}, $str, 8); + # Set the global $address_length based on what we see here. + # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars). + $address_length = ($str eq (chr(0)x8)) ? 16 : 8; + if ($address_length == 8) { + if (substr($str, 6, 2) eq chr(0)x2) { + $self->{unpack_code} = 'V'; # Little-endian. + } elsif (substr($str, 4, 2) eq chr(0)x2) { + $self->{unpack_code} = 'N'; # Big-endian + } else { + ::error("$fname: header size >= 2**16\n"); + } + @$slots = unpack($self->{unpack_code} . "*", $str); + } else { + # If we're a 64-bit profile, check if we're a 64-bit-capable + # perl. Otherwise, each slot will be represented as a float + # instead of an int64, losing precision and making all the + # 64-bit addresses wrong. We won't complain yet, but will + # later if we ever see a value that doesn't fit in 32 bits. + my $has_q = 0; + eval { $has_q = pack("Q", "1") ? 1 : 1; }; + if (!$has_q) { + $self->{perl_is_64bit} = 0; + } + read($self->{file}, $str, 8); + if (substr($str, 4, 4) eq chr(0)x4) { + # We'd love to use 'Q', but it's a) not universal, b) not endian-proof. + $self->{unpack_code} = 'V'; # Little-endian. + } elsif (substr($str, 0, 4) eq chr(0)x4) { + $self->{unpack_code} = 'N'; # Big-endian + } else { + ::error("$fname: header size >= 2**32\n"); + } + my @pair = unpack($self->{unpack_code} . "*", $str); + # Since we know one of the pair is 0, it's fine to just add them. + @$slots = (0, $pair[0] + $pair[1]); + } + return $self; + } + + # Load more data when we access slots->get(X) which is not yet in memory. + sub overflow { + my ($self) = @_; + my $slots = $self->{slots}; + $self->{base} += $#$slots + 1; # skip over data we're replacing + my $str; + read($self->{file}, $str, $self->{stride}); + if ($address_length == 8) { # the 32-bit case + # This is the easy case: unpack provides 32-bit unpacking primitives. + @$slots = unpack($self->{unpack_code} . "*", $str); + } else { + # We need to unpack 32 bits at a time and combine. + my @b32_values = unpack($self->{unpack_code} . "*", $str); + my @b64_values = (); + for (my $i = 0; $i < $#b32_values; $i += 2) { + # TODO(csilvers): if this is a 32-bit perl, the math below + # could end up in a too-large int, which perl will promote + # to a double, losing necessary precision. Deal with that. + # Right now, we just die. + my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]); + if ($self->{unpack_code} eq 'N') { # big-endian + ($lo, $hi) = ($hi, $lo); + } + my $value = $lo + $hi * (2**32); + if (!$self->{perl_is_64bit} && # check value is exactly represented + (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) { + ::error("Need a 64-bit perl to process this 64-bit profile.\n"); + } + push(@b64_values, $value); + } + @$slots = @b64_values; + } + } + + # Access the i-th long in the file (logically), or -1 at EOF. + sub get { + my ($self, $idx) = @_; + my $slots = $self->{slots}; + while ($#$slots >= 0) { + if ($idx < $self->{base}) { + # The only time we expect a reference to $slots[$i - something] + # after referencing $slots[$i] is reading the very first header. + # Since $stride > |header|, that shouldn't cause any lookback + # errors. And everything after the header is sequential. + print STDERR "Unexpected look-back reading CPU profile"; + return -1; # shrug, don't know what better to return + } elsif ($idx > $self->{base} + $#$slots) { + $self->overflow(); + } else { + return $slots->[$idx - $self->{base}]; + } + } + # If we get here, $slots is [], which means we've reached EOF + return -1; # unique since slots is supposed to hold unsigned numbers + } +} + +# Reads the top, 'header' section of a profile, and returns the last +# line of the header, commonly called a 'header line'. The header +# section of a profile consists of zero or more 'command' lines that +# are instructions to pprof, which pprof executes when reading the +# header. All 'command' lines start with a %. After the command +# lines is the 'header line', which is a profile-specific line that +# indicates what type of profile it is, and perhaps other global +# information about the profile. For instance, here's a header line +# for a heap profile: +# heap profile: 53: 38236 [ 5525: 1284029] @ heapprofile +# For historical reasons, the CPU profile does not contain a text- +# readable header line. If the profile looks like a CPU profile, +# this function returns "". If no header line could be found, this +# function returns undef. +# +# The following commands are recognized: +# %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:' +# +# The input file should be in binmode. +sub ReadProfileHeader { + local *PROFILE = shift; + my $firstchar = ""; + my $line = ""; + read(PROFILE, $firstchar, 1); + seek(PROFILE, -1, 1); # unread the firstchar + if ($firstchar !~ /[[:print:]]/) { # is not a text character + return ""; + } + while (defined($line = )) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ($line =~ /^%warn\s+(.*)/) { # 'warn' command + # Note this matches both '%warn blah\n' and '%warn\n'. + print STDERR "WARNING: $1\n"; # print the rest of the line + } elsif ($line =~ /^%/) { + print STDERR "Ignoring unknown command from profile header: $line"; + } else { + # End of commands, must be the header line. + return $line; + } + } + return undef; # got to EOF without seeing a header line +} + +sub IsSymbolizedProfileFile { + my $file_name = shift; + if (!(-e $file_name) || !(-r $file_name)) { + return 0; + } + # Check if the file contains a symbol-section marker. + open(TFILE, "<$file_name"); + binmode TFILE; + my $firstline = ReadProfileHeader(*TFILE); + close(TFILE); + if (!$firstline) { + return 0; + } + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + return $firstline =~ /^--- *$symbol_marker/; +} + +# Parse profile generated by common/profiler.cc and return a reference +# to a map: +# $result->{version} Version number of profile file +# $result->{period} Sampling period (in microseconds) +# $result->{profile} Profile object +# $result->{map} Memory map info from profile +# $result->{pcs} Hash of all PC values seen, key is hex address +sub ReadProfile { + my $prog = shift; + my $fname = shift; + my $result; # return value + + $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $contention_marker = $&; + $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $growth_marker = $&; + $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $symbol_marker = $&; + $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash + my $profile_marker = $&; + + # Look at first line to see if it is a heap or a CPU profile. + # CPU profile may start with no header at all, and just binary data + # (starting with \0\0\0\0) -- in that case, don't try to read the + # whole firstline, since it may be gigabytes(!) of data. + open(PROFILE, "<$fname") || error("$fname: $!\n"); + binmode PROFILE; # New perls do UTF-8 processing + my $header = ReadProfileHeader(*PROFILE); + if (!defined($header)) { # means "at EOF" + error("Profile is empty.\n"); + } + + my $symbols; + if ($header =~ m/^--- *$symbol_marker/o) { + # Verify that the user asked for a symbolized profile + if (!$main::use_symbolized_profile) { + # we have both a binary and symbolized profiles, abort + error("FATAL ERROR: Symbolized profile\n $fname\ncannot be used with " . + "a binary arg. Try again without passing\n $prog\n"); + } + # Read the symbol section of the symbolized profile file. + $symbols = ReadSymbols(*PROFILE{IO}); + # Read the next line to get the header for the remaining profile. + $header = ReadProfileHeader(*PROFILE) || ""; + } + + $main::profile_type = ''; + if ($header =~ m/^heap profile:.*$growth_marker/o) { + $main::profile_type = 'growth'; + $result = ReadHeapProfile($prog, *PROFILE, $header); + } elsif ($header =~ m/^heap profile:/) { + $main::profile_type = 'heap'; + $result = ReadHeapProfile($prog, *PROFILE, $header); + } elsif ($header =~ m/^--- *$contention_marker/o) { + $main::profile_type = 'contention'; + $result = ReadSynchProfile($prog, *PROFILE); + } elsif ($header =~ m/^--- *Stacks:/) { + print STDERR + "Old format contention profile: mistakenly reports " . + "condition variable signals as lock contentions.\n"; + $main::profile_type = 'contention'; + $result = ReadSynchProfile($prog, *PROFILE); + } elsif ($header =~ m/^--- *$profile_marker/) { + # the binary cpu profile data starts immediately after this line + $main::profile_type = 'cpu'; + $result = ReadCPUProfile($prog, $fname, *PROFILE); + } else { + if (defined($symbols)) { + # a symbolized profile contains a format we don't recognize, bail out + error("$fname: Cannot recognize profile section after symbols.\n"); + } + # no ascii header present -- must be a CPU profile + $main::profile_type = 'cpu'; + $result = ReadCPUProfile($prog, $fname, *PROFILE); + } + + close(PROFILE); + + # if we got symbols along with the profile, return those as well + if (defined($symbols)) { + $result->{symbols} = $symbols; + } + + return $result; +} + +# Subtract one from caller pc so we map back to call instr. +# However, don't do this if we're reading a symbolized profile +# file, in which case the subtract-one was done when the file +# was written. +# +# We apply the same logic to all readers, though ReadCPUProfile uses an +# independent implementation. +sub FixCallerAddresses { + my $stack = shift; + if ($main::use_symbolized_profile) { + return $stack; + } else { + $stack =~ /(\s)/; + my $delimiter = $1; + my @addrs = split(' ', $stack); + my @fixedaddrs; + $#fixedaddrs = $#addrs; + if ($#addrs >= 0) { + $fixedaddrs[0] = $addrs[0]; + } + for (my $i = 1; $i <= $#addrs; $i++) { + $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1"); + } + return join $delimiter, @fixedaddrs; + } +} + +# CPU profile reader +sub ReadCPUProfile { + my $prog = shift; + my $fname = shift; # just used for logging + local *PROFILE = shift; + my $version; + my $period; + my $i; + my $profile = {}; + my $pcs = {}; + + # Parse string into array of slots. + my $slots = CpuProfileStream->new(*PROFILE, $fname); + + # Read header. The current header version is a 5-element structure + # containing: + # 0: header count (always 0) + # 1: header "words" (after this one: 3) + # 2: format version (0) + # 3: sampling period (usec) + # 4: unused padding (always 0) + if ($slots->get(0) != 0 ) { + error("$fname: not a profile file, or old format profile file\n"); + } + $i = 2 + $slots->get(1); + $version = $slots->get(2); + $period = $slots->get(3); + # Do some sanity checking on these header values. + if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) { + error("$fname: not a profile file, or corrupted profile file\n"); + } + + # Parse profile + while ($slots->get($i) != -1) { + my $n = $slots->get($i++); + my $d = $slots->get($i++); + if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth? + my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8)); + print STDERR "At index $i (address $addr):\n"; + error("$fname: stack trace depth >= 2**32\n"); + } + if ($slots->get($i) == 0) { + # End of profile data marker + $i += $d; + last; + } + + # Make key out of the stack entries + my @k = (); + for (my $j = 0; $j < $d; $j++) { + my $pc = $slots->get($i+$j); + # Subtract one from caller pc so we map back to call instr. + # However, don't do this if we're reading a symbolized profile + # file, in which case the subtract-one was done when the file + # was written. + if ($j > 0 && !$main::use_symbolized_profile) { + $pc--; + } + $pc = sprintf("%0*x", $address_length, $pc); + $pcs->{$pc} = 1; + push @k, $pc; + } + + AddEntry($profile, (join "\n", @k), $n); + $i += $d; + } + + # Parse map + my $map = ''; + seek(PROFILE, $i * ($address_length / 2), 0); + read(PROFILE, $map, (stat PROFILE)[7]); + + my $r = {}; + $r->{version} = $version; + $r->{period} = $period; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + + return $r; +} + +sub ReadHeapProfile { + my $prog = shift; + local *PROFILE = shift; + my $header = shift; + + my $index = 1; + if ($main::opt_inuse_space) { + $index = 1; + } elsif ($main::opt_inuse_objects) { + $index = 0; + } elsif ($main::opt_alloc_space) { + $index = 3; + } elsif ($main::opt_alloc_objects) { + $index = 2; + } + + # Find the type of this profile. The header line looks like: + # heap profile: 1246: 8800744 [ 1246: 8800744] @ /266053 + # There are two pairs , the first inuse objects/space, and the + # second allocated objects/space. This is followed optionally by a profile + # type, and if that is present, optionally by a sampling frequency. + # For remote heap profiles (v1): + # The interpretation of the sampling frequency is that the profiler, for + # each sample, calculates a uniformly distributed random integer less than + # the given value, and records the next sample after that many bytes have + # been allocated. Therefore, the expected sample interval is half of the + # given frequency. By default, if not specified, the expected sample + # interval is 128KB. Only remote-heap-page profiles are adjusted for + # sample size. + # For remote heap profiles (v2): + # The sampling frequency is the rate of a Poisson process. This means that + # the probability of sampling an allocation of size X with sampling rate Y + # is 1 - exp(-X/Y) + # For version 2, a typical header line might look like this: + # heap profile: 1922: 127792360 [ 1922: 127792360] @ _v2/524288 + # the trailing number (524288) is the sampling rate. (Version 1 showed + # double the 'rate' here) + my $sampling_algorithm = 0; + my $sample_adjustment = 0; + chomp($header); + my $type = "unknown"; + if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") { + if (defined($6) && ($6 ne '')) { + $type = $6; + my $sample_period = $8; + # $type is "heapprofile" for profiles generated by the + # heap-profiler, and either "heap" or "heap_v2" for profiles + # generated by sampling directly within tcmalloc. It can also + # be "growth" for heap-growth profiles. The first is typically + # found for profiles generated locally, and the others for + # remote profiles. + if (($type eq "heapprofile") || ($type !~ /heap/) ) { + # No need to adjust for the sampling rate with heap-profiler-derived data + $sampling_algorithm = 0; + } elsif ($type =~ /_v2/) { + $sampling_algorithm = 2; # version 2 sampling + if (defined($sample_period) && ($sample_period ne '')) { + $sample_adjustment = int($sample_period); + } + } else { + $sampling_algorithm = 1; # version 1 sampling + if (defined($sample_period) && ($sample_period ne '')) { + $sample_adjustment = int($sample_period)/2; + } + } + } else { + # We detect whether or not this is a remote-heap profile by checking + # that the total-allocated stats ($n2,$s2) are exactly the + # same as the in-use stats ($n1,$s1). It is remotely conceivable + # that a non-remote-heap profile may pass this check, but it is hard + # to imagine how that could happen. + # In this case it's so old it's guaranteed to be remote-heap version 1. + my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); + if (($n1 == $n2) && ($s1 == $s2)) { + # This is likely to be a remote-heap based sample profile + $sampling_algorithm = 1; + } + } + } + + if ($sampling_algorithm > 0) { + # For remote-heap generated profiles, adjust the counts and sizes to + # account for the sample rate (we sample once every 128KB by default). + if ($sample_adjustment == 0) { + # Turn on profile adjustment. + $sample_adjustment = 128*1024; + print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n"; + } else { + printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n", + $sample_adjustment); + } + if ($sampling_algorithm > 1) { + # We don't bother printing anything for the original version (version 1) + printf STDERR "Heap version $sampling_algorithm\n"; + } + } + + my $profile = {}; + my $pcs = {}; + my $map = ""; + + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (/^MAPPED_LIBRARIES:/) { + # Read the /proc/self/maps data + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + $map .= $_; + } + last; + } + + if (/^--- Memory map:/) { + # Read /proc/self/maps data as formatted by DumpAddressMap() + my $buildvar = ""; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Parse "build=" specification if supplied + if (m/^\s*build=(.*)\n/) { + $buildvar = $1; + } + + # Expand "$build" variable if available + $_ =~ s/\$build\b/$buildvar/g; + + $map .= $_; + } + last; + } + + # Read entry of the form: + # : [: ] @ a1 a2 a3 ... an + s/^\s*//; + s/\s*$//; + if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) { + my $stack = $5; + my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); + + if ($sample_adjustment) { + if ($sampling_algorithm == 2) { + # Remote-heap version 2 + # The sampling frequency is the rate of a Poisson process. + # This means that the probability of sampling an allocation of + # size X with sampling rate Y is 1 - exp(-X/Y) + if ($n1 != 0) { + my $ratio = (($s1*1.0)/$n1)/($sample_adjustment); + my $scale_factor = 1/(1 - exp(-$ratio)); + $n1 *= $scale_factor; + $s1 *= $scale_factor; + } + if ($n2 != 0) { + my $ratio = (($s2*1.0)/$n2)/($sample_adjustment); + my $scale_factor = 1/(1 - exp(-$ratio)); + $n2 *= $scale_factor; + $s2 *= $scale_factor; + } + } else { + # Remote-heap version 1 + my $ratio; + $ratio = (($s1*1.0)/$n1)/($sample_adjustment); + if ($ratio < 1) { + $n1 /= $ratio; + $s1 /= $ratio; + } + $ratio = (($s2*1.0)/$n2)/($sample_adjustment); + if ($ratio < 1) { + $n2 /= $ratio; + $s2 /= $ratio; + } + } + } + + my @counts = ($n1, $s1, $n2, $s2); + $stack = FixCallerAddresses($stack); + push @stackTraces, "$n1 $s1 $n2 $s2 $stack"; + AddEntries($profile, $pcs, $stack, $counts[$index]); + } + } + + my $r = {}; + $r->{version} = "heap"; + $r->{period} = 1; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + return $r; +} + +sub ReadSynchProfile { + my $prog = shift; + local *PROFILE = shift; + my $header = shift; + + my $map = ''; + my $profile = {}; + my $pcs = {}; + my $sampling_period = 1; + my $cyclespernanosec = 2.8; # Default assumption for old binaries + my $seen_clockrate = 0; + my $line; + + my $index = 0; + if ($main::opt_total_delay) { + $index = 0; + } elsif ($main::opt_contentions) { + $index = 1; + } elsif ($main::opt_mean_delay) { + $index = 2; + } + + while ( $line = ) { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) { + my ($cycles, $count, $stack) = ($1, $2, $3); + + # Convert cycles to nanoseconds + $cycles /= $cyclespernanosec; + + # Adjust for sampling done by application + $cycles *= $sampling_period; + $count *= $sampling_period; + + my @values = ($cycles, $count, $cycles / $count); + AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]); + + } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ || + $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) { + my ($cycles, $stack) = ($1, $2); + if ($cycles !~ /^\d+$/) { + next; + } + + # Convert cycles to nanoseconds + $cycles /= $cyclespernanosec; + + # Adjust for sampling done by application + $cycles *= $sampling_period; + + AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles); + + } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) { + my ($variable, $value) = ($1,$2); + for ($variable, $value) { + s/^\s+//; + s/\s+$//; + } + if ($variable eq "cycles/second") { + $cyclespernanosec = $value / 1e9; + $seen_clockrate = 1; + } elsif ($variable eq "sampling period") { + $sampling_period = $value; + } elsif ($variable eq "ms since reset") { + # Currently nothing is done with this value in pprof + # So we just silently ignore it for now + } elsif ($variable eq "discarded samples") { + # Currently nothing is done with this value in pprof + # So we just silently ignore it for now + } else { + printf STDERR ("Ignoring unnknown variable in /contention output: " . + "'%s' = '%s'\n",$variable,$value); + } + } else { + # Memory map entry + $map .= $line; + } + } + + if (!$seen_clockrate) { + printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n", + $cyclespernanosec); + } + + my $r = {}; + $r->{version} = 0; + $r->{period} = $sampling_period; + $r->{profile} = $profile; + $r->{libs} = ParseLibraries($prog, $map, $pcs); + $r->{pcs} = $pcs; + return $r; +} + +# Given a hex value in the form "0x1abcd" or "1abcd", return either +# "0001abcd" or "000000000001abcd", depending on the current (global) +# address length. +sub HexExtend { + my $addr = shift; + + $addr =~ s/^(0x)?0*//; + my $zeros_needed = $address_length - length($addr); + if ($zeros_needed < 0) { + printf STDERR "Warning: address $addr is longer than address length $address_length\n"; + return $addr; + } + return ("0" x $zeros_needed) . $addr; +} + +##### Symbol extraction ##### + +# Aggressively search the lib_prefix values for the given library +# If all else fails, just return the name of the library unmodified. +# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so" +# it will search the following locations in this order, until it finds a file: +# /my/path/lib/dir/mylib.so +# /other/path/lib/dir/mylib.so +# /my/path/dir/mylib.so +# /other/path/dir/mylib.so +# /my/path/mylib.so +# /other/path/mylib.so +# /lib/dir/mylib.so (returned as last resort) +sub FindLibrary { + my $file = shift; + my $suffix = $file; + + # Search for the library as described above + do { + foreach my $prefix (@prefix_list) { + my $fullpath = $prefix . $suffix; + if (-e $fullpath) { + return $fullpath; + } + } + } while ($suffix =~ s|^/[^/]+/|/|); + return $file; +} + +# Return path to library with debugging symbols. +# For libc libraries, the copy in /usr/lib/debug contains debugging symbols +sub DebuggingLibrary { + my $file = shift; + if ($file =~ m|^/| && -f "/usr/lib/debug$file") { + return "/usr/lib/debug$file"; + } + if ($file =~ m|^/| && -f "/usr/lib/debug$file.debug") { + return "/usr/lib/debug$file.debug"; + } + return undef; +} + +# Parse text section header of a library using objdump +sub ParseTextSectionHeaderFromObjdump { + my $lib = shift; + + my $size = undef; + my $vma; + my $file_offset; + # Get objdump output from the library file to figure out how to + # map between mapped addresses and addresses in the library. + my $cmd = ShellEscape($obj_tool_map{"objdump"}, "-h", $lib); + open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + # Idx Name Size VMA LMA File off Algn + # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4 + # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file + # offset may still be 8. But AddressSub below will still handle that. + my @x = split; + if (($#x >= 6) && ($x[1] eq '.text')) { + $size = $x[2]; + $vma = $x[3]; + $file_offset = $x[5]; + last; + } + } + close(OBJDUMP); + + if (!defined($size)) { + return undef; + } + + my $r = {}; + $r->{size} = $size; + $r->{vma} = $vma; + $r->{file_offset} = $file_offset; + + return $r; +} + +# Parse text section header of a library using otool (on OS X) +sub ParseTextSectionHeaderFromOtool { + my $lib = shift; + + my $size = undef; + my $vma = undef; + my $file_offset = undef; + # Get otool output from the library file to figure out how to + # map between mapped addresses and addresses in the library. + my $command = ShellEscape($obj_tool_map{"otool"}, "-l", $lib); + open(OTOOL, "$command |") || error("$command: $!\n"); + my $cmd = ""; + my $sectname = ""; + my $segname = ""; + foreach my $line () { + $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines + # Load command <#> + # cmd LC_SEGMENT + # [...] + # Section + # sectname __text + # segname __TEXT + # addr 0x000009f8 + # size 0x00018b9e + # offset 2552 + # align 2^2 (4) + # We will need to strip off the leading 0x from the hex addresses, + # and convert the offset into hex. + if ($line =~ /Load command/) { + $cmd = ""; + $sectname = ""; + $segname = ""; + } elsif ($line =~ /Section/) { + $sectname = ""; + $segname = ""; + } elsif ($line =~ /cmd (\w+)/) { + $cmd = $1; + } elsif ($line =~ /sectname (\w+)/) { + $sectname = $1; + } elsif ($line =~ /segname (\w+)/) { + $segname = $1; + } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") && + $sectname eq "__text" && + $segname eq "__TEXT")) { + next; + } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) { + $vma = $1; + } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) { + $size = $1; + } elsif ($line =~ /\boffset ([0-9]+)/) { + $file_offset = sprintf("%016x", $1); + } + if (defined($vma) && defined($size) && defined($file_offset)) { + last; + } + } + close(OTOOL); + + if (!defined($vma) || !defined($size) || !defined($file_offset)) { + return undef; + } + + my $r = {}; + $r->{size} = $size; + $r->{vma} = $vma; + $r->{file_offset} = $file_offset; + + return $r; +} + +sub ParseTextSectionHeader { + # obj_tool_map("otool") is only defined if we're in a Mach-O environment + if (defined($obj_tool_map{"otool"})) { + my $r = ParseTextSectionHeaderFromOtool(@_); + if (defined($r)){ + return $r; + } + } + # If otool doesn't work, or we don't have it, fall back to objdump + return ParseTextSectionHeaderFromObjdump(@_); +} + +# Split /proc/pid/maps dump into a list of libraries +sub ParseLibraries { + return if $main::use_symbol_page; # We don't need libraries info. + my $prog = Cwd::abs_path(shift); + my $map = shift; + my $pcs = shift; + + my $result = []; + my $h = "[a-f0-9]+"; + my $zero_offset = HexExtend("0"); + + my $buildvar = ""; + foreach my $l (split("\n", $map)) { + if ($l =~ m/^\s*build=(.*)$/) { + $buildvar = $1; + } + + my $start; + my $finish; + my $offset; + my $lib; + if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(.+\.(so|dll|dylib|bundle|node)((\.\d+)+\w*(\.\d+){0,3})?)$/i) { + # Full line from /proc/self/maps. Example: + # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = HexExtend($3); + $lib = $4; + $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths + } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) { + # Cooked line from DumpAddressMap. Example: + # 40000000-40015000: /lib/ld-2.3.2.so + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = $zero_offset; + $lib = $3; + } elsif (($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+)$/i) && ($4 eq $prog)) { + # PIEs and address space randomization do not play well with our + # default assumption that main executable is at lowest + # addresses. So we're detecting main executable in + # /proc/self/maps as well. + $start = HexExtend($1); + $finish = HexExtend($2); + $offset = HexExtend($3); + $lib = $4; + $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths + } else { + next; + } + + # Expand "$build" variable if available + $lib =~ s/\$build\b/$buildvar/g; + + $lib = FindLibrary($lib); + + # Check for pre-relocated libraries, which use pre-relocated symbol tables + # and thus require adjusting the offset that we'll use to translate + # VM addresses into symbol table addresses. + # Only do this if we're not going to fetch the symbol table from a + # debugging copy of the library. + if (!DebuggingLibrary($lib)) { + my $text = ParseTextSectionHeader($lib); + if (defined($text)) { + my $vma_offset = AddressSub($text->{vma}, $text->{file_offset}); + $offset = AddressAdd($offset, $vma_offset); + } + } + + push(@{$result}, [$lib, $start, $finish, $offset]); + } + + # Append special entry for additional library (not relocated) + if ($main::opt_lib ne "") { + my $text = ParseTextSectionHeader($main::opt_lib); + if (defined($text)) { + my $start = $text->{vma}; + my $finish = AddressAdd($start, $text->{size}); + + push(@{$result}, [$main::opt_lib, $start, $finish, $start]); + } + } + + # Append special entry for the main program. This covers + # 0..max_pc_value_seen, so that we assume pc values not found in one + # of the library ranges will be treated as coming from the main + # program binary. + my $min_pc = HexExtend("0"); + my $max_pc = $min_pc; # find the maximal PC value in any sample + foreach my $pc (keys(%{$pcs})) { + if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); } + } + push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]); + + return $result; +} + +# Add two hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressAdd { + my $addr1 = shift; + my $addr2 = shift; + my $sum; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16); + return sprintf("%08x", $sum); + + } else { + # Do the addition in 7-nibble chunks to trivialize carry handling. + + if ($main::opt_debug and $main::opt_test) { + print STDERR "AddressAdd $addr1 + $addr2 = "; + } + + my $a1 = substr($addr1,-7); + $addr1 = substr($addr1,0,-7); + my $a2 = substr($addr2,-7); + $addr2 = substr($addr2,0,-7); + $sum = hex($a1) + hex($a2); + my $c = 0; + if ($sum > 0xfffffff) { + $c = 1; + $sum -= 0x10000000; + } + my $r = sprintf("%07x", $sum); + + $a1 = substr($addr1,-7); + $addr1 = substr($addr1,0,-7); + $a2 = substr($addr2,-7); + $addr2 = substr($addr2,0,-7); + $sum = hex($a1) + hex($a2) + $c; + $c = 0; + if ($sum > 0xfffffff) { + $c = 1; + $sum -= 0x10000000; + } + $r = sprintf("%07x", $sum) . $r; + + $sum = hex($addr1) + hex($addr2) + $c; + if ($sum > 0xff) { $sum -= 0x100; } + $r = sprintf("%02x", $sum) . $r; + + if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; } + + return $r; + } +} + + +# Subtract two hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressSub { + my $addr1 = shift; + my $addr2 = shift; + my $diff; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16); + return sprintf("%08x", $diff); + + } else { + # Do the addition in 7-nibble chunks to trivialize borrow handling. + # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; } + + my $a1 = hex(substr($addr1,-7)); + $addr1 = substr($addr1,0,-7); + my $a2 = hex(substr($addr2,-7)); + $addr2 = substr($addr2,0,-7); + my $b = 0; + if ($a2 > $a1) { + $b = 1; + $a1 += 0x10000000; + } + $diff = $a1 - $a2; + my $r = sprintf("%07x", $diff); + + $a1 = hex(substr($addr1,-7)); + $addr1 = substr($addr1,0,-7); + $a2 = hex(substr($addr2,-7)) + $b; + $addr2 = substr($addr2,0,-7); + $b = 0; + if ($a2 > $a1) { + $b = 1; + $a1 += 0x10000000; + } + $diff = $a1 - $a2; + $r = sprintf("%07x", $diff) . $r; + + $a1 = hex($addr1); + $a2 = hex($addr2) + $b; + if ($a2 > $a1) { $a1 += 0x100; } + $diff = $a1 - $a2; + $r = sprintf("%02x", $diff) . $r; + + # if ($main::opt_debug) { print STDERR "$r\n"; } + + return $r; + } +} + +# Increment a hex addresses of length $address_length. +# Run pprof --test for unit test if this is changed. +sub AddressInc { + my $addr = shift; + my $sum; + + if ($address_length == 8) { + # Perl doesn't cope with wraparound arithmetic, so do it explicitly: + $sum = (hex($addr)+1) % (0x10000000 * 16); + return sprintf("%08x", $sum); + + } else { + # Do the addition in 7-nibble chunks to trivialize carry handling. + # We are always doing this to step through the addresses in a function, + # and will almost never overflow the first chunk, so we check for this + # case and exit early. + + # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; } + + my $a1 = substr($addr,-7); + $addr = substr($addr,0,-7); + $sum = hex($a1) + 1; + my $r = sprintf("%07x", $sum); + if ($sum <= 0xfffffff) { + $r = $addr . $r; + # if ($main::opt_debug) { print STDERR "$r\n"; } + return HexExtend($r); + } else { + $r = "0000000"; + } + + $a1 = substr($addr,-7); + $addr = substr($addr,0,-7); + $sum = hex($a1) + 1; + $r = sprintf("%07x", $sum) . $r; + if ($sum <= 0xfffffff) { + $r = $addr . $r; + # if ($main::opt_debug) { print STDERR "$r\n"; } + return HexExtend($r); + } else { + $r = "00000000000000"; + } + + $sum = hex($addr) + 1; + if ($sum > 0xff) { $sum -= 0x100; } + $r = sprintf("%02x", $sum) . $r; + + # if ($main::opt_debug) { print STDERR "$r\n"; } + return $r; + } +} + +# Extract symbols for all PC values found in profile +sub ExtractSymbols { + my $libs = shift; + my $pcset = shift; + + my $symbols = {}; + + # Map each PC value to the containing library. To make this faster, + # we sort libraries by their starting pc value (highest first), and + # advance through the libraries as we advance the pc. Sometimes the + # addresses of libraries may overlap with the addresses of the main + # binary, so to make sure the libraries 'win', we iterate over the + # libraries in reverse order (which assumes the binary doesn't start + # in the middle of a library, which seems a fair assumption). + my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings + foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) { + my $libname = $lib->[0]; + my $start = $lib->[1]; + my $finish = $lib->[2]; + my $offset = $lib->[3]; + + # Get list of pcs that belong in this library. + my $contained = []; + my ($start_pc_index, $finish_pc_index); + # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index]. + for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0; + $finish_pc_index--) { + last if $pcs[$finish_pc_index - 1] le $finish; + } + # Find smallest start_pc_index such that $start <= $pc[$start_pc_index]. + for ($start_pc_index = $finish_pc_index; $start_pc_index > 0; + $start_pc_index--) { + last if $pcs[$start_pc_index - 1] lt $start; + } + # This keeps PC values higher than $pc[$finish_pc_index] in @pcs, + # in case there are overlaps in libraries and the main binary. + @{$contained} = splice(@pcs, $start_pc_index, + $finish_pc_index - $start_pc_index); + # Map to symbols + MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols); + } + + return $symbols; +} + +# Map list of PC values to symbols for a given image +sub MapToSymbols { + my $image = shift; + my $offset = shift; + my $pclist = shift; + my $symbols = shift; + + my $debug = 0; + + # For libc (and other) libraries, the copy in /usr/lib/debug contains debugging symbols + my $debugging = DebuggingLibrary($image); + if ($debugging) { + $image = $debugging; + } + + # Ignore empty binaries + if ($#{$pclist} < 0) { return; } + + # Figure out the addr2line command to use + my $addr2line = $obj_tool_map{"addr2line"}; + my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image); + if (exists $obj_tool_map{"addr2line_pdb"}) { + $addr2line = $obj_tool_map{"addr2line_pdb"}; + $cmd = ShellEscape($addr2line, "--demangle", "-f", "-C", "-e", $image); + } + + # If "addr2line" isn't installed on the system at all, just use + # nm to get what info we can (function names, but not line numbers). + if (system(ShellEscape($addr2line, "--help") . " >$dev_null 2>&1") != 0) { + MapSymbolsWithNM($image, $offset, $pclist, $symbols); + return; + } + + # "addr2line -i" can produce a variable number of lines per input + # address, with no separator that allows us to tell when data for + # the next address starts. So we find the address for a special + # symbol (_fini) and interleave this address between all real + # addresses passed to addr2line. The name of this special symbol + # can then be used as a separator. + $sep_address = undef; # May be filled in by MapSymbolsWithNM() + my $nm_symbols = {}; + MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols); + if (defined($sep_address)) { + # Only add " -i" to addr2line if the binary supports it. + # addr2line --help returns 0, but not if it sees an unknown flag first. + if (system("$cmd -i --help >$dev_null 2>&1") == 0) { + $cmd .= " -i"; + } else { + $sep_address = undef; # no need for sep_address if we don't support -i + } + } + + # Make file with all PC values with intervening 'sep_address' so + # that we can reliably detect the end of inlined function list + open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n"); + if ($debug) { print("---- $image ---\n"); } + for (my $i = 0; $i <= $#{$pclist}; $i++) { + # addr2line always reads hex addresses, and does not need '0x' prefix. + if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); } + printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset)); + if (defined($sep_address)) { + printf ADDRESSES ("%s\n", $sep_address); + } + } + close(ADDRESSES); + if ($debug) { + print("----\n"); + system("cat", $main::tmpfile_sym); + print("---- $cmd ---\n"); + system("$cmd < " . ShellEscape($main::tmpfile_sym)); + print("----\n"); + } + + open(SYMBOLS, "$cmd <" . ShellEscape($main::tmpfile_sym) . " |") + || error("$cmd: $!\n"); + my $count = 0; # Index in pclist + while () { + # Read fullfunction and filelineinfo from next pair of lines + s/\r?\n$//g; + my $fullfunction = $_; + $_ = ; + s/\r?\n$//g; + my $filelinenum = $_; + + if (defined($sep_address) && $fullfunction eq $sep_symbol) { + # Terminating marker for data for this address + $count++; + next; + } + + $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths + + # Remove discriminator markers as this comes after the line number and + # confuses the rest of this script. + $filelinenum =~ s/ \(discriminator \d+\)$//; + # Convert unknown line numbers into line 0. + $filelinenum =~ s/:\?$/:0/; + + my $pcstr = $pclist->[$count]; + my $function = ShortFunctionName($fullfunction); + my $nms = $nm_symbols->{$pcstr}; + if (defined($nms)) { + if ($fullfunction eq '??') { + # nm found a symbol for us. + $function = $nms->[0]; + $fullfunction = $nms->[2]; + } else { + # MapSymbolsWithNM tags each routine with its starting address, + # useful in case the image has multiple occurrences of this + # routine. (It uses a syntax that resembles template paramters, + # that are automatically stripped out by ShortFunctionName().) + # addr2line does not provide the same information. So we check + # if nm disambiguated our symbol, and if so take the annotated + # (nm) version of the routine-name. TODO(csilvers): this won't + # catch overloaded, inlined symbols, which nm doesn't see. + # Better would be to do a check similar to nm's, in this fn. + if ($nms->[2] =~ m/^\Q$function\E/) { # sanity check it's the right fn + $function = $nms->[0]; + $fullfunction = $nms->[2]; + } + } + } + + # Prepend to accumulated symbols for pcstr + # (so that caller comes before callee) + my $sym = $symbols->{$pcstr}; + if (!defined($sym)) { + $sym = []; + $symbols->{$pcstr} = $sym; + } + unshift(@{$sym}, $function, $filelinenum, $fullfunction); + if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); } + if (!defined($sep_address)) { + # Inlining is off, so this entry ends immediately + $count++; + } + } + close(SYMBOLS); +} + +# Use nm to map the list of referenced PCs to symbols. Return true iff we +# are able to read procedure information via nm. +sub MapSymbolsWithNM { + my $image = shift; + my $offset = shift; + my $pclist = shift; + my $symbols = shift; + + # Get nm output sorted by increasing address + my $symbol_table = GetProcedureBoundaries($image, "."); + if (!%{$symbol_table}) { + return 0; + } + # Start addresses are already the right length (8 or 16 hex digits). + my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] } + keys(%{$symbol_table}); + + if ($#names < 0) { + # No symbols: just use addresses + foreach my $pc (@{$pclist}) { + my $pcstr = "0x" . $pc; + $symbols->{$pc} = [$pcstr, "?", $pcstr]; + } + return 0; + } + + # Sort addresses so we can do a join against nm output + my $index = 0; + my $fullname = $names[0]; + my $name = ShortFunctionName($fullname); + foreach my $pc (sort { $a cmp $b } @{$pclist}) { + # Adjust for mapped offset + my $mpc = AddressSub($pc, $offset); + while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){ + $index++; + $fullname = $names[$index]; + $name = ShortFunctionName($fullname); + } + if ($mpc lt $symbol_table->{$fullname}->[1]) { + $symbols->{$pc} = [$name, "?", $fullname]; + } else { + my $pcstr = "0x" . $pc; + $symbols->{$pc} = [$pcstr, "?", $pcstr]; + } + } + return 1; +} + +sub ShortFunctionName { + my $function = shift; + while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types + $function =~ s/<[0-9a-f]*>$//g; # Remove Address + if (!$main::opt_no_strip_temp) { + while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments + } + $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type + return $function; +} + +# Trim overly long symbols found in disassembler output +sub CleanDisassembly { + my $d = shift; + while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax) + while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments + return $d; +} + +# Clean file name for display +sub CleanFileName { + my ($f) = @_; + $f =~ s|^/proc/self/cwd/||; + $f =~ s|^\./||; + return $f; +} + +# Make address relative to section and clean up for display +sub UnparseAddress { + my ($offset, $address) = @_; + $address = AddressSub($address, $offset); + $address =~ s/^0x//; + $address =~ s/^0*//; + return $address; +} + +##### Miscellaneous ##### + +# Find the right versions of the above object tools to use. The +# argument is the program file being analyzed, and should be an ELF +# 32-bit or ELF 64-bit executable file. The location of the tools +# is determined by considering the following options in this order: +# 1) --tools option, if set +# 2) PPROF_TOOLS environment variable, if set +# 3) the environment +sub ConfigureObjTools { + my $prog_file = shift; + + # Check for the existence of $prog_file because /usr/bin/file does not + # predictably return error status in prod. + (-e $prog_file) || error("$prog_file does not exist.\n"); + + my $file_type = undef; + if (-e "/usr/bin/file") { + # Follow symlinks (at least for systems where "file" supports that). + my $escaped_prog_file = ShellEscape($prog_file); + $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null || + /usr/bin/file $escaped_prog_file`; + } elsif ($^O == "MSWin32") { + $file_type = "MS Windows"; + } else { + print STDERR "WARNING: Can't determine the file type of $prog_file"; + } + + if ($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; + } + + if ($file_type =~ /MS Windows/) { + # For windows, we provide a version of nm and addr2line as part of + # the opensource release, which is capable of parsing + # Windows-style PDB executables. It should live in the path, or + # in the same directory as pprof. + $obj_tool_map{"nm_pdb"} = "nm-pdb"; + $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb"; + } + + if ($file_type =~ /Mach-O/) { + # OS X uses otool to examine Mach-O files, rather than objdump. + $obj_tool_map{"otool"} = "otool"; + $obj_tool_map{"addr2line"} = "false"; # no addr2line + $obj_tool_map{"objdump"} = "false"; # no objdump + } + + # Go fill in %obj_tool_map with the pathnames to use: + foreach my $tool (keys %obj_tool_map) { + $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool}); + } +} + +# Returns the path of a caller-specified object tool. If --tools or +# PPROF_TOOLS are specified, then returns the full path to the tool +# with that prefix. Otherwise, returns the path unmodified (which +# means we will look for it on PATH). +sub ConfigureTool { + my $tool = shift; + my $path; + + # --tools (or $PPROF_TOOLS) is a comma separated list, where each + # item is either a) a pathname prefix, or b) a map of the form + # :. First we look for an entry of type (b) for our + # tool. If one is found, we use it. Otherwise, we consider all the + # pathname prefixes in turn, until one yields an existing file. If + # none does, we use a default path. + my $tools = $main::opt_tools || $ENV{"PPROF_TOOLS"} || ""; + if ($tools =~ m/(,|^)\Q$tool\E:([^,]*)/) { + $path = $2; + # TODO(csilvers): sanity-check that $path exists? Hard if it's relative. + } elsif ($tools ne '') { + foreach my $prefix (split(',', $tools)) { + next if ($prefix =~ /:/); # ignore "tool:fullpath" entries in the list + if (-x $prefix . $tool) { + $path = $prefix . $tool; + last; + } + } + if (!$path) { + error("No '$tool' found with prefix specified by " . + "--tools (or \$PPROF_TOOLS) '$tools'\n"); + } + } else { + # ... otherwise use the version that exists in the same directory as + # pprof. If there's nothing there, use $PATH. + $0 =~ m,[^/]*$,; # this is everything after the last slash + my $dirname = $`; # this is everything up to and including the last slash + if (-x "$dirname$tool") { + $path = "$dirname$tool"; + } else { + $path = $tool; + } + } + if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; } + return $path; +} + +sub ShellEscape { + my @escaped_words = (); + foreach my $word (@_) { + my $escaped_word = $word; + if ($word =~ m![^a-zA-Z0-9/.,_=-]!) { # check for anything not in whitelist + $escaped_word =~ s/'/'\\''/; + $escaped_word = "'$escaped_word'"; + } + push(@escaped_words, $escaped_word); + } + return join(" ", @escaped_words); +} + +sub cleanup { + unlink($main::tmpfile_sym); + unlink(keys %main::tempnames); + + # We leave any collected profiles in $HOME/pprof in case the user wants + # to look at them later. We print a message informing them of this. + if ((scalar(@main::profile_files) > 0) && + defined($main::collected_profile)) { + if (scalar(@main::profile_files) == 1) { + print STDERR "Dynamically gathered profile is in $main::collected_profile\n"; + } + print STDERR "If you want to investigate this profile further, you can do:\n"; + print STDERR "\n"; + print STDERR " $0 \\\n"; + print STDERR " $main::prog \\\n"; + print STDERR " $main::collected_profile\n"; + print STDERR "\n"; + } +} + +sub sighandler { + cleanup(); + exit(1); +} + +sub error { + my $msg = shift; + print STDERR $msg; + cleanup(); + exit(1); +} + + +# Run $nm_command and get all the resulting procedure boundaries whose +# names match "$regexp" and returns them in a hashtable mapping from +# procedure name to a two-element vector of [start address, end address] +sub GetProcedureBoundariesViaNm { + my $escaped_nm_command = shift; # shell-escaped + my $regexp = shift; + my $image = shift; + + my $symbol_table = {}; + open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n"); + my $last_start = "0"; + my $routine = ""; + while () { + s/\r//g; # turn windows-looking lines into unix-looking lines + if (m/^\s*([0-9a-f]+) (.) (..*)/) { + my $start_val = $1; + my $type = $2; + my $this_routine = $3; + + # It's possible for two symbols to share the same address, if + # one is a zero-length variable (like __start_google_malloc) or + # one symbol is a weak alias to another (like __libc_malloc). + # In such cases, we want to ignore all values except for the + # actual symbol, which in nm-speak has type "T". The logic + # below does this, though it's a bit tricky: what happens when + # we have a series of lines with the same address, is the first + # one gets queued up to be processed. However, it won't + # *actually* be processed until later, when we read a line with + # a different address. That means that as long as we're reading + # lines with the same address, we have a chance to replace that + # item in the queue, which we do whenever we see a 'T' entry -- + # that is, a line with type 'T'. If we never see a 'T' entry, + # we'll just go ahead and process the first entry (which never + # got touched in the queue), and ignore the others. + if ($start_val eq $last_start && $type =~ /t/i) { + # We are the 'T' symbol at this address, replace previous symbol. + $routine = $this_routine; + next; + } elsif ($start_val eq $last_start) { + # We're not the 'T' symbol at this address, so ignore us. + next; + } + + if ($this_routine eq $sep_symbol) { + $sep_address = HexExtend($start_val); + } + + # Tag this routine with the starting address in case the image + # has multiple occurrences of this routine. We use a syntax + # that resembles template paramters that are automatically + # stripped out by ShortFunctionName() + $this_routine .= "<$start_val>"; + + if (defined($routine) && $routine =~ m/$regexp/) { + $symbol_table->{$routine} = [HexExtend($last_start), + HexExtend($start_val)]; + } + $last_start = $start_val; + $routine = $this_routine; + } elsif (m/^Loaded image name: (.+)/) { + # The win32 nm workalike emits information about the binary it is using. + if ($main::opt_debug) { print STDERR "Using Image $1\n"; } + } elsif (m/^PDB file name: (.+)/) { + # The win32 nm workalike emits information about the pdb it is using. + if ($main::opt_debug) { print STDERR "Using PDB $1\n"; } + } + } + close(NM); + # Handle the last line in the nm output. Unfortunately, we don't know + # how big this last symbol is, because we don't know how big the file + # is. For now, we just give it a size of 0. + # TODO(csilvers): do better here. + if (defined($routine) && $routine =~ m/$regexp/) { + $symbol_table->{$routine} = [HexExtend($last_start), + HexExtend($last_start)]; + } + + # Verify if addr2line can find the $sep_symbol. If not, we use objdump + # to find the address for the $sep_symbol on code section which addr2line + # can find. + if (defined($sep_address)){ + my $start_val = $sep_address; + my $addr2line = $obj_tool_map{"addr2line"}; + my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image, "-i"); + open(FINI, "echo $start_val | $cmd |") + || error("echo $start_val | $cmd: $!\n"); + $_ = ; + s/\r?\n$//g; + my $fini = $_; + close(FINI); + if ($fini ne $sep_symbol){ + my $objdump = $obj_tool_map{"objdump"}; + $cmd = ShellEscape($objdump, "-d", $image); + my $grep = ShellEscape("grep", $sep_symbol); + my $tail = ShellEscape("tail", "-n", "1"); + open(FINI, "$cmd | $grep | $tail |") + || error("$cmd | $grep | $tail: $!\n"); + s/\r//g; # turn windows-looking lines into unix-looking lines + my $data = ; + if (defined($data)){ + ($start_val, $fini) = split(/ $dev_null 2>&1"; + if (system(ShellEscape($nm, "--demangle", $image) . $to_devnull) == 0) { + # In this mode, we do "nm --demangle " + $demangle_flag = "--demangle"; + $cppfilt_flag = ""; + } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) { + # In this mode, we do "nm | c++filt" + $cppfilt_flag = " | " . ShellEscape($cppfilt); + }; + my $flatten_flag = ""; + if (system(ShellEscape($nm, "-f", $image) . $to_devnull) == 0) { + $flatten_flag = "-f"; + } + + # Finally, in the case $imagie isn't a debug library, we try again with + # -D to at least get *exported* symbols. If we can't use --demangle, + # we use c++filt instead, if it exists on this system. + my @nm_commands = (ShellEscape($nm, "-n", $flatten_flag, $demangle_flag, + $image) . " 2>$dev_null $cppfilt_flag", + ShellEscape($nm, "-D", "-n", $flatten_flag, $demangle_flag, + $image) . " 2>$dev_null $cppfilt_flag", + # 6nm is for Go binaries + ShellEscape("6nm", "$image") . " 2>$dev_null | sort", + ); + + # If the executable is an MS Windows PDB-format executable, we'll + # have set up obj_tool_map("nm_pdb"). In this case, we actually + # want to use both unix nm and windows-specific nm_pdb, since + # PDB-format executables can apparently include dwarf .o files. + if (exists $obj_tool_map{"nm_pdb"}) { + push(@nm_commands, + ShellEscape($obj_tool_map{"nm_pdb"}, "--demangle", $image) + . " 2>$dev_null"); + } + + foreach my $nm_command (@nm_commands) { + my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp, $image); + return $symbol_table if (%{$symbol_table}); + } + my $symbol_table = {}; + return $symbol_table; +} + + +# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings. +# To make them more readable, we add underscores at interesting places. +# This routine removes the underscores, producing the canonical representation +# used by pprof to represent addresses, particularly in the tested routines. +sub CanonicalHex { + my $arg = shift; + return join '', (split '_',$arg); +} + + +# Unit test for AddressAdd: +sub AddressAddUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressAdd ($row->[0], $row->[1]); + if ($sum ne $row->[2]) { + printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, + $row->[0], $row->[1], $row->[2]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1])); + my $expected = join '', (split '_',$row->[2]); + if ($sum ne CanonicalHex($row->[2])) { + printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, + $row->[0], $row->[1], $row->[2]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Unit test for AddressSub: +sub AddressSubUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressSub ($row->[0], $row->[1]); + if ($sum ne $row->[3]) { + printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, + $row->[0], $row->[1], $row->[3]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1])); + if ($sum ne CanonicalHex($row->[3])) { + printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, + $row->[0], $row->[1], $row->[3]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Unit test for AddressInc: +sub AddressIncUnitTest { + my $test_data_8 = shift; + my $test_data_16 = shift; + my $error_count = 0; + my $fail_count = 0; + my $pass_count = 0; + # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n"; + + # First a few 8-nibble addresses. Note that this implementation uses + # plain old arithmetic, so a quick sanity check along with verifying what + # happens to overflow (we want it to wrap): + $address_length = 8; + foreach my $row (@{$test_data_8}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressInc ($row->[0]); + if ($sum ne $row->[4]) { + printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, + $row->[0], $row->[4]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count = $fail_count; + $fail_count = 0; + $pass_count = 0; + + # Now 16-nibble addresses. + $address_length = 16; + foreach my $row (@{$test_data_16}) { + if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } + my $sum = AddressInc (CanonicalHex($row->[0])); + if ($sum ne CanonicalHex($row->[4])) { + printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, + $row->[0], $row->[4]; + ++$fail_count; + } else { + ++$pass_count; + } + } + printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n", + $pass_count, $fail_count; + $error_count += $fail_count; + + return $error_count; +} + + +# Driver for unit tests. +# Currently just the address add/subtract/increment routines for 64-bit. +sub RunUnitTests { + my $error_count = 0; + + # This is a list of tuples [a, b, a+b, a-b, a+1] + my $unit_test_data_8 = [ + [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)], + [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)], + [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)], + [qw(00000001 ffffffff 00000000 00000002 00000002)], + [qw(00000001 fffffff0 fffffff1 00000011 00000002)], + ]; + my $unit_test_data_16 = [ + # The implementation handles data in 7-nibble chunks, so those are the + # interesting boundaries. + [qw(aaaaaaaa 50505050 + 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)], + [qw(50505050 aaaaaaaa + 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)], + [qw(ffffffff aaaaaaaa + 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)], + [qw(00000001 ffffffff + 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)], + [qw(00000001 fffffff0 + 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)], + + [qw(00_a00000a_aaaaaaa 50505050 + 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)], + [qw(0f_fff0005_0505050 aaaaaaaa + 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)], + [qw(00_000000f_fffffff 01_800000a_aaaaaaa + 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)], + [qw(00_0000000_0000001 ff_fffffff_fffffff + 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)], + [qw(00_0000000_0000001 ff_fffffff_ffffff0 + ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)], + ]; + + $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16); + $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16); + $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16); + if ($error_count > 0) { + print STDERR $error_count, " errors: FAILED\n"; + } else { + print STDERR "PASS\n"; + } + exit ($error_count); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/profile-handler.cc b/trunk/3rdparty/gperftools-2-fit/src/profile-handler.cc new file mode 100644 index 000000000..0db17bbea --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/profile-handler.cc @@ -0,0 +1,599 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2009, 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: Sanjay Ghemawat +// Nabeel Mian +// +// Implements management of profile timers and the corresponding signal handler. + +#include "config.h" +#include "profile-handler.h" + +#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) + +#include +#include +#include + +#include +#include + +#if HAVE_LINUX_SIGEV_THREAD_ID +// for timer_{create,settime} and associated typedefs & constants +#include +// for sigevent +#include +// for SYS_gettid +#include + +// for perftools_pthread_key_create +#include "maybe_threads.h" +#endif + +#include "base/dynamic_annotations.h" +#include "base/googleinit.h" +#include "base/logging.h" +#include "base/spinlock.h" +#include "maybe_threads.h" + +// Some Linux systems don't have sigev_notify_thread_id defined in +// signal.h (despite having SIGEV_THREAD_ID defined) and also lack +// working linux/signal.h. So lets workaround. Note, we know that at +// least on Linux sigev_notify_thread_id is macro. +// +// See https://sourceware.org/bugzilla/show_bug.cgi?id=27417 and +// https://bugzilla.kernel.org/show_bug.cgi?id=200081 +// +#if __linux__ && HAVE_LINUX_SIGEV_THREAD_ID && !defined(sigev_notify_thread_id) +#define sigev_notify_thread_id _sigev_un._tid +#endif + +using std::list; +using std::string; + +// This structure is used by ProfileHandlerRegisterCallback and +// ProfileHandlerUnregisterCallback as a handle to a registered callback. +struct ProfileHandlerToken { + // Sets the callback and associated arg. + ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg) + : callback(cb), + callback_arg(cb_arg) { + } + + // Callback function to be invoked on receiving a profile timer interrupt. + ProfileHandlerCallback callback; + // Argument for the callback function. + void* callback_arg; +}; + +// Blocks a signal from being delivered to the current thread while the object +// is alive. Unblocks it upon destruction. +class ScopedSignalBlocker { + public: + ScopedSignalBlocker(int signo) { + sigemptyset(&sig_set_); + sigaddset(&sig_set_, signo); + RAW_CHECK(sigprocmask(SIG_BLOCK, &sig_set_, NULL) == 0, + "sigprocmask (block)"); + } + ~ScopedSignalBlocker() { + RAW_CHECK(sigprocmask(SIG_UNBLOCK, &sig_set_, NULL) == 0, + "sigprocmask (unblock)"); + } + + private: + sigset_t sig_set_; +}; + +// This class manages profile timers and associated signal handler. This is a +// a singleton. +class ProfileHandler { + public: + // Registers the current thread with the profile handler. + void RegisterThread(); + + // Registers a callback routine to receive profile timer ticks. The returned + // token is to be used when unregistering this callback and must not be + // deleted by the caller. + ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback, + void* callback_arg); + + // Unregisters a previously registered callback. Expects the token returned + // by the corresponding RegisterCallback routine. + void UnregisterCallback(ProfileHandlerToken* token) + NO_THREAD_SAFETY_ANALYSIS; + + // Unregisters all the callbacks and stops the timer(s). + void Reset(); + + // Gets the current state of profile handler. + void GetState(ProfileHandlerState* state); + + // Initializes and returns the ProfileHandler singleton. + static ProfileHandler* Instance(); + + private: + ProfileHandler(); + ~ProfileHandler(); + + // Largest allowed frequency. + static const int32 kMaxFrequency = 4000; + // Default frequency. + static const int32 kDefaultFrequency = 100; + + // ProfileHandler singleton. + static ProfileHandler* instance_; + + // pthread_once_t for one time initialization of ProfileHandler singleton. + static pthread_once_t once_; + + // Initializes the ProfileHandler singleton via GoogleOnceInit. + static void Init(); + + // Timer state as configured previously. + bool timer_running_; + + // The number of profiling signal interrupts received. + int64 interrupts_ GUARDED_BY(signal_lock_); + + // Profiling signal interrupt frequency, read-only after construction. + int32 frequency_; + + // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM). + // Translated into an equivalent choice of clock if per_thread_timer_enabled_ + // is true. + int timer_type_; + + // Signal number for timer signal. + int signal_number_; + + // Counts the number of callbacks registered. + int32 callback_count_ GUARDED_BY(control_lock_); + + // Is profiling allowed at all? + bool allowed_; + + // Must be false if HAVE_LINUX_SIGEV_THREAD_ID is not defined. + bool per_thread_timer_enabled_; + +#ifdef HAVE_LINUX_SIGEV_THREAD_ID + // this is used to destroy per-thread profiling timers on thread + // termination + pthread_key_t thread_timer_key; +#endif + + // This lock serializes the registration of threads and protects the + // callbacks_ list below. + // Locking order: + // In the context of a signal handler, acquire signal_lock_ to walk the + // callback list. Otherwise, acquire control_lock_, disable the signal + // handler and then acquire signal_lock_. + SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_); + SpinLock signal_lock_; + + // Holds the list of registered callbacks. We expect the list to be pretty + // small. Currently, the cpu profiler (base/profiler) and thread module + // (base/thread.h) are the only two components registering callbacks. + // Following are the locking requirements for callbacks_: + // For read-write access outside the SIGPROF handler: + // - Acquire control_lock_ + // - Disable SIGPROF handler. + // - Acquire signal_lock_ + // For read-only access in the context of SIGPROF handler + // (Read-write access is *not allowed* in the SIGPROF handler) + // - Acquire signal_lock_ + // For read-only access outside SIGPROF handler: + // - Acquire control_lock_ + typedef list CallbackList; + typedef CallbackList::iterator CallbackIterator; + CallbackList callbacks_ GUARDED_BY(signal_lock_); + + // Starts or stops the interval timer. + // Will ignore any requests to enable or disable when + // per_thread_timer_enabled_ is true. + void UpdateTimer(bool enable) EXCLUSIVE_LOCKS_REQUIRED(signal_lock_); + + // Returns true if the handler is not being used by something else. + // This checks the kernel's signal handler table. + bool IsSignalHandlerAvailable(); + + // Signal handler. Iterates over and calls all the registered callbacks. + static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext); + + DISALLOW_COPY_AND_ASSIGN(ProfileHandler); +}; + +ProfileHandler* ProfileHandler::instance_ = NULL; +pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT; + +const int32 ProfileHandler::kMaxFrequency; +const int32 ProfileHandler::kDefaultFrequency; + +// If we are LD_PRELOAD-ed against a non-pthreads app, then these functions +// won't be defined. We declare them here, for that case (with weak linkage) +// which will cause the non-definition to resolve to NULL. We can then check +// for NULL or not in Instance. +extern "C" { +int pthread_once(pthread_once_t *, void (*)(void)) ATTRIBUTE_WEAK; +int pthread_kill(pthread_t thread_id, int signo) ATTRIBUTE_WEAK; + +#if HAVE_LINUX_SIGEV_THREAD_ID +int timer_create(clockid_t clockid, struct sigevent* evp, + timer_t* timerid) ATTRIBUTE_WEAK; +int timer_delete(timer_t timerid) ATTRIBUTE_WEAK; +int timer_settime(timer_t timerid, int flags, const struct itimerspec* value, + struct itimerspec* ovalue) ATTRIBUTE_WEAK; +#endif +} + +#if HAVE_LINUX_SIGEV_THREAD_ID + +struct timer_id_holder { + timer_t timerid; + timer_id_holder(timer_t _timerid) : timerid(_timerid) {} +}; + +extern "C" { + static void ThreadTimerDestructor(void *arg) { + if (!arg) { + return; + } + timer_id_holder *holder = static_cast(arg); + timer_delete(holder->timerid); + delete holder; + } +} + +static void CreateThreadTimerKey(pthread_key_t *pkey) { + int rv = perftools_pthread_key_create(pkey, ThreadTimerDestructor); + if (rv) { + RAW_LOG(FATAL, "aborting due to pthread_key_create error: %s", strerror(rv)); + } +} + +static void StartLinuxThreadTimer(int timer_type, int signal_number, + int32 frequency, pthread_key_t timer_key) { + int rv; + struct sigevent sevp; + timer_t timerid; + struct itimerspec its; + memset(&sevp, 0, sizeof(sevp)); + sevp.sigev_notify = SIGEV_THREAD_ID; + sevp.sigev_notify_thread_id = syscall(SYS_gettid); + sevp.sigev_signo = signal_number; + clockid_t clock = CLOCK_THREAD_CPUTIME_ID; + if (timer_type == ITIMER_REAL) { + clock = CLOCK_MONOTONIC; + } + rv = timer_create(clock, &sevp, &timerid); + if (rv) { + RAW_LOG(FATAL, "aborting due to timer_create error: %s", strerror(errno)); + } + + timer_id_holder *holder = new timer_id_holder(timerid); + rv = perftools_pthread_setspecific(timer_key, holder); + if (rv) { + RAW_LOG(FATAL, "aborting due to pthread_setspecific error: %s", strerror(rv)); + } + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 1000000000 / frequency; + its.it_value = its.it_interval; + rv = timer_settime(timerid, 0, &its, 0); + if (rv) { + RAW_LOG(FATAL, "aborting due to timer_settime error: %s", strerror(errno)); + } +} +#endif + +void ProfileHandler::Init() { + instance_ = new ProfileHandler(); +} + +ProfileHandler* ProfileHandler::Instance() { + if (pthread_once) { + pthread_once(&once_, Init); + } + if (instance_ == NULL) { + // This will be true on systems that don't link in pthreads, + // including on FreeBSD where pthread_once has a non-zero address + // (but doesn't do anything) even when pthreads isn't linked in. + Init(); + assert(instance_ != NULL); + } + return instance_; +} + +ProfileHandler::ProfileHandler() + : timer_running_(false), + interrupts_(0), + callback_count_(0), + allowed_(true), + per_thread_timer_enabled_(false) { + SpinLockHolder cl(&control_lock_); + + timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); + signal_number_ = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); + + // Get frequency of interrupts (if specified) + char junk; + const char* fr = getenv("CPUPROFILE_FREQUENCY"); + if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) && + (frequency_ > 0)) { + // Limit to kMaxFrequency + frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_; + } else { + frequency_ = kDefaultFrequency; + } + + if (!allowed_) { + return; + } + +#if HAVE_LINUX_SIGEV_THREAD_ID + // Do this early because we might be overriding signal number. + + const char *per_thread = getenv("CPUPROFILE_PER_THREAD_TIMERS"); + const char *signal_number = getenv("CPUPROFILE_TIMER_SIGNAL"); + + if (per_thread || signal_number) { + if (timer_create && pthread_once) { + CreateThreadTimerKey(&thread_timer_key); + per_thread_timer_enabled_ = true; + // Override signal number if requested. + if (signal_number) { + signal_number_ = strtol(signal_number, NULL, 0); + } + } else { + RAW_LOG(INFO, + "Ignoring CPUPROFILE_PER_THREAD_TIMERS and\n" + " CPUPROFILE_TIMER_SIGNAL due to lack of timer_create().\n" + " Preload or link to librt.so for this to work"); + } + } +#endif + + // If something else is using the signal handler, + // assume it has priority over us and stop. + if (!IsSignalHandlerAvailable()) { + RAW_LOG(INFO, "Disabling profiler because signal %d handler is already in use.", + signal_number_); + allowed_ = false; + return; + } + + // Install the signal handler. + struct sigaction sa; + sa.sa_sigaction = SignalHandler; + sa.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&sa.sa_mask); + RAW_CHECK(sigaction(signal_number_, &sa, NULL) == 0, "sigprof (enable)"); +} + +ProfileHandler::~ProfileHandler() { + Reset(); +#ifdef HAVE_LINUX_SIGEV_THREAD_ID + if (per_thread_timer_enabled_) { + perftools_pthread_key_delete(thread_timer_key); + } +#endif +} + +void ProfileHandler::RegisterThread() { + SpinLockHolder cl(&control_lock_); + + if (!allowed_) { + return; + } + + // Record the thread identifier and start the timer if profiling is on. + ScopedSignalBlocker block(signal_number_); + SpinLockHolder sl(&signal_lock_); +#if HAVE_LINUX_SIGEV_THREAD_ID + if (per_thread_timer_enabled_) { + StartLinuxThreadTimer(timer_type_, signal_number_, frequency_, + thread_timer_key); + return; + } +#endif + UpdateTimer(callback_count_ > 0); +} + +ProfileHandlerToken* ProfileHandler::RegisterCallback( + ProfileHandlerCallback callback, void* callback_arg) { + + ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg); + + SpinLockHolder cl(&control_lock_); + { + ScopedSignalBlocker block(signal_number_); + SpinLockHolder sl(&signal_lock_); + callbacks_.push_back(token); + ++callback_count_; + UpdateTimer(true); + } + return token; +} + +void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) { + SpinLockHolder cl(&control_lock_); + for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end(); + ++it) { + if ((*it) == token) { + RAW_CHECK(callback_count_ > 0, "Invalid callback count"); + { + ScopedSignalBlocker block(signal_number_); + SpinLockHolder sl(&signal_lock_); + delete *it; + callbacks_.erase(it); + --callback_count_; + if (callback_count_ == 0) + UpdateTimer(false); + } + return; + } + } + // Unknown token. + RAW_LOG(FATAL, "Invalid token"); +} + +void ProfileHandler::Reset() { + SpinLockHolder cl(&control_lock_); + { + ScopedSignalBlocker block(signal_number_); + SpinLockHolder sl(&signal_lock_); + CallbackIterator it = callbacks_.begin(); + while (it != callbacks_.end()) { + CallbackIterator tmp = it; + ++it; + delete *tmp; + callbacks_.erase(tmp); + } + callback_count_ = 0; + UpdateTimer(false); + } +} + +void ProfileHandler::GetState(ProfileHandlerState* state) { + SpinLockHolder cl(&control_lock_); + { + ScopedSignalBlocker block(signal_number_); + SpinLockHolder sl(&signal_lock_); // Protects interrupts_. + state->interrupts = interrupts_; + } + state->frequency = frequency_; + state->callback_count = callback_count_; + state->allowed = allowed_; +} + +void ProfileHandler::UpdateTimer(bool enable) { + if (per_thread_timer_enabled_) { + // Ignore any attempts to disable it because that's not supported, and it's + // always enabled so enabling is always a NOP. + return; + } + + if (enable == timer_running_) { + return; + } + timer_running_ = enable; + + struct itimerval timer; + static const int kMillion = 1000000; + int interval_usec = enable ? kMillion / frequency_ : 0; + timer.it_interval.tv_sec = interval_usec / kMillion; + timer.it_interval.tv_usec = interval_usec % kMillion; + timer.it_value = timer.it_interval; + setitimer(timer_type_, &timer, 0); +} + +bool ProfileHandler::IsSignalHandlerAvailable() { + struct sigaction sa; + RAW_CHECK(sigaction(signal_number_, NULL, &sa) == 0, "is-signal-handler avail"); + + // We only take over the handler if the current one is unset. + // It must be SIG_IGN or SIG_DFL, not some other function. + // SIG_IGN must be allowed because when profiling is allowed but + // not actively in use, this code keeps the handler set to SIG_IGN. + // That setting will be inherited across fork+exec. In order for + // any child to be able to use profiling, SIG_IGN must be treated + // as available. + return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL; +} + +void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) { + int saved_errno = errno; + // At this moment, instance_ must be initialized because the handler is + // enabled in RegisterThread or RegisterCallback only after + // ProfileHandler::Instance runs. + ProfileHandler* instance = instance_; + RAW_CHECK(instance != NULL, "ProfileHandler is not initialized"); + { + SpinLockHolder sl(&instance->signal_lock_); + ++instance->interrupts_; + for (CallbackIterator it = instance->callbacks_.begin(); + it != instance->callbacks_.end(); + ++it) { + (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg); + } + } + errno = saved_errno; +} + +// This module initializer registers the main thread, so it must be +// executed in the context of the main thread. +REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread()); + +void ProfileHandlerRegisterThread() { + ProfileHandler::Instance()->RegisterThread(); +} + +ProfileHandlerToken* ProfileHandlerRegisterCallback( + ProfileHandlerCallback callback, void* callback_arg) { + return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg); +} + +void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { + ProfileHandler::Instance()->UnregisterCallback(token); +} + +void ProfileHandlerReset() { + return ProfileHandler::Instance()->Reset(); +} + +void ProfileHandlerGetState(ProfileHandlerState* state) { + ProfileHandler::Instance()->GetState(state); +} + +#else // OS_CYGWIN + +// ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't +// work as well for profiling, and also interferes with alarm(). Because of +// these issues, unless a specific need is identified, profiler support is +// disabled under Cygwin. +void ProfileHandlerRegisterThread() { +} + +ProfileHandlerToken* ProfileHandlerRegisterCallback( + ProfileHandlerCallback callback, void* callback_arg) { + return NULL; +} + +void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { +} + +void ProfileHandlerReset() { +} + +void ProfileHandlerGetState(ProfileHandlerState* state) { +} + +#endif // OS_CYGWIN diff --git a/trunk/3rdparty/gperftools-2-fit/src/profile-handler.h b/trunk/3rdparty/gperftools-2-fit/src/profile-handler.h new file mode 100644 index 000000000..b6bb0a14e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/profile-handler.h @@ -0,0 +1,142 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2009, 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: Nabeel Mian + * + * This module manages the cpu profile timers and the associated interrupt + * handler. When enabled, all threads in the program are profiled. + * + * Any component interested in receiving a profile timer interrupt can do so by + * registering a callback. All registered callbacks must be async-signal-safe. + * + * Note: This module requires the sole ownership of the configured timer and + * signal. The timer defaults to ITIMER_PROF, can be changed to ITIMER_REAL by + * the environment variable CPUPROFILE_REALTIME, or is changed to a POSIX timer + * with CPUPROFILE_PER_THREAD_TIMERS. The signal defaults to SIGPROF/SIGALRM to + * match the choice of timer and can be set to an arbitrary value using + * CPUPROFILE_TIMER_SIGNAL with CPUPROFILE_PER_THREAD_TIMERS. + */ + +#ifndef BASE_PROFILE_HANDLER_H_ +#define BASE_PROFILE_HANDLER_H_ + +#include "config.h" +#include +#ifdef COMPILER_MSVC +#include "conflict-signal.h" +#endif +#include "base/basictypes.h" + +/* Forward declaration. */ +struct ProfileHandlerToken; + +/* + * Callback function to be used with ProfilefHandlerRegisterCallback. This + * function will be called in the context of SIGPROF signal handler and must + * be async-signal-safe. The first three arguments are the values provided by + * the SIGPROF signal handler. We use void* to avoid using ucontext_t on + * non-POSIX systems. + * + * Requirements: + * - Callback must be async-signal-safe. + * - None of the functions in ProfileHandler are async-signal-safe. Therefore, + * callback function *must* not call any of the ProfileHandler functions. + * - Callback is not required to be re-entrant. At most one instance of + * callback can run at a time. + * + * Notes: + * - The SIGPROF signal handler saves and restores errno, so the callback + * doesn't need to. + * - Callback code *must* not acquire lock(s) to serialize access to data shared + * with the code outside the signal handler (callback must be + * async-signal-safe). If such a serialization is needed, follow the model + * used by profiler.cc: + * + * When code other than the signal handler modifies the shared data it must: + * - Acquire lock. + * - Unregister the callback with the ProfileHandler. + * - Modify shared data. + * - Re-register the callback. + * - Release lock. + * and the callback code gets a lockless, read-write access to the data. + */ +typedef void (*ProfileHandlerCallback)(int sig, siginfo_t* sig_info, + void* ucontext, void* callback_arg); + +/* + * Registers a new thread with profile handler and should be called only once + * per thread. The main thread is registered at program startup. This routine + * is called by the Thread module in google3/thread whenever a new thread is + * created. This function is not async-signal-safe. + */ +void ProfileHandlerRegisterThread(); + +/* + * Registers a callback routine. This callback function will be called in the + * context of SIGPROF handler, so must be async-signal-safe. The returned token + * is to be used when unregistering this callback via + * ProfileHandlerUnregisterCallback. Registering the first callback enables + * the SIGPROF signal handler. Caller must not free the returned token. This + * function is not async-signal-safe. + */ +ProfileHandlerToken* ProfileHandlerRegisterCallback( + ProfileHandlerCallback callback, void* callback_arg); + +/* + * Unregisters a previously registered callback. Expects the token returned + * by the corresponding ProfileHandlerRegisterCallback and asserts that the + * passed token is valid. Unregistering the last callback disables the SIGPROF + * signal handler. It waits for the currently running callback to + * complete before returning. This function is not async-signal-safe. + */ +void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token); + +/* + * FOR TESTING ONLY + * Unregisters all the callbacks, stops the timers (if shared) and disables the + * SIGPROF handler. All the threads, including the main thread, need to be + * re-registered after this call. This function is not async-signal-safe. + */ +void ProfileHandlerReset(); + +/* + * Stores profile handler's current state. This function is not + * async-signal-safe. + */ +struct ProfileHandlerState { + int32 frequency; /* Profiling frequency */ + int32 callback_count; /* Number of callbacks registered */ + int64 interrupts; /* Number of interrupts received */ + bool allowed; /* Profiling is allowed */ +}; +void ProfileHandlerGetState(struct ProfileHandlerState* state); + +#endif /* BASE_PROFILE_HANDLER_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/profiledata.cc b/trunk/3rdparty/gperftools-2-fit/src/profiledata.cc new file mode 100644 index 000000000..7bfb727a2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/profiledata.cc @@ -0,0 +1,332 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// Chris Demetriou (refactoring) +// +// Collect profiling data. + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include "profiledata.h" + +#include "base/logging.h" +#include "base/sysinfo.h" + +// All of these are initialized in profiledata.h. +const int ProfileData::kMaxStackDepth; +const int ProfileData::kAssociativity; +const int ProfileData::kBuckets; +const int ProfileData::kBufferLength; + +ProfileData::Options::Options() + : frequency_(1) { +} + +// This function is safe to call from asynchronous signals (but is not +// re-entrant). However, that's not part of its public interface. +void ProfileData::Evict(const Entry& entry) { + const int d = entry.depth; + const int nslots = d + 2; // Number of slots needed in eviction buffer + if (num_evicted_ + nslots > kBufferLength) { + FlushEvicted(); + assert(num_evicted_ == 0); + assert(nslots <= kBufferLength); + } + evict_[num_evicted_++] = entry.count; + evict_[num_evicted_++] = d; + memcpy(&evict_[num_evicted_], entry.stack, d * sizeof(Slot)); + num_evicted_ += d; +} + +ProfileData::ProfileData() + : hash_(0), + evict_(0), + num_evicted_(0), + out_(-1), + count_(0), + evictions_(0), + total_bytes_(0), + fname_(0), + start_time_(0) { +} + +bool ProfileData::Start(const char* fname, + const ProfileData::Options& options) { + if (enabled()) { + return false; + } + + // Open output file and initialize various data structures + int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666); + if (fd < 0) { + // Can't open outfile for write + return false; + } + + start_time_ = time(NULL); + fname_ = strdup(fname); + + // Reset counters + num_evicted_ = 0; + count_ = 0; + evictions_ = 0; + total_bytes_ = 0; + + hash_ = new Bucket[kBuckets]; + evict_ = new Slot[kBufferLength]; + memset(hash_, 0, sizeof(hash_[0]) * kBuckets); + + // Record special entries + evict_[num_evicted_++] = 0; // count for header + evict_[num_evicted_++] = 3; // depth for header + evict_[num_evicted_++] = 0; // Version number + CHECK_NE(0, options.frequency()); + int period = 1000000 / options.frequency(); + evict_[num_evicted_++] = period; // Period (microseconds) + evict_[num_evicted_++] = 0; // Padding + + out_ = fd; + + return true; +} + +ProfileData::~ProfileData() { + 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); + } +} + +void ProfileData::Stop() { + if (!enabled()) { + return; + } + + // Move data from hash table to eviction buffer + for (int b = 0; b < kBuckets; b++) { + Bucket* bucket = &hash_[b]; + for (int a = 0; a < kAssociativity; a++) { + if (bucket->entry[a].count > 0) { + Evict(bucket->entry[a]); + } + } + } + + if (num_evicted_ + 3 > kBufferLength) { + // Ensure there is enough room for end of data marker + FlushEvicted(); + } + + // Write end of data marker + evict_[num_evicted_++] = 0; // count + evict_[num_evicted_++] = 1; // depth + evict_[num_evicted_++] = 0; // end of data marker + FlushEvicted(); + + // Dump "/proc/self/maps" so we get list of mapped shared libraries + DumpProcSelfMaps(out_); + + Reset(); + fprintf(stderr, "PROFILE: interrupts/evictions/bytes = %d/%d/%zu\n", + count_, evictions_, total_bytes_); +} + +void ProfileData::Reset() { + if (!enabled()) { + return; + } + + // Don't reset count_, evictions_, or total_bytes_ here. They're used + // by Stop to print information about the profile after reset, and are + // cleared by Start when starting a new profile. + close(out_); + delete[] hash_; + hash_ = 0; + delete[] evict_; + evict_ = 0; + num_evicted_ = 0; + free(fname_); + fname_ = 0; + start_time_ = 0; + + out_ = -1; +} + +// This function is safe to call from asynchronous signals (but is not +// re-entrant). However, that's not part of its public interface. +void ProfileData::GetCurrentState(State* state) const { + if (enabled()) { + state->enabled = true; + state->start_time = start_time_; + state->samples_gathered = count_; + int buf_size = sizeof(state->profile_name); + strncpy(state->profile_name, fname_, buf_size); + state->profile_name[buf_size-1] = '\0'; + } else { + state->enabled = false; + state->start_time = 0; + state->samples_gathered = 0; + state->profile_name[0] = '\0'; + } +} + +// This function is safe to call from asynchronous signals (but is not +// re-entrant). However, that's not part of its public interface. +void ProfileData::FlushTable() { + if (!enabled()) { + return; + } + + // Move data from hash table to eviction buffer + for (int b = 0; b < kBuckets; b++) { + Bucket* bucket = &hash_[b]; + for (int a = 0; a < kAssociativity; a++) { + if (bucket->entry[a].count > 0) { + Evict(bucket->entry[a]); + bucket->entry[a].depth = 0; + bucket->entry[a].count = 0; + } + } + } + + // Write out all pending data + FlushEvicted(); +} + +void ProfileData::Add(int depth, const void* const* stack) { + if (!enabled()) { + return; + } + + if (depth > kMaxStackDepth) depth = kMaxStackDepth; + RAW_CHECK(depth > 0, "ProfileData::Add depth <= 0"); + + // Make hash-value + Slot h = 0; + for (int i = 0; i < depth; i++) { + Slot slot = reinterpret_cast(stack[i]); + h = (h << 8) | (h >> (8*(sizeof(h)-1))); + h += (slot * 31) + (slot * 7) + (slot * 3); + } + + count_++; + + // See if table already has an entry for this trace + bool done = false; + Bucket* bucket = &hash_[h % kBuckets]; + for (int a = 0; a < kAssociativity; a++) { + Entry* e = &bucket->entry[a]; + if (e->depth == depth) { + bool match = true; + for (int i = 0; i < depth; i++) { + if (e->stack[i] != reinterpret_cast(stack[i])) { + match = false; + break; + } + } + if (match) { + e->count++; + done = true; + break; + } + } + } + + if (!done) { + // Evict entry with smallest count + Entry* e = &bucket->entry[0]; + for (int a = 1; a < kAssociativity; a++) { + if (bucket->entry[a].count < e->count) { + e = &bucket->entry[a]; + } + } + if (e->count > 0) { + evictions_++; + Evict(*e); + } + + // Use the newly evicted entry + e->depth = depth; + e->count = 1; + for (int i = 0; i < depth; i++) { + e->stack[i] = reinterpret_cast(stack[i]); + } + } +} + +// This function is safe to call from asynchronous signals (but is not +// re-entrant). However, that's not part of its public interface. +void ProfileData::FlushEvicted() { + if (num_evicted_ > 0) { + const char* buf = reinterpret_cast(evict_); + size_t bytes = sizeof(evict_[0]) * num_evicted_; + total_bytes_ += bytes; + FDWrite(out_, buf, bytes); + } + num_evicted_ = 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/profiledata.h b/trunk/3rdparty/gperftools-2-fit/src/profiledata.h new file mode 100644 index 000000000..a4f0446d9 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/profiledata.h @@ -0,0 +1,184 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// Chris Demetriou (refactoring) +// +// Collect profiling data. +// +// The profile data file format is documented in +// docs/cpuprofile-fileformat.html + + +#ifndef BASE_PROFILEDATA_H_ +#define BASE_PROFILEDATA_H_ + +#include +#include // for time_t +#include +#include "base/basictypes.h" + +// A class that accumulates profile samples and writes them to a file. +// +// Each sample contains a stack trace and a count. Memory usage is +// reduced by combining profile samples that have the same stack trace +// by adding up the associated counts. +// +// Profile data is accumulated in a bounded amount of memory, and will +// flushed to a file as necessary to stay within the memory limit. +// +// Use of this class assumes external synchronization. The exact +// requirements of that synchronization are that: +// +// - 'Add' may be called from asynchronous signals, but is not +// re-entrant. +// +// - None of 'Start', 'Stop', 'Reset', 'Flush', and 'Add' may be +// called at the same time. +// +// - 'Start', 'Stop', or 'Reset' should not be called while 'Enabled' +// or 'GetCurrent' are running, and vice versa. +// +// A profiler which uses asyncronous signals to add samples will +// typically use two locks to protect this data structure: +// +// - A SpinLock which is held over all calls except for the 'Add' +// call made from the signal handler. +// +// - A SpinLock which is held over calls to 'Start', 'Stop', 'Reset', +// 'Flush', and 'Add'. (This SpinLock should be acquired after +// the first SpinLock in all cases where both are needed.) +class ProfileData { + public: + struct State { + bool enabled; // Is profiling currently enabled? + time_t start_time; // If enabled, when was profiling started? + char profile_name[1024]; // Name of file being written, or '\0' + int samples_gathered; // Number of samples gathered to far (or 0) + }; + + class Options { + public: + Options(); + + // Get and set the sample frequency. + int frequency() const { + return frequency_; + } + void set_frequency(int frequency) { + frequency_ = frequency; + } + + private: + int frequency_; // Sample frequency. + }; + + static const int kMaxStackDepth = 254; // Max stack depth stored in profile + + ProfileData(); + ~ProfileData(); + + // If data collection is not already enabled start to collect data + // into fname. Parameters related to this profiling run are specified + // by 'options'. + // + // Returns true if data collection could be started, otherwise (if an + // error occurred or if data collection was already enabled) returns + // false. + bool Start(const char *fname, const Options& options); + + // If data collection is enabled, stop data collection and write the + // data to disk. + void Stop(); + + // Stop data collection without writing anything else to disk, and + // discard any collected data. + void Reset(); + + // If data collection is enabled, record a sample with 'depth' + // entries from 'stack'. (depth must be > 0.) At most + // kMaxStackDepth stack entries will be recorded, starting with + // stack[0]. + // + // This function is safe to call from asynchronous signals (but is + // not re-entrant). + void Add(int depth, const void* const* stack); + + // If data collection is enabled, write the data to disk (and leave + // the collector enabled). + void FlushTable(); + + // Is data collection currently enabled? + bool enabled() const { return out_ >= 0; } + + // Get the current state of the data collector. + void GetCurrentState(State* state) const; + + private: + static const int kAssociativity = 4; // For hashtable + static const int kBuckets = 1 << 10; // For hashtable + static const int kBufferLength = 1 << 18; // For eviction buffer + + // Type of slots: each slot can be either a count, or a PC value + typedef uintptr_t Slot; + + // Hash-table/eviction-buffer entry (a.k.a. a sample) + struct Entry { + Slot count; // Number of hits + Slot depth; // Stack depth + Slot stack[kMaxStackDepth]; // Stack contents + }; + + // Hash table bucket + struct Bucket { + Entry entry[kAssociativity]; + }; + + Bucket* hash_; // hash table + Slot* evict_; // evicted entries + int num_evicted_; // how many evicted entries? + int out_; // fd for output file. + int count_; // How many samples recorded + int evictions_; // How many evictions + size_t total_bytes_; // How much output + char* fname_; // Profile file name + time_t start_time_; // Start time, or 0 + + // Move 'entry' to the eviction buffer. + void Evict(const Entry& entry); + + // Write contents of eviction buffer to disk. + void FlushEvicted(); + + DISALLOW_COPY_AND_ASSIGN(ProfileData); +}; + +#endif // BASE_PROFILEDATA_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/profiler.cc b/trunk/3rdparty/gperftools-2-fit/src/profiler.cc new file mode 100644 index 000000000..227deb2a0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/profiler.cc @@ -0,0 +1,434 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// Chris Demetriou (refactoring) +// +// Profile current program by sampling stack-trace every so often + +#include "config.h" +#include "getpc.h" // should be first to get the _GNU_SOURCE dfn +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include // for getpid() +#endif +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include +#elif defined(HAVE_CYGWIN_SIGNAL_H) +#include +typedef ucontext ucontext_t; +#else +typedef int ucontext_t; // just to quiet the compiler, mostly +#endif +#include +#include +#include +#include +#include "base/commandlineflags.h" +#include "base/logging.h" +#include "base/googleinit.h" +#include "base/spinlock.h" +#include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */ +#include "profiledata.h" +#include "profile-handler.h" + +using std::string; + +DEFINE_bool(cpu_profiler_unittest, + EnvToBool("PERFTOOLS_UNITTEST", true), + "Determines whether or not we are running under the \ + control of a unit test. This allows us to include or \ + exclude certain behaviours."); + +// Collects up all profile data. This is a singleton, which is +// initialized by a constructor at startup. If no cpu profiler +// signal is specified then the profiler lifecycle is either +// manaully controlled via the API or attached to the scope of +// the singleton (program scope). Otherwise the cpu toggle is +// used to allow for user selectable control via signal generation. +// This is very useful for profiling a daemon process without +// having to start and stop the daemon or having to modify the +// source code to use the cpu profiler API. +class CpuProfiler { + public: + CpuProfiler(); + ~CpuProfiler(); + + // Start profiler to write profile info into fname + bool Start(const char* fname, const ProfilerOptions* options); + + // Stop profiling and write the data to disk. + void Stop(); + + // Write the data to disk (and continue profiling). + void FlushTable(); + + bool Enabled(); + + void GetCurrentState(ProfilerState* state); + + static CpuProfiler instance_; + + private: + // This lock implements the locking requirements described in the ProfileData + // documentation, specifically: + // + // lock_ is held all over all collector_ method calls except for the 'Add' + // call made from the signal handler, to protect against concurrent use of + // collector_'s control routines. Code other than signal handler must + // unregister the signal handler before calling any collector_ method. + // 'Add' method in the collector is protected by a guarantee from + // ProfileHandle that only one instance of prof_handler can run at a time. + SpinLock lock_; + ProfileData collector_; + + // Filter function and its argument, if any. (NULL means include all + // samples). Set at start, read-only while running. Written while holding + // lock_, read and executed in the context of SIGPROF interrupt. + int (*filter_)(void*); + void* filter_arg_; + + // Opaque token returned by the profile handler. To be used when calling + // ProfileHandlerUnregisterCallback. + ProfileHandlerToken* prof_handler_token_; + + // Sets up a callback to receive SIGPROF interrupt. + void EnableHandler(); + + // Disables receiving SIGPROF interrupt. + void DisableHandler(); + + // Signal handler that records the interrupted pc in the profile data. + static void prof_handler(int sig, siginfo_t*, void* signal_ucontext, + void* cpu_profiler); +}; + +// Signal handler that is registered when a user selectable signal +// number is defined in the environment variable CPUPROFILESIGNAL. +static void CpuProfilerSwitch(int signal_number) +{ + static unsigned profile_count; + static char base_profile_name[PATH_MAX]; + static bool started = false; + + if (base_profile_name[0] == '\0') { + if (!GetUniquePathFromEnv("CPUPROFILE", base_profile_name)) { + RAW_LOG(FATAL,"Cpu profiler switch is registered but no CPUPROFILE is defined"); + return; + } + } + + if (!started) { + char full_profile_name[PATH_MAX + 16]; + + snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", + base_profile_name, profile_count++); + + if(!ProfilerStart(full_profile_name)) { + RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", + full_profile_name, strerror(errno)); + } + } else { + ProfilerStop(); + } + started = !started; +} + +// Profile data structure singleton: Constructor will check to see if +// profiling should be enabled. Destructor will write profile data +// out to disk. +CpuProfiler CpuProfiler::instance_; + +// Initialize profiling: activated if getenv("CPUPROFILE") exists. +CpuProfiler::CpuProfiler() + : prof_handler_token_(NULL) { + // TODO(cgd) Move this code *out* of the CpuProfile constructor into a + // separate object responsible for initialization. With ProfileHandler there + // is no need to limit the number of profilers. + if (getenv("CPUPROFILE") == NULL) { + if (!FLAGS_cpu_profiler_unittest) { + RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n"); + } + return; + } + + // We don't enable profiling if setuid -- it's a security risk +#ifdef HAVE_GETEUID + if (getuid() != geteuid()) { + if (!FLAGS_cpu_profiler_unittest) { + RAW_LOG(WARNING, "Cannot perform CPU profiling when running with setuid\n"); + } + return; + } +#endif + + char *signal_number_str = getenv("CPUPROFILESIGNAL"); + if (signal_number_str != NULL) { + long int signal_number = strtol(signal_number_str, NULL, 10); + if (signal_number >= 1 && signal_number <= 64) { + intptr_t old_signal_handler = reinterpret_cast(signal(signal_number, CpuProfilerSwitch)); + if (old_signal_handler == 0) { + RAW_LOG(INFO,"Using signal %d as cpu profiling switch", signal_number); + } else { + RAW_LOG(FATAL, "Signal %d already in use\n", signal_number); + } + } else { + RAW_LOG(FATAL, "Signal number %s is invalid\n", signal_number_str); + } + } else { + char fname[PATH_MAX]; + if (!GetUniquePathFromEnv("CPUPROFILE", fname)) { + if (!FLAGS_cpu_profiler_unittest) { + RAW_LOG(WARNING, "CPU profiler linked but no valid CPUPROFILE environment variable found\n"); + } + return; + } + + if (!Start(fname, NULL)) { + RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", + fname, strerror(errno)); + } + } +} + +bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { + SpinLockHolder cl(&lock_); + + if (collector_.enabled()) { + return false; + } + + ProfileHandlerState prof_handler_state; + ProfileHandlerGetState(&prof_handler_state); + + ProfileData::Options collector_options; + collector_options.set_frequency(prof_handler_state.frequency); + if (!collector_.Start(fname, collector_options)) { + return false; + } + + filter_ = NULL; + if (options != NULL && options->filter_in_thread != NULL) { + filter_ = options->filter_in_thread; + filter_arg_ = options->filter_in_thread_arg; + } + + // Setup handler for SIGPROF interrupts + EnableHandler(); + + return true; +} + +CpuProfiler::~CpuProfiler() { + Stop(); +} + +// Stop profiling and write out any collected profile data +void CpuProfiler::Stop() { + SpinLockHolder cl(&lock_); + + if (!collector_.enabled()) { + return; + } + + // Unregister prof_handler to stop receiving SIGPROF interrupts before + // stopping the collector. + DisableHandler(); + + // DisableHandler waits for the currently running callback to complete and + // guarantees no future invocations. It is safe to stop the collector. + collector_.Stop(); +} + +void CpuProfiler::FlushTable() { + SpinLockHolder cl(&lock_); + + if (!collector_.enabled()) { + return; + } + + // Unregister prof_handler to stop receiving SIGPROF interrupts before + // flushing the profile data. + DisableHandler(); + + // DisableHandler waits for the currently running callback to complete and + // guarantees no future invocations. It is safe to flush the profile data. + collector_.FlushTable(); + + EnableHandler(); +} + +bool CpuProfiler::Enabled() { + SpinLockHolder cl(&lock_); + return collector_.enabled(); +} + +void CpuProfiler::GetCurrentState(ProfilerState* state) { + ProfileData::State collector_state; + { + SpinLockHolder cl(&lock_); + collector_.GetCurrentState(&collector_state); + } + + state->enabled = collector_state.enabled; + state->start_time = static_cast(collector_state.start_time); + state->samples_gathered = collector_state.samples_gathered; + int buf_size = sizeof(state->profile_name); + strncpy(state->profile_name, collector_state.profile_name, buf_size); + state->profile_name[buf_size-1] = '\0'; +} + +void CpuProfiler::EnableHandler() { + RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered"); + prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this); + RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler"); +} + +void CpuProfiler::DisableHandler() { + RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered"); + ProfileHandlerUnregisterCallback(prof_handler_token_); + prof_handler_token_ = NULL; +} + +// Signal handler that records the pc in the profile-data structure. We do no +// synchronization here. profile-handler.cc guarantees that at most one +// instance of prof_handler() will run at a time. All other routines that +// access the data touched by prof_handler() disable this signal handler before +// accessing the data and therefore cannot execute concurrently with +// prof_handler(). +void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, + void* cpu_profiler) { + CpuProfiler* instance = static_cast(cpu_profiler); + + if (instance->filter_ == NULL || + (*instance->filter_)(instance->filter_arg_)) { + void* stack[ProfileData::kMaxStackDepth]; + + // Under frame-pointer-based unwinding at least on x86, 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] = GetPC(*reinterpret_cast(signal_ucontext)); + + // We skip the top three stack trace entries (this function, + // SignalHandler::SignalHandler and one signal handler frame) + // since they are artifacts of profiling and should not be + // measured. Other profiling related frames may be removed by + // "pprof" at analysis time. Instead of skipping the top frames, + // we could skip nothing, but that would increase the profile size + // unnecessarily. + int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, + 3, signal_ucontext); + + void **used_stack; + if (depth > 0 && stack[1] == stack[0]) { + // in case of non-frame-pointer-based unwinding we will get + // duplicate of PC in stack[1], which we don't want + used_stack = stack + 1; + } else { + used_stack = stack; + depth++; // To account for pc value in stack[0]; + } + + instance->collector_.Add(depth, used_stack); + } +} + +#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) + +extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { + ProfileHandlerRegisterThread(); +} + +extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { + CpuProfiler::instance_.FlushTable(); +} + +extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { + return CpuProfiler::instance_.Enabled(); +} + +extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) { + return CpuProfiler::instance_.Start(fname, NULL); +} + +extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions( + const char *fname, const ProfilerOptions *options) { + return CpuProfiler::instance_.Start(fname, options); +} + +extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { + CpuProfiler::instance_.Stop(); +} + +extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState( + ProfilerState* state) { + CpuProfiler::instance_.GetCurrentState(state); +} + +extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( + void** result, int max_depth, int skip_count, const void *uc) { + return GetStackTraceWithContext(result, max_depth, skip_count, uc); +} + +#else // OS_CYGWIN + +// ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't +// work as well for profiling, and also interferes with alarm(). Because of +// these issues, unless a specific need is identified, profiler support is +// disabled under Cygwin. +extern "C" void ProfilerRegisterThread() { } +extern "C" void ProfilerFlush() { } +extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } +extern "C" int ProfilerStart(const char* fname) { return 0; } +extern "C" int ProfilerStartWithOptions(const char *fname, + const ProfilerOptions *options) { + return 0; +} +extern "C" void ProfilerStop() { } +extern "C" void ProfilerGetCurrentState(ProfilerState* state) { + memset(state, 0, sizeof(*state)); +} +extern "C" int ProfilerGetStackTrace( + void** result, int max_depth, int skip_count, const void *uc) { + return 0; +} + +#endif // OS_CYGWIN + +// DEPRECATED routines +extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { } +extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { } diff --git a/trunk/3rdparty/gperftools-2-fit/src/raw_printer.cc b/trunk/3rdparty/gperftools-2-fit/src/raw_printer.cc new file mode 100644 index 000000000..785d473f0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/raw_printer.cc @@ -0,0 +1,72 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: sanjay@google.com (Sanjay Ghemawat) + +#include +#include +#include +#include "raw_printer.h" +#include "base/logging.h" + +namespace base { + +RawPrinter::RawPrinter(char* buf, int length) + : base_(buf), + ptr_(buf), + limit_(buf + length - 1) { + RAW_DCHECK(length > 0, ""); + *ptr_ = '\0'; + *limit_ = '\0'; +} + +void RawPrinter::Printf(const char* format, ...) { + if (limit_ > ptr_) { + va_list ap; + va_start(ap, format); + int avail = limit_ - ptr_; + // We pass avail+1 to vsnprintf() since that routine needs room + // to store the trailing \0. + const int r = perftools_vsnprintf(ptr_, avail+1, format, ap); + va_end(ap); + if (r < 0) { + // Perhaps an old glibc that returns -1 on truncation? + ptr_ = limit_; + } else if (r > avail) { + // Truncation + ptr_ = limit_; + } else { + ptr_ += r; + } + } +} + +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/raw_printer.h b/trunk/3rdparty/gperftools-2-fit/src/raw_printer.h new file mode 100644 index 000000000..5f57bbf40 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/raw_printer.h @@ -0,0 +1,90 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat +// +// A printf() wrapper that writes into a fixed length buffer. +// Useful in low-level code that does not want to use allocating +// routines like StringPrintf(). +// +// The implementation currently uses vsnprintf(). This seems to +// be fine for use in many low-level contexts, but we may need to +// rethink this decision if we hit a problem with it calling +// down into malloc() etc. + +#ifndef BASE_RAW_PRINTER_H_ +#define BASE_RAW_PRINTER_H_ + +#include +#include "base/basictypes.h" + +namespace base { + +class RawPrinter { + public: + // REQUIRES: "length > 0" + // Will printf any data added to this into "buf[0,length-1]" and + // will arrange to always keep buf[] null-terminated. + RawPrinter(char* buf, int length); + + // Return the number of bytes that have been appended to the string + // so far. Does not count any bytes that were dropped due to overflow. + int length() const { return (ptr_ - base_); } + + // Return the number of bytes that can be added to this. + int space_left() const { return (limit_ - ptr_); } + + // Format the supplied arguments according to the "format" string + // and append to this. Will silently truncate the output if it does + // not fit. + void Printf(const char* format, ...) +#ifdef HAVE___ATTRIBUTE__ + __attribute__ ((__format__ (__printf__, 2, 3))) +#endif +; + + private: + // We can write into [ptr_ .. limit_-1]. + // *limit_ is also writable, but reserved for a terminating \0 + // in case we overflow. + // + // Invariants: *ptr_ == \0 + // Invariants: *limit_ == \0 + char* base_; // Initial pointer + char* ptr_; // Where should we write next + char* limit_; // One past last non-\0 char we can write + + DISALLOW_COPY_AND_ASSIGN(RawPrinter); +}; + +} + +#endif // BASE_RAW_PRINTER_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/sampler.cc b/trunk/3rdparty/gperftools-2-fit/src/sampler.cc new file mode 100644 index 000000000..20bf1ad57 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/sampler.cc @@ -0,0 +1,134 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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. + +// --- +// All Rights Reserved. +// +// Author: Daniel Ford + +#include "sampler.h" + +#include // For min() +#include +#include "base/commandlineflags.h" + +using std::min; + +// The approximate gap in bytes between sampling actions. +// I.e., we take one sample approximately once every +// tcmalloc_sample_parameter bytes of allocation +// i.e. about once every 512KB if value is 1<<19. +#ifdef NO_TCMALLOC_SAMPLES +DEFINE_int64(tcmalloc_sample_parameter, 0, + "Unused: code is compiled with NO_TCMALLOC_SAMPLES"); +#else +DEFINE_int64(tcmalloc_sample_parameter, + EnvToInt64("TCMALLOC_SAMPLE_PARAMETER", 0), + "The approximate gap in bytes between sampling actions. " + "This must be between 1 and 2^58."); +#endif + +namespace tcmalloc { + +int Sampler::GetSamplePeriod() { + return FLAGS_tcmalloc_sample_parameter; +} + +// Run this before using your sampler +void Sampler::Init(uint64_t seed) { + ASSERT(seed != 0); + + // Initialize PRNG + rnd_ = seed; + // Step it forward 20 times for good measure + for (int i = 0; i < 20; i++) { + rnd_ = NextRandom(rnd_); + } + // Initialize counter + bytes_until_sample_ = PickNextSamplingPoint(); +} + +#define MAX_SSIZE (static_cast(static_cast(static_cast(-1)) >> 1)) + +// Generates a geometric variable with the specified mean (512K by default). +// This is done by generating a random number between 0 and 1 and applying +// the inverse cumulative distribution function for an exponential. +// Specifically: Let m be the inverse of the sample period, then +// the probability distribution function is m*exp(-mx) so the CDF is +// p = 1 - exp(-mx), so +// q = 1 - p = exp(-mx) +// log_e(q) = -mx +// -log_e(q)/m = x +// log_2(q) * (-log_e(2) * 1/m) = x +// In the code, q is actually in the range 1 to 2**26, hence the -26 below +ssize_t Sampler::PickNextSamplingPoint() { + if (FLAGS_tcmalloc_sample_parameter <= 0) { + // In this case, we don't want to sample ever, and the larger a + // value we put here, the longer until we hit the slow path + // again. However, we have to support the flag changing at + // runtime, so pick something reasonably large (to keep overhead + // low) but small enough that we'll eventually start to sample + // again. + return 16 << 20; + } + + rnd_ = NextRandom(rnd_); + // Take the top 26 bits as the random number + // (This plus the 1<<58 sampling bound give a max possible step of + // 5194297183973780480 bytes.) + const uint64_t prng_mod_power = 48; // Number of bits in prng + // The uint32_t cast is to prevent a (hard-to-reproduce) NAN + // under piii debug for some binaries. + double q = static_cast(rnd_ >> (prng_mod_power - 26)) + 1.0; + // Put the computed p-value through the CDF of a geometric. + double interval = + (log2(q) - 26) * (-log(2.0) * FLAGS_tcmalloc_sample_parameter); + + // Very large values of interval overflow ssize_t. If we happen to + // hit such improbable condition, we simply cheat and clamp interval + // to largest supported value. + return static_cast( + std::min(interval, static_cast(MAX_SSIZE))); +} + +bool Sampler::RecordAllocationSlow(size_t k) { + if (!initialized_) { + initialized_ = true; + Init(reinterpret_cast(this)); + if (static_cast(bytes_until_sample_) >= k) { + bytes_until_sample_ -= k; + return true; + } + } + bytes_until_sample_ = PickNextSamplingPoint(); + return FLAGS_tcmalloc_sample_parameter <= 0; +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/sampler.h b/trunk/3rdparty/gperftools-2-fit/src/sampler.h new file mode 100644 index 000000000..82b1e6793 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/sampler.h @@ -0,0 +1,232 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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. + +// --- +// All Rights Reserved. +// +// Author: Daniel Ford + +#ifndef TCMALLOC_SAMPLER_H_ +#define TCMALLOC_SAMPLER_H_ + +#include "config.h" +#include // for size_t +#ifdef HAVE_STDINT_H +#include // for uint64_t, uint32_t, int32_t +#endif +#include // for memcpy +#include "base/basictypes.h" // for ASSERT +#include "internal_logging.h" // for ASSERT +#include "static_vars.h" + +namespace tcmalloc { + +//------------------------------------------------------------------- +// Sampler to decide when to create a sample trace for an allocation +// Not thread safe: Each thread should have it's own sampler object. +// Caller must use external synchronization if used +// from multiple threads. +// +// With 512K average sample step (the default): +// the probability of sampling a 4K allocation is about 0.00778 +// the probability of sampling a 1MB allocation is about 0.865 +// the probability of sampling a 1GB allocation is about 1.00000 +// In general, the probablity of sampling is an allocation of size X +// given a flag value of Y (default 1M) is: +// 1 - e^(-X/Y) +// +// With 128K average sample step: +// the probability of sampling a 1MB allocation is about 0.99966 +// the probability of sampling a 1GB allocation is about 1.0 +// (about 1 - 2**(-26)) +// With 1M average sample step: +// the probability of sampling a 4K allocation is about 0.00390 +// the probability of sampling a 1MB allocation is about 0.632 +// the probability of sampling a 1GB allocation is about 1.0 +// +// The sampler works by representing memory as a long stream from +// which allocations are taken. Some of the bytes in this stream are +// marked and if an allocation includes a marked byte then it is +// sampled. Bytes are marked according to a Poisson point process +// with each byte being marked independently with probability +// p = 1/tcmalloc_sample_parameter. This makes the probability +// of sampling an allocation of X bytes equal to the CDF of +// a geometric with mean tcmalloc_sample_parameter. (ie. the +// probability that at least one byte in the range is marked). This +// is accurately given by the CDF of the corresponding exponential +// distribution : 1 - e^(-X/tcmalloc_sample_parameter_) +// Independence of the byte marking ensures independence of +// the sampling of each allocation. +// +// This scheme is implemented by noting that, starting from any +// fixed place, the number of bytes until the next marked byte +// is geometrically distributed. This number is recorded as +// bytes_until_sample_. Every allocation subtracts from this +// number until it is less than 0. When this happens the current +// allocation is sampled. +// +// When an allocation occurs, bytes_until_sample_ is reset to +// a new independtly sampled geometric number of bytes. The +// memoryless property of the point process means that this may +// be taken as the number of bytes after the end of the current +// allocation until the next marked byte. This ensures that +// very large allocations which would intersect many marked bytes +// only result in a single call to PickNextSamplingPoint. +//------------------------------------------------------------------- + +class SamplerTest; + +class PERFTOOLS_DLL_DECL Sampler { + public: + constexpr Sampler() {} + + // Initialize this sampler. + void Init(uint64_t seed); + + // Record allocation of "k" bytes. Return true if no further work + // is need, and false if allocation needed to be sampled. + bool RecordAllocation(size_t k); + + // Same as above (but faster), except: + // a) REQUIRES(k < std::numeric_limits::max()) + // b) if this returns false, you must call RecordAllocation + // to confirm if sampling truly needed. + // + // The point of this function is to only deal with common case of no + // sampling and let caller (which is in malloc fast-path) to + // "escalate" to fuller and slower logic only if necessary. + bool TryRecordAllocationFast(size_t k); + + // Generate a geometric with mean 512K (or FLAG_tcmalloc_sample_parameter) + ssize_t PickNextSamplingPoint(); + + // Returns the current sample period + static int GetSamplePeriod(); + + // The following are public for the purposes of testing + static uint64_t NextRandom(uint64_t rnd_); // Returns the next prng value + + // C++03 requires that types stored in TLS be POD. As a result, you must + // initialize these members to {0, 0, false} before using this class! + // + // TODO(ahh): C++11 support will let us make these private. + + // Bytes until we sample next. + // + // More specifically when bytes_until_sample_ is X, we can allocate + // X bytes without triggering sampling; on the (X+1)th allocated + // byte, the containing allocation will be sampled. + // + // Always non-negative with only very brief exceptions (see + // DecrementFast{,Finish}, so casting to size_t is ok. + private: + friend class SamplerTest; + bool RecordAllocationSlow(size_t k); + + ssize_t bytes_until_sample_{}; + uint64_t rnd_{}; // Cheap random number generator + bool initialized_{}; +}; + +inline bool Sampler::RecordAllocation(size_t k) { + // The first time we enter this function we expect bytes_until_sample_ + // to be zero, and we must call SampleAllocationSlow() to ensure + // proper initialization of static vars. + ASSERT(Static::IsInited() || bytes_until_sample_ == 0); + + // Note that we have to deal with arbitrarily large values of k + // here. Thus we're upcasting bytes_until_sample_ to unsigned rather + // than the other way around. And this is why this code cannot be + // merged with DecrementFast code below. + if (static_cast(bytes_until_sample_) < k) { + bool result = RecordAllocationSlow(k); + ASSERT(Static::IsInited()); + return result; + } else { + bytes_until_sample_ -= k; + ASSERT(Static::IsInited()); + return true; + } +} + +inline bool Sampler::TryRecordAllocationFast(size_t k) { + // For efficiency reason, we're testing bytes_until_sample_ after + // decrementing it by k. This allows compiler to do sub , + // followed by conditional jump on sign. But it is correct only if k + // is actually smaller than largest ssize_t value. Otherwise + // converting k to signed value overflows. + // + // It would be great for generated code to be sub , + // followed by conditional jump on 'carry', which would work for + // arbitrary values of k, but there seem to be no way to express + // that in C++. + // + // Our API contract explicitly states that only small values of k + // are permitted. And thus it makes sense to assert on that. + ASSERT(static_cast(k) >= 0); + + bytes_until_sample_ -= static_cast(k); + if (PREDICT_FALSE(bytes_until_sample_ < 0)) { + // Note, we undo sampling counter update, since we're not actually + // handling slow path in the "needs sampling" case (calling + // RecordAllocationSlow to reset counter). And we do that in order + // to avoid non-tail calls in malloc fast-path. See also comments + // on declaration inside Sampler class. + // + // volatile is used here to improve compiler's choice of + // instuctions. We know that this path is very rare and that there + // is no need to keep previous value of bytes_until_sample_ in + // register. This helps compiler generate slightly more efficient + // sub , instruction for subtraction above. + volatile ssize_t *ptr = + const_cast(&bytes_until_sample_); + *ptr += k; + return false; + } + return true; +} + +// Inline functions which are public for testing purposes + +// Returns the next prng value. +// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48 +// This is the lrand64 generator. +inline uint64_t Sampler::NextRandom(uint64_t rnd) { + const uint64_t prng_mult = 0x5DEECE66DULL; + const uint64_t prng_add = 0xB; + const uint64_t prng_mod_power = 48; + const uint64_t prng_mod_mask = + ~((~static_cast(0)) << prng_mod_power); + return (prng_mult * rnd + prng_add) & prng_mod_mask; +} + +} // namespace tcmalloc + +#endif // TCMALLOC_SAMPLER_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/span.cc b/trunk/3rdparty/gperftools-2-fit/src/span.cc new file mode 100644 index 000000000..eac43f4d6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/span.cc @@ -0,0 +1,90 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#include +#include "span.h" + +#include // for NULL, memset + +#include "internal_logging.h" // for ASSERT +#include "page_heap_allocator.h" // for PageHeapAllocator +#include "static_vars.h" // for Static + +namespace tcmalloc { + +Span* NewSpan(PageID p, Length len) { + Span* result = Static::span_allocator()->New(); + memset(result, 0, sizeof(*result)); + result->start = p; + result->length = len; + return result; +} + +void DeleteSpan(Span* span) { +#ifndef NDEBUG + // In debug mode, trash the contents of deleted Spans + memset(span, 0x3f, sizeof(*span)); +#endif + Static::span_allocator()->Delete(span); +} + +void DLL_Init(Span* list) { + list->next = list; + list->prev = list; +} + +void DLL_Remove(Span* span) { + span->prev->next = span->next; + span->next->prev = span->prev; + span->prev = NULL; + span->next = NULL; +} + +int DLL_Length(const Span* list) { + int result = 0; + for (Span* s = list->next; s != list; s = s->next) { + result++; + } + return result; +} + +void DLL_Prepend(Span* list, Span* span) { + ASSERT(span->next == NULL); + ASSERT(span->prev == NULL); + span->next = list->next; + span->prev = list; + list->next->prev = span; + list->next = span; +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/span.h b/trunk/3rdparty/gperftools-2-fit/src/span.h new file mode 100644 index 000000000..70688933c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/span.h @@ -0,0 +1,161 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat +// +// A Span is a contiguous run of pages. + +#ifndef TCMALLOC_SPAN_H_ +#define TCMALLOC_SPAN_H_ + +#include +#include +#include "common.h" +#include "base/logging.h" +#include "page_heap_allocator.h" + +namespace tcmalloc { + +struct SpanBestFitLess; +struct Span; + +// Store a pointer to a span along with a cached copy of its length. +// These are used as set elements to improve the performance of +// comparisons during tree traversal: the lengths are inline with the +// tree nodes and thus avoid expensive cache misses to dereference +// the actual Span objects in most cases. +struct SpanPtrWithLength { + explicit SpanPtrWithLength(Span* s); + + Span* span; + Length length; +}; +typedef std::set > SpanSet; + +// Comparator for best-fit search, with address order as a tie-breaker. +struct SpanBestFitLess { + bool operator()(SpanPtrWithLength a, SpanPtrWithLength b) const; +}; + +// Information kept for a span (a contiguous run of pages). +struct Span { + PageID start; // Starting page number + Length length; // Number of pages in span + Span* next; // Used when in link list + Span* prev; // Used when in link list + union { + void* objects; // Linked list of free objects + + // Span may contain iterator pointing back at SpanSet entry of + // this span into set of large spans. It is used to quickly delete + // spans from those sets. span_iter_space is space for such + // iterator which lifetime is controlled explicitly. + char span_iter_space[sizeof(SpanSet::iterator)]; + }; + unsigned int refcount : 16; // Number of non-free objects + unsigned int sizeclass : 8; // Size-class for small objects (or 0) + unsigned int location : 2; // Is the span on a freelist, and if so, which? + unsigned int sample : 1; // Sampled object? + bool has_span_iter : 1; // Iff span_iter_space has valid + // iterator. Only for debug builds. + + // Sets iterator stored in span_iter_space. + // Requires has_span_iter == 0. + void SetSpanSetIterator(const SpanSet::iterator& iter); + // Copies out and destroys iterator stored in span_iter_space. + SpanSet::iterator ExtractSpanSetIterator(); + + // What freelist the span is on: IN_USE if on none, or normal or returned + enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST }; +}; + +inline SpanPtrWithLength::SpanPtrWithLength(Span* s) + : span(s), + length(s->length) { +} + +inline bool SpanBestFitLess::operator()(SpanPtrWithLength a, SpanPtrWithLength b) const { + if (a.length < b.length) + return true; + if (a.length > b.length) + return false; + return a.span->start < b.span->start; +} + +inline void Span::SetSpanSetIterator(const SpanSet::iterator& iter) { + ASSERT(!has_span_iter); + has_span_iter = 1; + + new (span_iter_space) SpanSet::iterator(iter); +} + +inline SpanSet::iterator Span::ExtractSpanSetIterator() { + typedef SpanSet::iterator iterator_type; + + ASSERT(has_span_iter); + has_span_iter = 0; + + iterator_type* this_iter = + reinterpret_cast(span_iter_space); + iterator_type retval = *this_iter; + this_iter->~iterator_type(); + return retval; +} + +// Allocator/deallocator for spans +Span* NewSpan(PageID p, Length len); +void DeleteSpan(Span* span); + +// ------------------------------------------------------------------------- +// Doubly linked list of spans. +// ------------------------------------------------------------------------- + +// Initialize *list to an empty list. +void DLL_Init(Span* list); + +// Remove 'span' from the linked list in which it resides, updating the +// pointers of adjacent Spans and setting span's next and prev to NULL. +void DLL_Remove(Span* span); + +// Return true iff "list" is empty. +inline bool DLL_IsEmpty(const Span* list) { + return list->next == list; +} + +// Add span to the front of list. +void DLL_Prepend(Span* list, Span* span); + +// Return the length of the linked list. O(n) +int DLL_Length(const Span* list); + +} // namespace tcmalloc + +#endif // TCMALLOC_SPAN_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.cc b/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.cc new file mode 100644 index 000000000..5888dc041 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.cc @@ -0,0 +1,123 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2009, 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: Andrew Fikes + +#include +#include "stack_trace_table.h" +#include // for NULL, memset +#include "base/spinlock.h" // for SpinLockHolder +#include "common.h" // for StackTrace +#include "internal_logging.h" // for ASSERT, Log +#include "page_heap_allocator.h" // for PageHeapAllocator +#include "static_vars.h" // for Static + +namespace tcmalloc { + +StackTraceTable::StackTraceTable() + : error_(false), + depth_total_(0), + bucket_total_(0), + head_(nullptr) { +} + +StackTraceTable::~StackTraceTable() { + ASSERT(head_ == nullptr); +} + +void StackTraceTable::AddTrace(const StackTrace& t) { + if (error_) { + return; + } + + depth_total_ += t.depth; + bucket_total_++; + Entry* entry = allocator_.allocate(1); + if (entry == nullptr) { + Log(kLog, __FILE__, __LINE__, + "tcmalloc: could not allocate bucket", sizeof(*entry)); + error_ = true; + } else { + entry->trace = t; + entry->next = head_; + head_ = entry; + } +} + +void** StackTraceTable::ReadStackTracesAndClear() { + void** out = nullptr; + + const int out_len = bucket_total_ * 3 + depth_total_ + 1; + if (!error_) { + // Allocate output array + out = new (std::nothrow_t{}) void*[out_len]; + if (out == nullptr) { + Log(kLog, __FILE__, __LINE__, + "tcmalloc: allocation failed for stack traces", + out_len * sizeof(*out)); + } + } + + if (out) { + // Fill output array + int idx = 0; + Entry* entry = head_; + while (entry != NULL) { + out[idx++] = reinterpret_cast(uintptr_t{1}); // count + out[idx++] = reinterpret_cast(entry->trace.size); // cumulative size + out[idx++] = reinterpret_cast(entry->trace.depth); + for (int d = 0; d < entry->trace.depth; ++d) { + out[idx++] = entry->trace.stack[d]; + } + entry = entry->next; + } + out[idx++] = NULL; + ASSERT(idx == out_len); + } + + // Clear state + error_ = false; + depth_total_ = 0; + bucket_total_ = 0; + + SpinLockHolder h(Static::pageheap_lock()); + Entry* entry = head_; + while (entry != nullptr) { + Entry* next = entry->next; + allocator_.deallocate(entry, 1); + entry = next; + } + head_ = nullptr; + + return out; +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.h b/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.h new file mode 100644 index 000000000..46b86bad0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stack_trace_table.h @@ -0,0 +1,85 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2009, 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: Andrew Fikes +// +// Utility class for coalescing sampled stack traces. Not thread-safe. + +#ifndef TCMALLOC_STACK_TRACE_TABLE_H_ +#define TCMALLOC_STACK_TRACE_TABLE_H_ + +#include +#ifdef HAVE_STDINT_H +#include // for uintptr_t +#endif +#include "common.h" +#include "page_heap_allocator.h" + +namespace tcmalloc { + +class PERFTOOLS_DLL_DECL StackTraceTable { + public: + // REQUIRES: L < pageheap_lock + StackTraceTable(); + ~StackTraceTable(); + + // Adds stack trace "t" to table. + // + // REQUIRES: L >= pageheap_lock + void AddTrace(const StackTrace& t); + + // Returns stack traces formatted per MallocExtension guidelines. + // May return NULL on error. Clears state before returning. + // + // REQUIRES: L < pageheap_lock + void** ReadStackTracesAndClear(); + + // Exposed for PageHeapAllocator + // For testing + int depth_total() const { return depth_total_; } + int bucket_total() const { return bucket_total_; } + + private: + struct Entry { + Entry* next; + StackTrace trace; + }; + + bool error_; + int depth_total_; + int bucket_total_; + Entry* head_; + STLPageHeapAllocator allocator_; +}; + +} // namespace tcmalloc + +#endif // TCMALLOC_STACK_TRACE_TABLE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace.cc b/trunk/3rdparty/gperftools-2-fit/src/stacktrace.cc new file mode 100644 index 000000000..2a2c64822 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace.cc @@ -0,0 +1,396 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Produce stack trace. +// +// There are three different ways we can try to get the stack trace: +// +// 1) Our hand-coded stack-unwinder. This depends on a certain stack +// layout, which is used by gcc (and those systems using a +// gcc-compatible ABI) on x86 systems, at least since gcc 2.95. +// It uses the frame pointer to do its work. +// +// 2) The libunwind library. This is still in development, and as a +// separate library adds a new dependency, abut doesn't need a frame +// pointer. It also doesn't call malloc. +// +// 3) The gdb unwinder -- also the one used by the c++ exception code. +// It's obviously well-tested, but has a fatal flaw: it can call +// malloc() from the unwinder. This is a problem because we're +// trying to use the unwinder to instrument malloc(). +// +// Note: if you add a new implementation here, make sure it works +// correctly when GetStackTrace() is called with max_depth == 0. +// Some code may do that. + +#include +#include // for getenv +#include // for strcmp +#include // for fprintf +#include "gperftools/stacktrace.h" +#include "base/commandlineflags.h" +#include "base/googleinit.h" +#include "getenv_safe.h" + + +// we're using plain struct and not class to avoid any possible issues +// during initialization. Struct of pointers is easy to init at +// link-time. +struct GetStackImplementation { + int (*GetStackFramesPtr)(void** result, int* sizes, int max_depth, + int skip_count); + + int (*GetStackFramesWithContextPtr)(void** result, int* sizes, int max_depth, + int skip_count, const void *uc); + + int (*GetStackTracePtr)(void** result, int max_depth, + int skip_count); + + int (*GetStackTraceWithContextPtr)(void** result, int max_depth, + int skip_count, const void *uc); + + const char *name; +}; + +#if HAVE_DECL_BACKTRACE +#define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h" +#define GST_SUFFIX generic +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_generic +#endif + +#ifdef HAVE_UNWIND_BACKTRACE +#define STACKTRACE_INL_HEADER "stacktrace_libgcc-inl.h" +#define GST_SUFFIX libgcc +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_libgcc +#endif + +// libunwind uses __thread so we check for both libunwind.h and +// __thread support +#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_TLS) +#define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h" +#define GST_SUFFIX libunwind +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_libunwind +#endif // HAVE_LIBUNWIND_H + +#if defined(__i386__) || defined(__x86_64__) +#define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h" +#define GST_SUFFIX x86 +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_x86 +#endif // i386 || x86_64 + +// Sadly, different OSes have very different mcontexts even for +// identical hardware arch. So keep it linux-only for now. +#if defined(__GNUC__) && __linux__ && (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) +#define STACKTRACE_INL_HEADER "stacktrace_generic_fp-inl.h" +#define GST_SUFFIX generic_fp +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_generic_fp + +#undef TCMALLOC_UNSAFE_GENERIC_FP_STACKTRACE +#define TCMALLOC_UNSAFE_GENERIC_FP_STACKTRACE 1 + +#define STACKTRACE_INL_HEADER "stacktrace_generic_fp-inl.h" +#define GST_SUFFIX generic_fp_unsafe +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_generic_fp_unsafe +#endif + +#if defined(__ppc__) || defined(__PPC__) +#if defined(__linux__) +#define STACKTRACE_INL_HEADER "stacktrace_powerpc-linux-inl.h" +#else +#define STACKTRACE_INL_HEADER "stacktrace_powerpc-darwin-inl.h" +#endif +#define GST_SUFFIX ppc +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_ppc +#endif + +#if defined(__arm__) +#define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h" +#define GST_SUFFIX arm +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_arm +#endif + +#ifdef TCMALLOC_ENABLE_INSTRUMENT_STACKTRACE +#define STACKTRACE_INL_HEADER "stacktrace_instrument-inl.h" +#define GST_SUFFIX instrument +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_instrument +#endif + +// The Windows case -- probably cygwin and mingw will use one of the +// x86-includes above, but if not, we can fall back to windows intrinsics. +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) +#define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h" +#define GST_SUFFIX win32 +#include "stacktrace_impl_setup-inl.h" +#undef GST_SUFFIX +#undef STACKTRACE_INL_HEADER +#define HAVE_GST_win32 +#endif + +static GetStackImplementation *all_impls[] = { +#ifdef HAVE_GST_libgcc + &impl__libgcc, +#endif +#ifdef HAVE_GST_generic + &impl__generic, +#endif +#ifdef HAVE_GST_generic_fp + &impl__generic_fp, +#endif +#ifdef HAVE_GST_generic_fp + &impl__generic_fp_unsafe, +#endif +#ifdef HAVE_GST_libunwind + &impl__libunwind, +#endif +#ifdef HAVE_GST_x86 + &impl__x86, +#endif +#ifdef HAVE_GST_arm + &impl__arm, +#endif +#ifdef HAVE_GST_ppc + &impl__ppc, +#endif +#ifdef HAVE_GST_instrument + &impl__instrument, +#endif +#ifdef HAVE_GST_win32 + &impl__win32, +#endif + NULL +}; + +// ppc and i386 implementations prefer arch-specific asm implementations. +// arm's asm implementation is broken +#if defined(__i386__) || defined(__ppc__) || defined(__PPC__) +#if !defined(NO_FRAME_POINTER) +#define TCMALLOC_DONT_PREFER_LIBUNWIND +#endif +#endif + +static bool get_stack_impl_inited; + +#if defined(HAVE_GST_instrument) +static GetStackImplementation *get_stack_impl = &impl__instrument; +#elif defined(HAVE_GST_win32) +static GetStackImplementation *get_stack_impl = &impl__win32; +#elif defined(HAVE_GST_generic_fp) && !defined(NO_FRAME_POINTER) \ + && !defined(__riscv) \ + && (!defined(HAVE_GST_libunwind) || defined(TCMALLOC_DONT_PREFER_LIBUNWIND)) +static GetStackImplementation *get_stack_impl = &impl__generic_fp; +#elif defined(HAVE_GST_x86) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND) +static GetStackImplementation *get_stack_impl = &impl__x86; +#elif defined(HAVE_GST_ppc) && defined(TCMALLOC_DONT_PREFER_LIBUNWIND) +static GetStackImplementation *get_stack_impl = &impl__ppc; +#elif defined(HAVE_GST_libunwind) +static GetStackImplementation *get_stack_impl = &impl__libunwind; +#elif defined(HAVE_GST_libgcc) +static GetStackImplementation *get_stack_impl = &impl__libgcc; +#elif defined(HAVE_GST_generic) +static GetStackImplementation *get_stack_impl = &impl__generic; +#elif defined(HAVE_GST_arm) +static GetStackImplementation *get_stack_impl = &impl__arm; +#elif 0 +// This is for the benefit of code analysis tools that may have +// trouble with the computed #include above. +# include "stacktrace_x86-inl.h" +# include "stacktrace_libunwind-inl.h" +# include "stacktrace_generic-inl.h" +# include "stacktrace_powerpc-inl.h" +# include "stacktrace_win32-inl.h" +# include "stacktrace_arm-inl.h" +# include "stacktrace_instrument-inl.h" +#else +#error Cannot calculate stack trace: will need to write for your environment +#endif + +static int ATTRIBUTE_NOINLINE frame_forcer(int rv) { + return rv; +} + +static void init_default_stack_impl_inner(void); + +namespace tcmalloc { + bool EnterStacktraceScope(void); + void LeaveStacktraceScope(void); +} + +namespace { + using tcmalloc::EnterStacktraceScope; + using tcmalloc::LeaveStacktraceScope; + + class StacktraceScope { + bool stacktrace_allowed; + public: + StacktraceScope() { + stacktrace_allowed = true; + stacktrace_allowed = EnterStacktraceScope(); + } + bool IsStacktraceAllowed() { + return stacktrace_allowed; + } + ~StacktraceScope() { + if (stacktrace_allowed) { + LeaveStacktraceScope(); + } + } + }; +} + +PERFTOOLS_DLL_DECL int GetStackFrames(void** result, int* sizes, int max_depth, + int skip_count) { + StacktraceScope scope; + if (!scope.IsStacktraceAllowed()) { + return 0; + } + init_default_stack_impl_inner(); + return frame_forcer(get_stack_impl->GetStackFramesPtr(result, sizes, max_depth, skip_count)); +} + +PERFTOOLS_DLL_DECL int GetStackFramesWithContext(void** result, int* sizes, int max_depth, + int skip_count, const void *uc) { + StacktraceScope scope; + if (!scope.IsStacktraceAllowed()) { + return 0; + } + init_default_stack_impl_inner(); + return frame_forcer(get_stack_impl->GetStackFramesWithContextPtr( + result, sizes, max_depth, + skip_count, uc)); +} + +PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth, + int skip_count) { + StacktraceScope scope; + if (!scope.IsStacktraceAllowed()) { + return 0; + } + init_default_stack_impl_inner(); + return frame_forcer(get_stack_impl->GetStackTracePtr(result, max_depth, skip_count)); +} + +PERFTOOLS_DLL_DECL int GetStackTraceWithContext(void** result, int max_depth, + int skip_count, const void *uc) { + StacktraceScope scope; + if (!scope.IsStacktraceAllowed()) { + return 0; + } + init_default_stack_impl_inner(); + return frame_forcer(get_stack_impl->GetStackTraceWithContextPtr( + result, max_depth, skip_count, uc)); +} + +// As of this writing, aarch64 has completely borked libunwind, so +// lets test this case and fall back to frame pointers (which is +// nearly but not quite perfect). +ATTRIBUTE_NOINLINE +static void maybe_convert_libunwind_to_generic_fp() { +#if defined(HAVE_GST_libunwind) && defined(HAVE_GST_generic_fp) + if (get_stack_impl != &impl__libunwind) { + return; + } + + // Okay we're on libunwind and we have generic_fp, check if + // libunwind returns bogus results. + void* stack[4]; + int rv = get_stack_impl->GetStackTracePtr(stack, 4, 0); + if (rv > 2) { + // Seems fine + return; + } + // bogus. So replacing with generic_fp + get_stack_impl = &impl__generic_fp; +#endif +} + +static void init_default_stack_impl_inner(void) { + if (get_stack_impl_inited) { + return; + } + get_stack_impl_inited = true; + const char *val = TCMallocGetenvSafe("TCMALLOC_STACKTRACE_METHOD"); + if (!val || !*val) { + maybe_convert_libunwind_to_generic_fp(); + return; + } + for (GetStackImplementation **p = all_impls; *p; p++) { + GetStackImplementation *c = *p; + if (strcmp(c->name, val) == 0) { + get_stack_impl = c; + return; + } + } + fprintf(stderr, "Unknown or unsupported stacktrace method requested: %s. Ignoring it\n", val); +} + +ATTRIBUTE_NOINLINE +static void init_default_stack_impl(void) { + init_default_stack_impl_inner(); + if (EnvToBool("TCMALLOC_STACKTRACE_METHOD_VERBOSE", false)) { + fprintf(stderr, "Chosen stacktrace method is %s\nSupported methods:\n", get_stack_impl->name); + for (GetStackImplementation **p = all_impls; *p; p++) { + GetStackImplementation *c = *p; + fprintf(stderr, "* %s\n", c->name); + } + fputs("\n", stderr); + } +} + +REGISTER_MODULE_INITIALIZER(stacktrace_init_default_stack_impl, init_default_stack_impl()); diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_arm-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_arm-inl.h new file mode 100644 index 000000000..1586b8fec --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_arm-inl.h @@ -0,0 +1,148 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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: Doug Kwan +// This is inspired by Craig Silverstein's PowerPC stacktrace code. +// + +#ifndef BASE_STACKTRACE_ARM_INL_H_ +#define BASE_STACKTRACE_ARM_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include "base/basictypes.h" // for NULL +#include + +// WARNING: +// This only works if all your code is in either ARM or THUMB mode. With +// interworking, the frame pointer of the caller can either be in r11 (ARM +// mode) or r7 (THUMB mode). A callee only saves the frame pointer of its +// mode in a fixed location on its stack frame. If the caller is a different +// mode, there is no easy way to find the frame pointer. It can either be +// still in the designated register or saved on stack along with other callee +// saved registers. + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static void **NextStackFrame(void **old_sp) { + void **new_sp = (void**) old_sp[-1]; + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) + && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL; + } + if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; + return new_sp; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +#ifdef __GNUC__ +void StacktraceArmDummyFunction() __attribute__((noinline)); +void StacktraceArmDummyFunction() { __asm__ volatile(""); } +#else +# error StacktraceArmDummyFunction() needs to be ported to this platform. +#endif +#endif // BASE_STACKTRACE_ARM_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { +#ifdef __GNUC__ + void **sp = reinterpret_cast(__builtin_frame_address(0)); +#else +# error reading stack point not yet supported on this platform. +#endif + + // On ARM, the return address is stored in the link register (r14). + // This is not saved on the stack frame of a leaf function. To + // simplify code that reads return addresses, we call a dummy + // function so that the return address of this function is also + // stored in the stack frame. This works at least for gcc. + StacktraceArmDummyFunction(); + + skip_count++; // skip parent frame due to indirection in stacktrace.cc + + int n = 0; + while (sp && n < max_depth) { + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few bogus + // entries in some rare cases). + void **next_sp = NextStackFrame(sp); + + if (skip_count > 0) { + skip_count--; + } else { + result[n] = *sp; + +#if IS_STACK_FRAMES + if (next_sp > sp) { + sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + sp = next_sp; + } + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic-inl.h new file mode 100644 index 000000000..7d7c22d9e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic-inl.h @@ -0,0 +1,84 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Portable implementation - just use glibc +// +// Note: The glibc implementation may cause a call to malloc. +// This can cause a deadlock in HeapProfiler. + +#ifndef BASE_STACKTRACE_GENERIC_INL_H_ +#define BASE_STACKTRACE_GENERIC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include +#include +#include "gperftools/stacktrace.h" +#endif // BASE_STACKTRACE_GENERIC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + static const int kStackLength = 64; + void * stack[kStackLength]; + int size; + + size = backtrace(stack, kStackLength); + skip_count += 2; // we want to skip the current and it's parent frame as well + int result_count = size - skip_count; + if (result_count < 0) + result_count = 0; + if (result_count > max_depth) + result_count = max_depth; + for (int i = 0; i < result_count; i++) + result[i] = stack[i + skip_count]; + +#if IS_STACK_FRAMES + // No implementation for finding out the stack frame sizes yet. + memset(sizes, 0, sizeof(*sizes) * result_count); +#endif + + return result_count; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic_fp-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic_fp-inl.h new file mode 100644 index 000000000..d45810978 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_generic_fp-inl.h @@ -0,0 +1,222 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2021, gperftools Contributors +// 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. + +// This file contains "generic" stack frame pointer backtracing +// code. Attempt is made to minimize amount of arch- or os-specific +// code and keep everything as generic as possible. Currently +// supported are x86-64, aarch64 and riscv. +#ifndef BASE_STACKTRACE_GENERIC_FP_INL_H_ +#define BASE_STACKTRACE_GENERIC_FP_INL_H_ + +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include +#endif + +// This is only used on OS-es with mmap support. +#include + +// Set this to true to disable "probing" of addresses that are read to +// make backtracing less-safe, but faster. +#ifndef TCMALLOC_UNSAFE_GENERIC_FP_STACKTRACE +#define TCMALLOC_UNSAFE_GENERIC_FP_STACKTRACE 0 +#endif + +namespace { +namespace stacktrace_generic_fp { + +struct frame { + uintptr_t parent; + void* pc; +}; + +frame* adjust_fp(frame* f) { +#ifdef __riscv + return f - 1; +#else + return f; +#endif +} + +static bool CheckPageIsReadable(void* ptr, void* checked_ptr) { + static uintptr_t pagesize; + if (pagesize == 0) { + pagesize = getpagesize(); + } + + uintptr_t addr = reinterpret_cast(ptr); + uintptr_t parent_frame = reinterpret_cast(checked_ptr); + + parent_frame &= ~(pagesize - 1); + addr &= ~(pagesize - 1); + + if (parent_frame != 0 && addr == parent_frame) { + return true; + } + + return (msync(reinterpret_cast(addr), pagesize, MS_ASYNC) == 0); +} + +ATTRIBUTE_NOINLINE // forces architectures with link register to save it +int capture(void **result, int max_depth, int skip_count, + void* initial_frame, void* const * initial_pc) { + int i = 0; + + if (initial_pc != nullptr) { + // This is 'with ucontext' case. We take first pc from ucontext + // and then skip_count is ignored as we assume that caller only + // needed stack trace up to signal handler frame. + skip_count = 0; + if (max_depth == 0) { + return 0; + } + result[0] = *initial_pc; + i++; + } + + constexpr uintptr_t kTooSmallAddr = 16 << 10; + constexpr uintptr_t kFrameSizeThreshold = 128 << 10; + + // This is simplistic yet. Here we're targeting x86-64, aarch64 and + // riscv. All have 16 bytes stack alignment (even 32 bit + // riscv). This can be made more elaborate as we consider more + // architectures. Note, it allows us to only readability of check + // f->parent address. + constexpr uintptr_t kAlignment = 16; + + uintptr_t initial_frame_addr = reinterpret_cast(initial_frame); + if ((initial_frame_addr & (kAlignment - 1)) != 0) { + return i; + } + if (initial_frame_addr < kTooSmallAddr) { + return i; + } + + frame* prev_f = nullptr; + frame *f = adjust_fp(reinterpret_cast(initial_frame)); + + while (i < max_depth) { + if (!TCMALLOC_UNSAFE_GENERIC_FP_STACKTRACE + && !CheckPageIsReadable(&f->parent, prev_f)) { + break; + } + + void* pc = f->pc; + if (pc == nullptr) { + break; + } + + if (i >= skip_count) { + result[i - skip_count] = pc; + } + + i++; + + uintptr_t parent_frame_addr = f->parent; + uintptr_t child_frame_addr = reinterpret_cast(f); + + if (parent_frame_addr < kTooSmallAddr) { + break; + } + // stack grows towards smaller addresses, so if we didn't see + // frame address increased (going from child to parent), it is bad + // frame. We also test if frame is too big since that is another + // sign of bad stack frame. + if (parent_frame_addr - child_frame_addr > kFrameSizeThreshold) { + break; + } + + if ((parent_frame_addr & (kAlignment - 1)) != 0) { + // not aligned, so we keep it safe and assume frame is bogus + break; + } + + prev_f = f; + + f = adjust_fp(reinterpret_cast(parent_frame_addr)); + } + return i; +} + +} // namespace stacktrace_generic_fp +} // namespace + +#endif // BASE_STACKTRACE_GENERIC_FP_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) + +static int GET_STACK_TRACE_OR_FRAMES { +#if IS_STACK_FRAMES + memset(sizes, 0, sizeof(*sizes) * max_depth); +#endif + + // one for this function + skip_count += 1; + + void* const * initial_pc = nullptr; + void* initial_frame = __builtin_frame_address(0); + +#if IS_WITH_CONTEXT + if (ucp) { + auto uc = static_cast(ucp); +#ifdef __riscv + initial_pc = reinterpret_cast(&uc->uc_mcontext.__gregs[REG_PC]); + initial_frame = reinterpret_cast(uc->uc_mcontext.__gregs[REG_S0]); +#elif __aarch64__ + initial_pc = reinterpret_cast(&uc->uc_mcontext.pc); + initial_frame = reinterpret_cast(uc->uc_mcontext.regs[29]); +#else + initial_pc = reinterpret_cast(&uc->uc_mcontext.gregs[REG_RIP]); + initial_frame = reinterpret_cast(uc->uc_mcontext.gregs[REG_RBP]); +#endif + } +#endif // IS_WITH_CONTEXT + + int n = stacktrace_generic_fp::capture(result, max_depth, skip_count, + initial_frame, initial_pc); + + // make sure we don't tail-call capture + (void)*(const_cast(result)); + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_impl_setup-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_impl_setup-inl.h new file mode 100644 index 000000000..698c5b381 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_impl_setup-inl.h @@ -0,0 +1,94 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// NOTE: this is NOT to be #include-d normally. It's internal +// implementation detail of stacktrace.cc +// + +// Copyright (c) 2014, gperftools Contributors. +// 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: Aliaksey Kandratsenka +// +// based on stacktrace.cc and stacktrace_config.h by Sanjay Ghemawat +// and Paul Pluzhnikov from Google Inc + +#define SIS_CONCAT2(a, b) a##b +#define SIS_CONCAT(a, b) SIS_CONCAT2(a,b) + +#define SIS_STRINGIFY(a) SIS_STRINGIFY2(a) +#define SIS_STRINGIFY2(a) #a + +#define IS_STACK_FRAMES 0 +#define IS_WITH_CONTEXT 0 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackTrace_, GST_SUFFIX)(void **result, int max_depth, int skip_count) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 1 +#define IS_WITH_CONTEXT 0 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackFrames_, GST_SUFFIX)(void **result, int *sizes, int max_depth, int skip_count) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 0 +#define IS_WITH_CONTEXT 1 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX)(void **result, int max_depth, \ + int skip_count, const void *ucp) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +#define IS_STACK_FRAMES 1 +#define IS_WITH_CONTEXT 1 +#define GET_STACK_TRACE_OR_FRAMES \ + SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX)(void **result, int *sizes, int max_depth, \ + int skip_count, const void *ucp) +#include STACKTRACE_INL_HEADER +#undef IS_STACK_FRAMES +#undef IS_WITH_CONTEXT +#undef GET_STACK_TRACE_OR_FRAMES + +static GetStackImplementation SIS_CONCAT(impl__,GST_SUFFIX) = { + SIS_CONCAT(GetStackFrames_, GST_SUFFIX), + SIS_CONCAT(GetStackFramesWithContext_, GST_SUFFIX), + SIS_CONCAT(GetStackTrace_, GST_SUFFIX), + SIS_CONCAT(GetStackTraceWithContext_, GST_SUFFIX), + SIS_STRINGIFY(GST_SUFFIX) +}; + +#undef SIS_CONCAT2 +#undef SIS_CONCAT diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_instrument-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_instrument-inl.h new file mode 100644 index 000000000..c631765c8 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_instrument-inl.h @@ -0,0 +1,155 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2013, 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: Jean Lee +// based on gcc Code-Gen-Options "-finstrument-functions" listed in +// http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html . +// Should run configure with CXXFLAGS="-finstrument-functions". + +// This file is a backtrace implementation for systems : +// * The glibc implementation of backtrace() may cause a call to malloc, +// and cause a deadlock in HeapProfiler. +// * The libunwind implementation prints no backtrace. + +// The backtrace arrays are stored in "thread_back_trace" variable. +// Maybe to use thread local storage is better and should save memorys. + +#ifndef BASE_STACKTRACE_INSTRUMENT_INL_H_ +#define BASE_STACKTRACE_INSTRUMENT_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include +#include +#include +#include +#include "gperftools/stacktrace.h" + +#define gettid() syscall(__NR_gettid) +#ifndef __x86_64__ +#define MAX_THREAD (32768) +#else +#define MAX_THREAD (65536) +#endif +#define MAX_DEPTH (30) +#define ATTRIBUTE_NOINSTRUMENT __attribute__ ((no_instrument_function)) + +typedef struct { + int stack_depth; + void* frame[MAX_DEPTH]; +}BACK_TRACE; + +static BACK_TRACE thread_back_trace[MAX_THREAD]; +extern "C" { +void __cyg_profile_func_enter(void *func_address, + void *call_site) ATTRIBUTE_NOINSTRUMENT; +void __cyg_profile_func_enter(void *func_address, void *call_site) { + (void)func_address; + + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + backtrace->stack_depth = stack_depth + 1; + if ( stack_depth >= MAX_DEPTH ) { + return; + } + backtrace->frame[stack_depth] = call_site; +} + +void __cyg_profile_func_exit(void *func_address, + void *call_site) ATTRIBUTE_NOINSTRUMENT; +void __cyg_profile_func_exit(void *func_address, void *call_site) { + (void)func_address; + (void)call_site; + + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + backtrace->stack_depth = stack_depth - 1; + if ( stack_depth >= MAX_DEPTH ) { + return; + } + backtrace->frame[stack_depth] = 0; +} +} // extern "C" + +static int cyg_backtrace(void **buffer, int size) { + BACK_TRACE* backtrace = thread_back_trace + gettid(); + int stack_depth = backtrace->stack_depth; + if ( stack_depth >= MAX_DEPTH ) { + stack_depth = MAX_DEPTH; + } + int nSize = (size > stack_depth) ? stack_depth : size; + for (int i = 0; i < nSize; i++) { + buffer[i] = backtrace->frame[nSize - i - 1]; + } + + return nSize; +} + +#endif // BASE_STACKTRACE_INSTRUMENT_INL_H_ + + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + static const int kStackLength = 64; + void * stack[kStackLength]; + int size; + memset(stack, 0, sizeof(stack)); + + size = cyg_backtrace(stack, kStackLength); + skip_count += 2; // we want to skip the current and parent frame as well + int result_count = size - skip_count; + if (result_count < 0) + result_count = 0; + if (result_count > max_depth) + result_count = max_depth; + for (int i = 0; i < result_count; i++) + result[i] = stack[i + skip_count]; + +#if IS_STACK_FRAMES + // No implementation for finding out the stack frame sizes yet. + memset(sizes, 0, sizeof(*sizes) * result_count); +#endif + + return result_count; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libgcc-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libgcc-inl.h new file mode 100644 index 000000000..ce9cf5196 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libgcc-inl.h @@ -0,0 +1,111 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2016, gperftools Contributors +// 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. + +// This file implements backtrace capturing via libgcc's +// _Unwind_Backtrace. This generally works almost always. It will fail +// sometimes when we're trying to capture backtrace from signal +// handler (i.e. in cpu profiler) while some C++ code is throwing +// exception. + +#ifndef BASE_STACKTRACE_LIBGCC_INL_H_ +#define BASE_STACKTRACE_LIBGCC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +extern "C" { +#include +#include // for memset() +} + +#include + +#include "gperftools/stacktrace.h" + +struct libgcc_backtrace_data { + void **array; + int skip; + int pos; + int limit; +}; + +static _Unwind_Reason_Code libgcc_backtrace_helper(struct _Unwind_Context *ctx, + void *_data) { + libgcc_backtrace_data *data = + reinterpret_cast(_data); + + if (data->skip > 0) { + data->skip--; + return _URC_NO_REASON; + } + + if (data->pos < data->limit) { + void *ip = reinterpret_cast(_Unwind_GetIP(ctx));; + data->array[data->pos++] = ip; + } + + return _URC_NO_REASON; +} + +#endif // BASE_STACKTRACE_LIBGCC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + libgcc_backtrace_data data; + data.array = result; + // we're also skipping current and parent's frame + data.skip = skip_count + 2; + data.pos = 0; + data.limit = max_depth; + + _Unwind_Backtrace(libgcc_backtrace_helper, &data); + + if (data.pos > 1 && data.array[data.pos - 1] == NULL) + --data.pos; + +#if IS_STACK_FRAMES + // No implementation for finding out the stack frame sizes. + memset(sizes, 0, sizeof(*sizes) * data.pos); +#endif + + return data.pos; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libunwind-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libunwind-inl.h new file mode 100644 index 000000000..6f361ecd3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_libunwind-inl.h @@ -0,0 +1,152 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Arun Sharma +// +// Produce stack trace using libunwind + +#ifndef BASE_STACKTRACE_LIBINWIND_INL_H_ +#define BASE_STACKTRACE_LIBINWIND_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +// We only need local unwinder. +#define UNW_LOCAL_ONLY + +extern "C" { +#include +#include // for memset() +#include +} +#include "gperftools/stacktrace.h" + +#include "base/basictypes.h" +#include "base/logging.h" + +// Sometimes, we can try to get a stack trace from within a stack +// trace, because libunwind can call mmap (maybe indirectly via an +// internal mmap based memory allocator), and that mmap gets trapped +// and causes a stack-trace request. If were to try to honor that +// recursive request, we'd end up with infinite recursion or deadlock. +// Luckily, it's safe to ignore those subsequent traces. In such +// cases, we return 0 to indicate the situation. +static __thread int recursive ATTR_INITIAL_EXEC; + +#if defined(TCMALLOC_ENABLE_UNWIND_FROM_UCONTEXT) && (defined(__i386__) || defined(__x86_64__)) && defined(__GNU_LIBRARY__) +#define BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT 1 +#endif + +#endif // BASE_STACKTRACE_LIBINWIND_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + void *ip; + int n = 0; + unw_cursor_t cursor; + unw_context_t uc; +#if IS_STACK_FRAMES + unw_word_t sp = 0, next_sp = 0; +#endif + + if (recursive) { + return 0; + } + ++recursive; + +#if (IS_WITH_CONTEXT && defined(BASE_STACKTRACE_UNW_CONTEXT_IS_UCONTEXT)) + if (ucp) { + uc = *(static_cast(const_cast(ucp))); + /* this is a bit weird. profiler.cc calls us with signal's ucontext + * yet passing us 2 as skip_count and essentially assuming we won't + * use ucontext. */ + /* In order to fix that I'm going to assume that if ucp is + * non-null we're asked to ignore skip_count in case we're + * able to use ucp */ + skip_count = 0; + } else { + unw_getcontext(&uc); + skip_count += 2; // Do not include current and parent frame + } +#else + unw_getcontext(&uc); + skip_count += 2; // Do not include current and parent frame +#endif + + int ret = unw_init_local(&cursor, &uc); + assert(ret >= 0); + + while (skip_count--) { + if (unw_step(&cursor) <= 0) { + goto out; + } +#if IS_STACK_FRAMES + if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp)) { + goto out; + } +#endif + } + + while (n < max_depth) { + if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) { + break; + } +#if IS_STACK_FRAMES + sizes[n] = 0; +#endif + result[n++] = ip; + if (unw_step(&cursor) <= 0) { + break; + } +#if IS_STACK_FRAMES + sp = next_sp; + if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp) , 0) { + break; + } + sizes[n - 1] = next_sp - sp; +#endif + } +out: + --recursive; + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-darwin-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-darwin-inl.h new file mode 100644 index 000000000..3f6c3670f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-darwin-inl.h @@ -0,0 +1,163 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// Produce stack trace. ABI documentation reference can be found at: +// * PowerPC32 ABI: https://www.power.org/documentation/ +// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/ +// * PowerPC64 ABI: +// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK + +#ifndef BASE_STACKTRACE_POWERPC_INL_H_ +#define BASE_STACKTRACE_POWERPC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include // for NULL +#include + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static void **NextStackFrame(void **old_sp) { + void **new_sp = (void **) *old_sp; + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) + && ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL; + } + if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; + return new_sp; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +void StacktracePowerPCDummyFunction() __attribute__((noinline)); +void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +#endif // BASE_STACKTRACE_POWERPC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +int GET_STACK_TRACE_OR_FRAMES { + void **sp; + // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther) + // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a + // different asm syntax. I don't know quite the best way to discriminate + // systems using the old as from the new one; I've gone with __APPLE__. + // TODO(csilvers): use autoconf instead, to look for 'as --version' == 1 or 2 +#ifdef __FreeBSD__ + __asm__ volatile ("mr %0,1" : "=r" (sp)); +#else + __asm__ volatile ("mr %0,r1" : "=r" (sp)); +#endif + + // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack + // entry that holds 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. While the compiler will always(?) set up LR for + // subroutine calls, it may not for leaf functions (such as this one). + // This routine forces the compiler (at least gcc) to push it anyway. + StacktracePowerPCDummyFunction(); + +#if IS_STACK_FRAMES + // Note we do *not* increment skip_count here for the SYSV ABI. If + // we did, the list of stack frames wouldn't properly match up with + // the list of return addresses. Note this means the top pc entry + // is probably bogus for linux/ppc (and other SYSV-ABI systems). +#else + // The LR save area is used by the callee, so the top entry is bogus. + skip_count++; +#endif + + int n = 0; + while (sp && n < max_depth) { + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few + // bogus entries in some rare cases). + void **next_sp = NextStackFrame(sp); + + if (skip_count > 0) { + skip_count--; + } else { + // PowerPC has 3 main ABIs, which say where in the stack the + // Link Register is. For DARWIN and AIX (used by apple and + // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc), + // it's in sp[1]. +#if defined(__PPC64__) + // This check is in case the compiler doesn't define _CALL_AIX/etc. + result[n] = *(sp+2); +#elif defined(__linux) + // This check is in case the compiler doesn't define _CALL_SYSV. + result[n] = *(sp+1); +#endif + +#if IS_STACK_FRAMES + if (next_sp > sp) { + sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + sp = next_sp; + } + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-inl.h new file mode 100644 index 000000000..124bc4e83 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-inl.h @@ -0,0 +1,176 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein +// +// 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 + +#ifndef BASE_STACKTRACE_POWERPC_INL_H_ +#define BASE_STACKTRACE_POWERPC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include // for NULL +#include + +struct layout_ppc { + struct layout_ppc *next; +#if defined(__APPLE__) || (defined(__linux) && defined(__PPC64__)) + long condition_register; +#endif + void *return_addr; +}; + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static layout_ppc *NextStackFrame(layout_ppc *current) { + uintptr_t old_sp = (uintptr_t)(current); + uintptr_t new_sp = (uintptr_t)(current->next); + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) + return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if (new_sp - old_sp > 100000) + return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) + return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) && (new_sp - old_sp > 1000000)) + return NULL; + } + if (new_sp & (sizeof(void *) - 1)) + return NULL; + return current->next; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +void StacktracePowerPCDummyFunction() __attribute__((noinline)); +void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +#endif // BASE_STACKTRACE_POWERPC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// Load instruction used on top-of-stack get. +#if defined(__PPC64__) || defined(__LP64__) +# define LOAD "ld" +#else +# define LOAD "lwz" +#endif + +#if defined(__linux__) && defined(__PPC__) +# define TOP_STACK "%0,0(1)" +#elif defined(__MACH__) && defined(__APPLE__) +// Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther) +// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a +// different asm syntax. I don't know quite the best way to discriminate +// systems using the old as from the new one; I've gone with __APPLE__. +// TODO(csilvers): use autoconf instead, to look for 'as --version' == 1 or 2 +# define TOP_STACK "%0,0(r1)" +#endif + + + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + layout_ppc *current; + int n; + + // Force GCC to spill LR. + asm volatile ("" : "=l"(current)); + + // Get the address on top-of-stack + asm volatile (LOAD " " TOP_STACK : "=r"(current)); + + StacktracePowerPCDummyFunction(); + + n = 0; + skip_count++; // skip parent's frame due to indirection in + // stacktrace.cc + while (current && n < max_depth) { + + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few + // bogus entries in some rare cases). + layout_ppc *next = NextStackFrame(current); + if (skip_count > 0) { + skip_count--; + } else { + result[n] = current->return_addr; +#if IS_STACK_FRAMES + if (next > current) { + sizes[n] = (uintptr_t)next - (uintptr_t)current; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + current = next; + } + + // It's possible the second-last stack frame can't return + // (that is, it's __libc_start_main), in which case + // the CRT startup code will have set its LR to 'NULL'. + if (n > 0 && result[n-1] == NULL) + n--; + + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-linux-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-linux-inl.h new file mode 100644 index 000000000..a301a46ad --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_powerpc-linux-inl.h @@ -0,0 +1,231 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein +// +// Produce stack trace. ABI documentation reference can be found at: +// * PowerPC32 ABI: https://www.power.org/documentation/ +// power-architecture-32-bit-abi-supplement-1-0-embeddedlinuxunified/ +// * PowerPC64 ABI: +// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK + +#ifndef BASE_STACKTRACE_POWERPC_INL_H_ +#define BASE_STACKTRACE_POWERPC_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include // for uintptr_t +#include // for NULL +#include // for siginfo_t +#include +#include + +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include // for ucontext_t +#endif + +// PowerPC64 Little Endian follows BE wrt. backchain, condition register, +// and LR save area, so no need to adjust the reading struct. +struct layout_ppc { + struct layout_ppc *next; +#ifdef __PPC64__ + long condition_register; +#endif + void *return_addr; +}; + +// Signal callbacks are handled by the vDSO symbol: +// +// * PowerPC64 Linux (arch/powerpc/kernel/vdso64/sigtramp.S): +// __kernel_sigtramp_rt64 +// * PowerPC32 Linux (arch/powerpc/kernel/vdso32/sigtramp.S): +// __kernel_sigtramp32 +// __kernel_sigtramp_rt32 +// +// So a backtrace may need to specially handling if the symbol readed is +// the signal trampoline. + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static layout_ppc *NextStackFrame(layout_ppc *current) { + uintptr_t old_sp = (uintptr_t)(current); + uintptr_t new_sp = (uintptr_t)(current->next); + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) + return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if (new_sp - old_sp > 100000) + return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) + return NULL; + // And allow frames upto about 1MB. + if ((new_sp > old_sp) && (new_sp - old_sp > 1000000)) + return NULL; + } + if (new_sp & (sizeof(void *) - 1)) + return NULL; + return current->next; +} + +// This ensures that GetStackTrace stes up the Link Register properly. +void StacktracePowerPCDummyFunction() __attribute__((noinline)); +void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +#endif // BASE_STACKTRACE_POWERPC_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// Load instruction used on top-of-stack get. +#if defined(__PPC64__) || defined(__LP64__) +# define LOAD "ld" +#else +# define LOAD "lwz" +#endif + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) +static int GET_STACK_TRACE_OR_FRAMES { + layout_ppc *current; + int n; + + // Get the address on top-of-stack + current = reinterpret_cast (__builtin_frame_address (0)); + // And ignore the current symbol + current = current->next; + + StacktracePowerPCDummyFunction(); + + n = 0; + skip_count++; // skip parent's frame due to indirection in + // stacktrace.cc + + base::VDSOSupport vdso; + base::ElfMemImage::SymbolInfo rt_sigreturn_symbol_info; +#ifdef __PPC64__ + const void *sigtramp64_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp_rt64", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp64_vdso = rt_sigreturn_symbol_info.address; +#else + const void *sigtramp32_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp32", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp32_vdso = rt_sigreturn_symbol_info.address; + const void *sigtramp32_rt_vdso = 0; + if (vdso.LookupSymbol("__kernel_sigtramp_rt32", "LINUX_2.6.15", STT_NOTYPE, + &rt_sigreturn_symbol_info)) + sigtramp32_rt_vdso = rt_sigreturn_symbol_info.address; +#endif + + while (current && n < max_depth) { + + // The GetStackFrames routine is called when we are in some + // informational context (the failure signal handler for example). + // Use the non-strict unwinding rules to produce a stack trace + // that is as complete as possible (even if it contains a few + // bogus entries in some rare cases). + layout_ppc *next = NextStackFrame(current); + if (skip_count > 0) { + skip_count--; + } else { + result[n] = current->return_addr; +#ifdef __PPC64__ + if (sigtramp64_vdso && (sigtramp64_vdso == current->return_addr)) { + struct signal_frame_64 { + char dummy[128]; + ucontext_t uc; + // We don't care about the rest, since the IP value is at 'uc' field. + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP]; + } +#else + if (sigtramp32_vdso && (sigtramp32_vdso == current->return_addr)) { + struct signal_frame_32 { + char dummy[64]; + struct sigcontext sctx; + mcontext_t mctx; + // We don't care about the rest, since IP value is at 'mctx' field. + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->mctx.gregs[PT_NIP]; + } else if (sigtramp32_rt_vdso && (sigtramp32_rt_vdso == current->return_addr)) { + struct rt_signal_frame_32 { + char dummy[64 + 16]; + siginfo_t info; + ucontext_t uc; + // We don't care about the rest, since IP value is at 'uc' field.A + } *sigframe = reinterpret_cast(current); + result[n] = (void*) sigframe->uc.uc_mcontext.uc_regs->gregs[PT_NIP]; + } +#endif + +#if IS_STACK_FRAMES + if (next > current) { + sizes[n] = (uintptr_t)next - (uintptr_t)current; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + current = next; + } + + // It's possible the second-last stack frame can't return + // (that is, it's __libc_start_main), in which case + // the CRT startup code will have set its LR to 'NULL'. + if (n > 0 && result[n-1] == NULL) + n--; + + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_win32-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_win32-inl.h new file mode 100644 index 000000000..663e9a5bf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_win32-inl.h @@ -0,0 +1,107 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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. +// +// --- +// Produces a stack trace for Windows. Normally, one could use +// stacktrace_x86-inl.h or stacktrace_x86_64-inl.h -- and indeed, that +// should work for binaries compiled using MSVC in "debug" mode. +// However, in "release" mode, Windows uses frame-pointer +// optimization, which makes getting a stack trace very difficult. +// +// There are several approaches one can take. One is to use Windows +// intrinsics like StackWalk64. These can work, but have restrictions +// on how successful they can be. Another attempt is to write a +// version of stacktrace_x86-inl.h that has heuristic support for +// dealing with FPO, similar to what WinDbg does (see +// http://www.nynaeve.net/?p=97). +// +// The solution we've ended up doing is to call the undocumented +// windows function RtlCaptureStackBackTrace, which probably doesn't +// work with FPO but at least is fast, and doesn't require a symbol +// server. +// +// This code is inspired by a patch from David Vitek: +// http://code.google.com/p/gperftools/issues/detail?id=83 + +#ifndef BASE_STACKTRACE_WIN32_INL_H_ +#define BASE_STACKTRACE_WIN32_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include "config.h" +#include // for GetProcAddress and GetModuleHandle +#include + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +// Load the function we need at static init time, where we don't have +// to worry about someone else holding the loader's lock. +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +static int GetStackTrace_win32(void** result, int max_depth, + int skip_count) { + if (!RtlCaptureStackBackTrace_fn) { + // TODO(csilvers): should we log an error here? + return 0; // can't find a stacktrace with no function to call + } + return (int)RtlCaptureStackBackTrace_fn(skip_count + 3, max_depth, + result, 0); +} + +static int not_implemented(void) { + assert(0 == "Not yet implemented"); + return 0; +} + +static int GetStackFrames_win32(void** /* pcs */, + int* /* sizes */, + int /* max_depth */, + int /* skip_count */) { + return not_implemented(); +} + +static int GetStackFramesWithContext_win32(void** result, int* sizes, int max_depth, + int skip_count, const void *uc) { + return not_implemented(); +} + +static int GetStackTraceWithContext_win32(void** result, int max_depth, + int skip_count, const void *uc) { + return not_implemented(); +} + + +#endif // BASE_STACKTRACE_WIN32_INL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/stacktrace_x86-inl.h b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_x86-inl.h new file mode 100644 index 000000000..46eb5d82d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/stacktrace_x86-inl.h @@ -0,0 +1,354 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Produce stack trace + +#ifndef BASE_STACKTRACE_X86_INL_H_ +#define BASE_STACKTRACE_X86_INL_H_ +// Note: this file is included into stacktrace.cc more than once. +// Anything that should only be defined once should be here: + +#include "config.h" +#include // for NULL +#include +#if defined(HAVE_SYS_UCONTEXT_H) +#include +#elif defined(HAVE_UCONTEXT_H) +#include // for ucontext_t +#elif defined(HAVE_CYGWIN_SIGNAL_H) +// cygwin/signal.h has a buglet where it uses pthread_attr_t without +// #including itself. So we have to do it. +# ifdef HAVE_PTHREAD +# include +# endif +#include +typedef ucontext ucontext_t; +#endif +#ifdef HAVE_STDINT_H +#include // for uintptr_t +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_MMAP +#include // for msync +#include "base/vdso_support.h" +#endif + +#include "gperftools/stacktrace.h" + +#if defined(__linux__) && defined(__i386__) && defined(__ELF__) && defined(HAVE_MMAP) +// Count "push %reg" instructions in VDSO __kernel_vsyscall(), +// preceding "syscall" or "sysenter". +// If __kernel_vsyscall uses frame pointer, answer 0. +// +// kMaxBytes tells how many instruction bytes of __kernel_vsyscall +// to analyze before giving up. Up to kMaxBytes+1 bytes of +// instructions could be accessed. +// +// Here are known __kernel_vsyscall instruction sequences: +// +// SYSENTER (linux-2.6.26/arch/x86/vdso/vdso32/sysenter.S). +// Used on Intel. +// 0xffffe400 <__kernel_vsyscall+0>: push %ecx +// 0xffffe401 <__kernel_vsyscall+1>: push %edx +// 0xffffe402 <__kernel_vsyscall+2>: push %ebp +// 0xffffe403 <__kernel_vsyscall+3>: mov %esp,%ebp +// 0xffffe405 <__kernel_vsyscall+5>: sysenter +// +// SYSCALL (see linux-2.6.26/arch/x86/vdso/vdso32/syscall.S). +// Used on AMD. +// 0xffffe400 <__kernel_vsyscall+0>: push %ebp +// 0xffffe401 <__kernel_vsyscall+1>: mov %ecx,%ebp +// 0xffffe403 <__kernel_vsyscall+3>: syscall +// +// i386 (see linux-2.6.26/arch/x86/vdso/vdso32/int80.S) +// 0xffffe400 <__kernel_vsyscall+0>: int $0x80 +// 0xffffe401 <__kernel_vsyscall+1>: ret +// +static const int kMaxBytes = 10; + +// We use assert()s instead of DCHECK()s -- this is too low level +// for DCHECK(). + +static int CountPushInstructions(const unsigned char *const addr) { + int result = 0; + for (int i = 0; i < kMaxBytes; ++i) { + if (addr[i] == 0x89) { + // "mov reg,reg" + if (addr[i + 1] == 0xE5) { + // Found "mov %esp,%ebp". + return 0; + } + ++i; // Skip register encoding byte. + } else if (addr[i] == 0x0F && + (addr[i + 1] == 0x34 || addr[i + 1] == 0x05)) { + // Found "sysenter" or "syscall". + return result; + } else if ((addr[i] & 0xF0) == 0x50) { + // Found "push %reg". + ++result; + } else if (addr[i] == 0xCD && addr[i + 1] == 0x80) { + // Found "int $0x80" + assert(result == 0); + return 0; + } else { + // Unexpected instruction. + assert(0 == "unexpected instruction in __kernel_vsyscall"); + return 0; + } + } + // Unexpected: didn't find SYSENTER or SYSCALL in + // [__kernel_vsyscall, __kernel_vsyscall + kMaxBytes) interval. + assert(0 == "did not find SYSENTER or SYSCALL in __kernel_vsyscall"); + return 0; +} +#endif + +// Given a pointer to a stack frame, locate and return the calling +// stackframe, or return NULL if no stackframe can be found. Perform sanity +// checks (the strictness of which is controlled by the boolean parameter +// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. +template +static void **NextStackFrame(void **old_sp, const void *uc) { + void **new_sp = (void **) *old_sp; + +#if defined(__linux__) && defined(__i386__) && defined(HAVE_VDSO_SUPPORT) + if (WITH_CONTEXT && uc != NULL) { + // How many "push %reg" instructions are there at __kernel_vsyscall? + // This is constant for a given kernel and processor, so compute + // it only once. + static int num_push_instructions = -1; // Sentinel: not computed yet. + // Initialize with sentinel value: __kernel_rt_sigreturn can not possibly + // be there. + static const unsigned char *kernel_rt_sigreturn_address = NULL; + static const unsigned char *kernel_vsyscall_address = NULL; + if (num_push_instructions == -1) { + base::VDSOSupport vdso; + if (vdso.IsPresent()) { + base::VDSOSupport::SymbolInfo rt_sigreturn_symbol_info; + base::VDSOSupport::SymbolInfo vsyscall_symbol_info; + if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.5", + STT_FUNC, &rt_sigreturn_symbol_info) || + !vdso.LookupSymbol("__kernel_vsyscall", "LINUX_2.5", + STT_FUNC, &vsyscall_symbol_info) || + rt_sigreturn_symbol_info.address == NULL || + vsyscall_symbol_info.address == NULL) { + // Unexpected: 32-bit VDSO is present, yet one of the expected + // symbols is missing or NULL. + assert(0 == "VDSO is present, but doesn't have expected symbols"); + num_push_instructions = 0; + } else { + kernel_rt_sigreturn_address = + reinterpret_cast( + rt_sigreturn_symbol_info.address); + kernel_vsyscall_address = + reinterpret_cast( + vsyscall_symbol_info.address); + num_push_instructions = + CountPushInstructions(kernel_vsyscall_address); + } + } else { + num_push_instructions = 0; + } + } + if (num_push_instructions != 0 && kernel_rt_sigreturn_address != NULL && + old_sp[1] == kernel_rt_sigreturn_address) { + const ucontext_t *ucv = static_cast(uc); + // This kernel does not use frame pointer in its VDSO code, + // and so %ebp is not suitable for unwinding. + void **const reg_ebp = + reinterpret_cast(ucv->uc_mcontext.gregs[REG_EBP]); + const unsigned char *const reg_eip = + reinterpret_cast(ucv->uc_mcontext.gregs[REG_EIP]); + if (new_sp == reg_ebp && + kernel_vsyscall_address <= reg_eip && + reg_eip - kernel_vsyscall_address < kMaxBytes) { + // We "stepped up" to __kernel_vsyscall, but %ebp is not usable. + // Restore from 'ucv' instead. + void **const reg_esp = + reinterpret_cast(ucv->uc_mcontext.gregs[REG_ESP]); + // Check that alleged %esp is not NULL and is reasonably aligned. + if (reg_esp && + ((uintptr_t)reg_esp & (sizeof(reg_esp) - 1)) == 0) { + // Check that alleged %esp is actually readable. This is to prevent + // "double fault" in case we hit the first fault due to e.g. stack + // corruption. + // + // page_size is linker-initalized to avoid async-unsafe locking + // that GCC would otherwise insert (__cxa_guard_acquire etc). + static int page_size; + if (page_size == 0) { + // First time through. + page_size = getpagesize(); + } + void *const reg_esp_aligned = + reinterpret_cast( + (uintptr_t)(reg_esp + num_push_instructions - 1) & + ~(page_size - 1)); + if (msync(reg_esp_aligned, page_size, MS_ASYNC) == 0) { + // Alleged %esp is readable, use it for further unwinding. + new_sp = reinterpret_cast( + reg_esp[num_push_instructions - 1]); + } + } + } + } + } +#endif + + // Check that the transition from frame pointer old_sp to frame + // pointer new_sp isn't clearly bogus + if (STRICT_UNWINDING) { + // With the stack growing downwards, older stack frame must be + // at a greater address that the current one. + if (new_sp <= old_sp) return NULL; + // Assume stack frames larger than 100,000 bytes are bogus. + if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL; + } else { + // In the non-strict mode, allow discontiguous stack frames. + // (alternate-signal-stacks for example). + if (new_sp == old_sp) return NULL; + if (new_sp > old_sp) { + // And allow frames upto about 1MB. + const uintptr_t delta = (uintptr_t)new_sp - (uintptr_t)old_sp; + const uintptr_t acceptable_delta = 1000000; + if (delta > acceptable_delta) { + return NULL; + } + } + } + if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL; +#ifdef __i386__ + // On 64-bit machines, the stack pointer can be very close to + // 0xffffffff, so we explicitly check for a pointer into the + // last two pages in the address space + if ((uintptr_t)new_sp >= 0xffffe000) return NULL; +#endif +#ifdef HAVE_MMAP + if (!STRICT_UNWINDING) { + // Lax sanity checks cause a crash on AMD-based machines with + // VDSO-enabled kernels. + // Make an extra sanity check to insure new_sp is readable. + // Note: NextStackFrame() is only called while the program + // is already on its last leg, so it's ok to be slow here. + static int page_size = getpagesize(); + void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1)); + if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1) + return NULL; + } +#endif + return new_sp; +} + +#endif // BASE_STACKTRACE_X86_INL_H_ + +// Note: this part of the file is included several times. +// Do not put globals below. + +// The following 4 functions are generated from the code below: +// GetStack{Trace,Frames}() +// GetStack{Trace,Frames}WithContext() +// +// These functions take the following args: +// void** result: the stack-trace, as an array +// int* sizes: the size of each stack frame, as an array +// (GetStackFrames* only) +// int max_depth: the size of the result (and sizes) array(s) +// int skip_count: how many stack pointers to skip before storing in result +// void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only) + +static int GET_STACK_TRACE_OR_FRAMES { + void **sp; +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__ + // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8. + // It's always correct on llvm, and the techniques below aren't (in + // particular, llvm-gcc will make a copy of pcs, so it's not in sp[2]), + // so we also prefer __builtin_frame_address when running under llvm. + sp = reinterpret_cast(__builtin_frame_address(0)); +#elif defined(__i386__) + // Stack frame format: + // sp[0] pointer to previous frame + // sp[1] caller address + // sp[2] first argument + // ... + // NOTE: This will break under llvm, since result is a copy and not in sp[2] + sp = (void **)&result - 2; +#elif defined(__x86_64__) + unsigned long rbp; + // Move the value of the register %rbp into the local variable rbp. + // We need 'volatile' to prevent this instruction from getting moved + // around during optimization to before function prologue is done. + // An alternative way to achieve this + // would be (before this __asm__ instruction) to call Noop() defined as + // static void Noop() __attribute__ ((noinline)); // prevent inlining + // static void Noop() { asm(""); } // prevent optimizing-away + __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp)); + // Arguments are passed in registers on x86-64, so we can't just + // offset from &result + sp = (void **) rbp; +#else +# error Using stacktrace_x86-inl.h on a non x86 architecture! +#endif + + skip_count++; // skip parent's frame due to indirection in stacktrace.cc + + int n = 0; + while (sp && n < max_depth) { + if (*(sp+1) == reinterpret_cast(0)) { + // In 64-bit code, we often see a frame that + // points to itself and has a return address of 0. + break; + } +#if !IS_WITH_CONTEXT + const void *const ucp = NULL; +#endif + void **next_sp = NextStackFrame(sp, ucp); + if (skip_count > 0) { + skip_count--; + } else { + result[n] = *(sp+1); +#if IS_STACK_FRAMES + if (next_sp > sp) { + sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; + } else { + // A frame-size of 0 is used to indicate unknown frame size. + sizes[n] = 0; + } +#endif + n++; + } + sp = next_sp; + } + return n; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/static_vars.cc b/trunk/3rdparty/gperftools-2-fit/src/static_vars.cc new file mode 100644 index 000000000..fef6ed1af --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/static_vars.cc @@ -0,0 +1,152 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Ken Ashcraft + +#include +#include "static_vars.h" +#include // for NULL +#include // for operator new +#ifdef HAVE_PTHREAD +#include // for pthread_atfork +#endif +#include "internal_logging.h" // for CHECK_CONDITION +#include "common.h" +#include "sampler.h" // for Sampler +#include "getenv_safe.h" // TCMallocGetenvSafe +#include "base/googleinit.h" +#include "maybe_threads.h" + +namespace tcmalloc { + +#if defined(HAVE_FORK) && defined(HAVE_PTHREAD) +// These following two functions are registered via pthread_atfork to make +// sure the central_cache locks remain in a consisten state in the forked +// version of the thread. + +void CentralCacheLockAll() NO_THREAD_SAFETY_ANALYSIS +{ + Static::pageheap_lock()->Lock(); + for (int i = 0; i < Static::num_size_classes(); ++i) + Static::central_cache()[i].Lock(); +} + +void CentralCacheUnlockAll() NO_THREAD_SAFETY_ANALYSIS +{ + for (int i = 0; i < Static::num_size_classes(); ++i) + Static::central_cache()[i].Unlock(); + Static::pageheap_lock()->Unlock(); +} +#endif + +bool Static::inited_; +SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED); +SizeMap Static::sizemap_; +CentralFreeListPadded Static::central_cache_[kClassSizesMax]; +PageHeapAllocator Static::span_allocator_; +PageHeapAllocator Static::stacktrace_allocator_; +Span Static::sampled_objects_; +StackTrace* Static::growth_stacks_ = NULL; +Static::PageHeapStorage Static::pageheap_; + +void Static::InitStaticVars() { + sizemap_.Init(); + span_allocator_.Init(); + span_allocator_.New(); // Reduce cache conflicts + span_allocator_.New(); // Reduce cache conflicts + stacktrace_allocator_.Init(); + // Do a bit of sanitizing: make sure central_cache is aligned properly + CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0); + for (int i = 0; i < num_size_classes(); ++i) { + central_cache_[i].Init(i); + } + + new (&pageheap_.memory) PageHeap; + +#if defined(ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT) + const bool kDefaultAggressiveDecommit = true; +#else + const bool kDefaultAggressiveDecommit = false; +#endif + + + bool aggressive_decommit = + tcmalloc::commandlineflags::StringToBool( + TCMallocGetenvSafe("TCMALLOC_AGGRESSIVE_DECOMMIT"), + kDefaultAggressiveDecommit); + + pageheap()->SetAggressiveDecommit(aggressive_decommit); + + inited_ = true; + + DLL_Init(&sampled_objects_); +} + +void Static::InitLateMaybeRecursive() { +#if defined(HAVE_FORK) && defined(HAVE_PTHREAD) \ + && !defined(__APPLE__) && !defined(TCMALLOC_NO_ATFORK) + // OSX has it's own way of handling atfork in malloc (see + // libc_override_osx.h). + // + // For other OSes we do pthread_atfork even if standard seemingly + // discourages pthread_atfork, asking apps to do only + // async-signal-safe calls between fork and exec. + // + // We're deliberately attempting to register atfork handlers as part + // of malloc initialization. So very early. This ensures that our + // handler is called last and that means fork will try to grab + // tcmalloc locks last avoiding possible issues with many other + // locks that are held around calls to malloc. I.e. if we don't do + // that, fork() grabbing malloc lock before such other lock would be + // prone to deadlock, if some other thread holds other lock and + // calls malloc. + // + // We still leave some way of disabling it via + // -DTCMALLOC_NO_ATFORK. It looks like on glibc even with fully + // static binaries malloc is really initialized very early. But I + // can see how combination of static linking and other libc-s could + // be less fortunate and allow some early app constructors to run + // before malloc is ever called. + + perftools_pthread_atfork( + CentralCacheLockAll, // parent calls before fork + CentralCacheUnlockAll, // parent calls after fork + CentralCacheUnlockAll); // child calls after fork +#endif + +#ifndef NDEBUG + // pthread_atfork above may malloc sometimes. Lets ensure we test + // that malloc works from here. + free(malloc(1)); +#endif +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/static_vars.h b/trunk/3rdparty/gperftools-2-fit/src/static_vars.h new file mode 100644 index 000000000..bef018088 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/static_vars.h @@ -0,0 +1,126 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Ken Ashcraft +// +// Static variables shared by multiple classes. + +#ifndef TCMALLOC_STATIC_VARS_H_ +#define TCMALLOC_STATIC_VARS_H_ + +#include +#include "base/basictypes.h" +#include "base/spinlock.h" +#include "central_freelist.h" +#include "common.h" +#include "page_heap.h" +#include "page_heap_allocator.h" +#include "span.h" +#include "stack_trace_table.h" + +namespace tcmalloc { + +class Static { + public: + // Linker initialized, so this lock can be accessed at any time. + static SpinLock* pageheap_lock() { return &pageheap_lock_; } + + // Must be called before calling any of the accessors below. + static void InitStaticVars(); + static void InitLateMaybeRecursive(); + + // Central cache -- an array of free-lists, one per size-class. + // We have a separate lock per free-list to reduce contention. + static CentralFreeListPadded* central_cache() { return central_cache_; } + + static SizeMap* sizemap() { return &sizemap_; } + + static unsigned num_size_classes() { return sizemap_.num_size_classes; } + + ////////////////////////////////////////////////////////////////////// + // In addition to the explicit initialization comment, the variables below + // must be protected by pageheap_lock. + + // Page-level allocator. + static PageHeap* pageheap() { return reinterpret_cast(&pageheap_.memory); } + + static PageHeapAllocator* span_allocator() { return &span_allocator_; } + + static PageHeapAllocator* stacktrace_allocator() { + return &stacktrace_allocator_; + } + + static StackTrace* growth_stacks() { return growth_stacks_; } + static void set_growth_stacks(StackTrace* s) { growth_stacks_ = s; } + + // State kept for sampled allocations (/pprof/heap support) + static Span* sampled_objects() { return &sampled_objects_; } + + // Check if InitStaticVars() has been run. + static bool IsInited() { return inited_; } + + private: + // some unit tests depend on this and link to static vars + // imperfectly. Thus we keep those unhidden for now. Thankfully + // they're not performance-critical. + /* ATTRIBUTE_HIDDEN */ static bool inited_; + /* ATTRIBUTE_HIDDEN */ static SpinLock pageheap_lock_; + + // These static variables require explicit initialization. We cannot + // count on their constructors to do any initialization because other + // static variables may try to allocate memory before these variables + // can run their constructors. + + ATTRIBUTE_HIDDEN static SizeMap sizemap_; + ATTRIBUTE_HIDDEN static CentralFreeListPadded central_cache_[kClassSizesMax]; + ATTRIBUTE_HIDDEN static PageHeapAllocator span_allocator_; + ATTRIBUTE_HIDDEN static PageHeapAllocator stacktrace_allocator_; + ATTRIBUTE_HIDDEN static Span sampled_objects_; + + // Linked list of stack traces recorded every time we allocated memory + // from the system. Useful for finding allocation sites that cause + // increase in the footprint of the system. The linked list pointer + // is stored in trace->stack[kMaxStackDepth-1]. + ATTRIBUTE_HIDDEN static StackTrace* growth_stacks_; + + // PageHeap uses a constructor for initialization. Like the members above, + // we can't depend on initialization order, so pageheap is new'd + // into this buffer. + union PageHeapStorage { + char memory[sizeof(PageHeap)]; + uintptr_t extra; // To force alignment + }; + ATTRIBUTE_HIDDEN static PageHeapStorage pageheap_; +}; + +} // namespace tcmalloc + +#endif // TCMALLOC_STATIC_VARS_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/symbolize.cc b/trunk/3rdparty/gperftools-2-fit/src/symbolize.cc new file mode 100644 index 000000000..8c94c18ff --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/symbolize.cc @@ -0,0 +1,298 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2009, 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 forks out to pprof to do the actual symbolizing. We might +// be better off writing our own in C++. + +#include "config.h" +#include "symbolize.h" +#include +#ifdef HAVE_UNISTD_H +#include // for write() +#endif +#ifdef HAVE_SYS_SOCKET_H +#include // for socketpair() -- needed by Symbolize +#endif +#ifdef HAVE_SYS_WAIT_H +#include // for wait() -- needed by Symbolize +#endif +#ifdef HAVE_POLL_H +#include +#endif +#ifdef __MACH__ +#include // for GetProgramInvocationName() +#include // for PATH_MAX +#endif +#if defined(__CYGWIN__) || defined(__CYGWIN32__) +#include // for get_osfhandle() +#endif +#include +#include "base/commandlineflags.h" +#include "base/logging.h" +#include "base/sysinfo.h" +#if defined(__FreeBSD__) +#include +#endif + +using std::string; +using tcmalloc::DumpProcSelfMaps; // from sysinfo.h + +// pprof may be used after destructors are +// called (since that's when leak-checking is done), so we make +// a more-permanent copy that won't ever get destroyed. +static char* get_pprof_path() { + static char* result = ([] () { + string pprof_string = EnvToString("PPROF_PATH", "pprof-symbolize"); + return strdup(pprof_string.c_str()); + })(); + + return result; +} + +// Returns NULL if we're on an OS where we can't get the invocation name. +// Using a static var is ok because we're not called from a thread. +static const char* GetProgramInvocationName() { +#if defined(HAVE_PROGRAM_INVOCATION_NAME) +#ifdef __UCLIBC__ + extern const char* program_invocation_name; // uclibc provides this +#else + extern char* program_invocation_name; // gcc provides this +#endif + return program_invocation_name; +#elif defined(__MACH__) + // We don't want to allocate memory for this since we may be + // calculating it when memory is corrupted. + static char program_invocation_name[PATH_MAX]; + if (program_invocation_name[0] == '\0') { // first time calculating + uint32_t length = sizeof(program_invocation_name); + if (_NSGetExecutablePath(program_invocation_name, &length)) + return NULL; + } + return program_invocation_name; +#elif defined(__FreeBSD__) + static char program_invocation_name[PATH_MAX]; + size_t len = sizeof(program_invocation_name); + static const int name[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + if (!sysctl(name, 4, program_invocation_name, &len, NULL, 0)) + return program_invocation_name; + return NULL; +#else + return NULL; // figure out a way to get argv[0] +#endif +} + +// Prints an error message when you can't run Symbolize(). +static void PrintError(const char* reason) { + RAW_LOG(ERROR, + "*** WARNING: Cannot convert addresses to symbols in output below.\n" + "*** Reason: %s\n" + "*** If you cannot fix this, try running pprof directly.\n", + reason); +} + +void SymbolTable::Add(const void* addr) { + symbolization_table_[addr] = ""; +} + +const char* SymbolTable::GetSymbol(const void* addr) { + return symbolization_table_[addr]; +} + +// Updates symbolization_table with the pointers to symbol names corresponding +// to its keys. The symbol names are stored in out, which is allocated and +// freed by the caller of this routine. +// Note that the forking/etc is not thread-safe or re-entrant. That's +// ok for the purpose we need -- reporting leaks detected by heap-checker +// -- but be careful if you decide to use this routine for other purposes. +// Returns number of symbols read on error. If can't symbolize, returns 0 +// and emits an error message about why. +int SymbolTable::Symbolize() { +#if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H) + PrintError("Perftools does not know how to call a sub-process on this O/S"); + return 0; +#else + const char* argv0 = GetProgramInvocationName(); + if (argv0 == NULL) { // can't call symbolize if we can't figure out our name + PrintError("Cannot figure out the name of this executable (argv0)"); + return 0; + } + if (access(get_pprof_path(), R_OK) != 0) { + PrintError("Cannot find 'pprof' (is PPROF_PATH set correctly?)"); + return 0; + } + + // All this work is to do two-way communication. ugh. + int *child_in = NULL; // file descriptors + int *child_out = NULL; // for now, we don't worry about child_err + int child_fds[5][2]; // socketpair may be called up to five times below + + // The client program may close its stdin and/or stdout and/or stderr + // thus allowing socketpair to reuse file descriptors 0, 1 or 2. + // In this case the communication between the forked processes may be broken + // if either the parent or the child tries to close or duplicate these + // descriptors. The loop below produces two pairs of file descriptors, each + // greater than 2 (stderr). + for (int i = 0; i < 5; i++) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_fds[i]) == -1) { + for (int j = 0; j < i; j++) { + close(child_fds[j][0]); + close(child_fds[j][1]); + PrintError("Cannot create a socket pair"); + } + return 0; + } else { + if ((child_fds[i][0] > 2) && (child_fds[i][1] > 2)) { + if (child_in == NULL) { + child_in = child_fds[i]; + } else { + child_out = child_fds[i]; + for (int j = 0; j < i; j++) { + if (child_fds[j] == child_in) continue; + close(child_fds[j][0]); + close(child_fds[j][1]); + } + break; + } + } + } + } + + switch (fork()) { + case -1: { // error + close(child_in[0]); + close(child_in[1]); + close(child_out[0]); + close(child_out[1]); + PrintError("Unknown error calling fork()"); + return 0; + } + case 0: { // child + close(child_in[1]); // child uses the 0's, parent uses the 1's + close(child_out[1]); // child uses the 0's, parent uses the 1's + close(0); + close(1); + if (dup2(child_in[0], 0) == -1) _exit(1); + if (dup2(child_out[0], 1) == -1) _exit(2); + // Unset vars that might cause trouble when we fork + unsetenv("CPUPROFILE"); + unsetenv("HEAPPROFILE"); + unsetenv("HEAPCHECK"); + unsetenv("PERFTOOLS_VERBOSE"); + execlp(get_pprof_path(), get_pprof_path(), + "--symbols", argv0, NULL); + _exit(3); // if execvp fails, it's bad news for us + } + default: { // parent + close(child_in[0]); // child uses the 0's, parent uses the 1's + close(child_out[0]); // child uses the 0's, parent uses the 1's +#ifdef HAVE_POLL_H + // Waiting for 1ms seems to give the OS time to notice any errors. + poll(0, 0, 1); + // For maximum safety, we check to make sure the execlp + // succeeded before trying to write. (Otherwise we'll get a + // SIGPIPE.) For systems without poll.h, we'll just skip this + // check, and trust that the user set PPROF_PATH correctly! + struct pollfd pfd = { child_in[1], POLLOUT, 0 }; + if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) || + (pfd.revents & (POLLHUP|POLLERR))) { + PrintError("Cannot run 'pprof' (is PPROF_PATH set correctly?)"); + return 0; + } +#endif +#if defined(__CYGWIN__) || defined(__CYGWIN32__) + // On cygwin, DumpProcSelfMaps() takes a HANDLE, not an fd. Convert. + const HANDLE symbols_handle = (HANDLE) get_osfhandle(child_in[1]); + DumpProcSelfMaps(symbols_handle); +#else + DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin +#endif + + // Allocate 24 bytes = ("0x" + 8 bytes + "\n" + overhead) for each + // address to feed to pprof. + const int kOutBufSize = 24 * symbolization_table_.size(); + char *pprof_buffer = new char[kOutBufSize]; + int written = 0; + for (SymbolMap::const_iterator iter = symbolization_table_.begin(); + iter != symbolization_table_.end(); ++iter) { + written += snprintf(pprof_buffer + written, kOutBufSize - written, + // pprof expects format to be 0xXXXXXX + "0x%" PRIxPTR "\n", reinterpret_cast(iter->first)); + } + write(child_in[1], pprof_buffer, strlen(pprof_buffer)); + close(child_in[1]); // that's all we need to write + delete[] pprof_buffer; + + const int kSymbolBufferSize = kSymbolSize * symbolization_table_.size(); + int total_bytes_read = 0; + delete[] symbol_buffer_; + symbol_buffer_ = new char[kSymbolBufferSize]; + memset(symbol_buffer_, '\0', kSymbolBufferSize); + while (1) { + int bytes_read = read(child_out[1], symbol_buffer_ + total_bytes_read, + kSymbolBufferSize - total_bytes_read); + if (bytes_read < 0) { + close(child_out[1]); + PrintError("Cannot read data from pprof"); + return 0; + } else if (bytes_read == 0) { + close(child_out[1]); + wait(NULL); + break; + } else { + total_bytes_read += bytes_read; + } + } + // We have successfully read the output of pprof into out. Make sure + // the last symbol is full (we can tell because it ends with a \n). + if (total_bytes_read == 0 || symbol_buffer_[total_bytes_read - 1] != '\n') + return 0; + // make the symbolization_table_ values point to the output vector + SymbolMap::iterator fill = symbolization_table_.begin(); + int num_symbols = 0; + const char *current_name = symbol_buffer_; + for (int i = 0; i < total_bytes_read; i++) { + if (symbol_buffer_[i] == '\n') { + fill->second = current_name; + symbol_buffer_[i] = '\0'; + current_name = symbol_buffer_ + i + 1; + fill++; + num_symbols++; + } + } + return num_symbols; + } + } + PrintError("Unkown error (should never occur!)"); + return 0; // shouldn't be reachable +#endif +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/symbolize.h b/trunk/3rdparty/gperftools-2-fit/src/symbolize.h new file mode 100644 index 000000000..aa0aa33a7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/symbolize.h @@ -0,0 +1,84 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2009, 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 + +#ifndef TCMALLOC_SYMBOLIZE_H_ +#define TCMALLOC_SYMBOLIZE_H_ + +#include "config.h" +#ifdef HAVE_STDINT_H +#include // for uintptr_t +#endif +#include // for NULL +#include + +using std::map; + +// SymbolTable encapsulates the address operations necessary for stack trace +// symbolization. A common use-case is to Add() the addresses from one or +// several stack traces to a table, call Symbolize() once and use GetSymbol() +// to get the symbol names for pretty-printing the stack traces. +class SymbolTable { + public: + SymbolTable() + : symbol_buffer_(NULL) {} + ~SymbolTable() { + delete[] symbol_buffer_; + } + + // Adds an address to the table. This may overwrite a currently known symbol + // name, so Add() should not generally be called after Symbolize(). + void Add(const void* addr); + + // Returns the symbol name for addr, if the given address was added before + // the last successful call to Symbolize(). Otherwise may return an empty + // c-string. + const char* GetSymbol(const void* addr); + + // Obtains the symbol names for the addresses stored in the table and returns + // the number of addresses actually symbolized. + int Symbolize(); + + private: + typedef map SymbolMap; + + // An average size of memory allocated for a stack trace symbol. + static const int kSymbolSize = 1024; + + // Map from addresses to symbol names. + SymbolMap symbolization_table_; + + // Pointer to the buffer that stores the symbol names. + char *symbol_buffer_; +}; + +#endif // TCMALLOC_SYMBOLIZE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/system-alloc.cc b/trunk/3rdparty/gperftools-2-fit/src/system-alloc.cc new file mode 100644 index 000000000..e84a5f1bf --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/system-alloc.cc @@ -0,0 +1,555 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat + +#include +#include // for EAGAIN, errno +#include // for open, O_RDWR +#include // for size_t, NULL, ptrdiff_t +#if defined HAVE_STDINT_H +#include // for uintptr_t, intptr_t +#elif defined HAVE_INTTYPES_H +#include +#else +#include +#endif +#ifdef HAVE_MMAP +#include // for munmap, mmap, MADV_DONTNEED, etc +#endif +#ifdef HAVE_UNISTD_H +#include // for sbrk, getpagesize, off_t +#endif +#include // for operator new +#include +#include "base/basictypes.h" +#include "base/commandlineflags.h" +#include "base/spinlock.h" // for SpinLockHolder, SpinLock, etc +#include "common.h" +#include "internal_logging.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 + +// Linux added support for MADV_FREE in 4.5 but we aren't ready to use it +// yet. Among other things, using compile-time detection leads to poor +// results when compiling on a system with MADV_FREE and running on a +// system without it. See https://github.com/gperftools/gperftools/issues/780. +#if defined(__linux__) && defined(MADV_FREE) && !defined(TCMALLOC_USE_MADV_FREE) +# undef MADV_FREE +#endif + +// 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. +#if !defined(MADV_FREE) && defined(MADV_DONTNEED) +# define MADV_FREE MADV_DONTNEED +#endif + +// Solaris has a bug where it doesn't declare madvise() for C++. +// http://www.opensolaris.org/jive/thread.jspa?threadID=21035&tstart=0 +#if defined(__sun) && defined(__SVR4) +# include // for caddr_t + extern "C" { extern int madvise(caddr_t, size_t, int); } +#endif + +// Set kDebugMode mode so that we can have use C++ conditionals +// instead of preprocessor conditionals. +#ifdef NDEBUG +static const bool kDebugMode = false; +#else +static const bool kDebugMode = true; +#endif + +// TODO(sanjay): Move the code below into the tcmalloc namespace +using tcmalloc::kLog; +using tcmalloc::Log; + +// Check that no bit is set at position ADDRESS_BITS or higher. +static bool CheckAddressBits(uintptr_t ptr) { + bool always_ok = (kAddressBits == 8 * sizeof(void*)); + // this is a bit insane but otherwise we get compiler warning about + // shifting right by word size even if this code is dead :( + int shift_bits = always_ok ? 0 : kAddressBits; + return always_ok || ((ptr >> shift_bits) == 0); +} + +COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*), + address_bits_larger_than_pointer_size); + +static SpinLock spinlock(SpinLock::LINKER_INITIALIZED); + +#if defined(HAVE_MMAP) || defined(MADV_FREE) +// Page size is initialized on demand (only needed for mmap-based allocators) +static size_t pagesize = 0; +#endif + +// The current system allocator +SysAllocator* tcmalloc_sys_alloc = NULL; + +// Number of bytes taken from system. +size_t TCMalloc_SystemTaken = 0; + +// Configuration parameters. +DEFINE_int32(malloc_devmem_start, + EnvToInt("TCMALLOC_DEVMEM_START", 0), + "Physical memory starting location in MB for /dev/mem allocation." + " Setting this to 0 disables /dev/mem allocation"); +DEFINE_int32(malloc_devmem_limit, + EnvToInt("TCMALLOC_DEVMEM_LIMIT", 0), + "Physical memory limit location in MB for /dev/mem allocation." + " Setting this to 0 means no limit."); +DEFINE_bool(malloc_skip_sbrk, + EnvToBool("TCMALLOC_SKIP_SBRK", false), + "Whether sbrk can be used to obtain memory."); +DEFINE_bool(malloc_skip_mmap, + EnvToBool("TCMALLOC_SKIP_MMAP", false), + "Whether mmap can be used to obtain memory."); +DEFINE_bool(malloc_disable_memory_release, + EnvToBool("TCMALLOC_DISABLE_MEMORY_RELEASE", false), + "Whether MADV_FREE/MADV_DONTNEED should be used" + " to return unused memory to the system."); + +// static allocators +class SbrkSysAllocator : public SysAllocator { +public: + SbrkSysAllocator() : SysAllocator() { + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); +}; +static union { + char buf[sizeof(SbrkSysAllocator)]; + void *ptr; +} sbrk_space; + +class MmapSysAllocator : public SysAllocator { +public: + MmapSysAllocator() : SysAllocator() { + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); +}; +static union { + char buf[sizeof(MmapSysAllocator)]; + void *ptr; +} mmap_space; + +class DevMemSysAllocator : public SysAllocator { +public: + DevMemSysAllocator() : SysAllocator() { + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); +}; + +class DefaultSysAllocator : public SysAllocator { + public: + DefaultSysAllocator() : SysAllocator() { + for (int i = 0; i < kMaxAllocators; i++) { + failed_[i] = true; + allocs_[i] = NULL; + names_[i] = NULL; + } + } + void SetChildAllocator(SysAllocator* alloc, unsigned int index, + const char* name) { + if (index < kMaxAllocators && alloc != NULL) { + allocs_[index] = alloc; + failed_[index] = false; + names_[index] = name; + } + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); + + private: + static const int kMaxAllocators = 2; + bool failed_[kMaxAllocators]; + SysAllocator* allocs_[kMaxAllocators]; + const char* names_[kMaxAllocators]; +}; +static union { + char buf[sizeof(DefaultSysAllocator)]; + void *ptr; +} default_space; +static const char sbrk_name[] = "SbrkSysAllocator"; +static const char mmap_name[] = "MmapSysAllocator"; + + +void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { +#if !defined(HAVE_SBRK) || defined(__UCLIBC__) + return NULL; +#else + // Check if we should use sbrk allocation. + // FLAGS_malloc_skip_sbrk starts out as false (its uninitialized + // state) and eventually gets initialized to the specified value. Note + // that this code runs for a while before the flags are initialized. + // That means that even if this flag is set to true, some (initial) + // memory will be allocated with sbrk before the flag takes effect. + if (FLAGS_malloc_skip_sbrk) { + return NULL; + } + + // sbrk will release memory if passed a negative number, so we do + // a strict check here + if (static_cast(size + alignment) < 0) return NULL; + + // This doesn't overflow because TCMalloc_SystemAlloc has already + // tested for overflow at the alignment boundary. + size = ((size + alignment - 1) / alignment) * alignment; + + // "actual_size" indicates that the bytes from the returned pointer + // p up to and including (p + actual_size - 1) have been allocated. + if (actual_size) { + *actual_size = size; + } + + // Check that we we're not asking for so much more memory that we'd + // wrap around the end of the virtual address space. (This seems + // like something sbrk() should check for us, and indeed opensolaris + // does, but glibc does not: + // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/sys/sbrk.c?a=true + // http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev=1.1.2.1&content-type=text/plain&cvsroot=glibc + // Without this check, sbrk may succeed when it ought to fail.) + if (reinterpret_cast(sbrk(0)) + size < size) { + return NULL; + } + + void* result = sbrk(size); + if (result == reinterpret_cast(-1)) { + return NULL; + } + + // Is it aligned? + uintptr_t ptr = reinterpret_cast(result); + if ((ptr & (alignment-1)) == 0) return result; + + // Try to get more memory for alignment + size_t extra = alignment - (ptr & (alignment-1)); + void* r2 = sbrk(extra); + if (reinterpret_cast(r2) == (ptr + size)) { + // Contiguous with previous result + return reinterpret_cast(ptr + extra); + } + + // Give up and ask for "size + alignment - 1" bytes so + // that we can find an aligned region within it. + result = sbrk(size + alignment - 1); + if (result == reinterpret_cast(-1)) { + return NULL; + } + ptr = reinterpret_cast(result); + if ((ptr & (alignment-1)) != 0) { + ptr += alignment - (ptr & (alignment-1)); + } + return reinterpret_cast(ptr); +#endif // HAVE_SBRK +} + +void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { +#ifndef HAVE_MMAP + return NULL; +#else + // Check if we should use mmap allocation. + // FLAGS_malloc_skip_mmap starts out as false (its uninitialized + // state) and eventually gets initialized to the specified value. Note + // that this code runs for a while before the flags are initialized. + // Chances are we never get here before the flags are initialized since + // sbrk is used until the heap is exhausted (before mmap is used). + if (FLAGS_malloc_skip_mmap) { + return NULL; + } + + // Enforce page alignment + if (pagesize == 0) pagesize = getpagesize(); + if (alignment < pagesize) alignment = pagesize; + size_t aligned_size = ((size + alignment - 1) / alignment) * alignment; + if (aligned_size < size) { + return NULL; + } + size = aligned_size; + + // "actual_size" indicates that the bytes from the returned pointer + // p up to and including (p + actual_size - 1) have been allocated. + if (actual_size) { + *actual_size = size; + } + + // Ask for extra memory if alignment > pagesize + size_t extra = 0; + if (alignment > pagesize) { + extra = alignment - pagesize; + } + + // Note: size + extra does not overflow since: + // size + alignment < (1<(MAP_FAILED)) { + return NULL; + } + + // Adjust the return memory so it is aligned + uintptr_t ptr = reinterpret_cast(result); + size_t adjust = 0; + if ((ptr & (alignment - 1)) != 0) { + adjust = alignment - (ptr & (alignment - 1)); + } + + // Return the unused memory to the system + if (adjust > 0) { + munmap(reinterpret_cast(ptr), adjust); + } + if (adjust < extra) { + munmap(reinterpret_cast(ptr + adjust + size), extra - adjust); + } + + ptr += adjust; + return reinterpret_cast(ptr); +#endif // HAVE_MMAP +} + +void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { +#ifndef HAVE_MMAP + return NULL; +#else + static bool initialized = false; + static off_t physmem_base; // next physical memory address to allocate + static off_t physmem_limit; // maximum physical address allowed + static int physmem_fd; // file descriptor for /dev/mem + + // Check if we should use /dev/mem allocation. Note that it may take + // a while to get this flag initialized, so meanwhile we fall back to + // the next allocator. (It looks like 7MB gets allocated before + // this flag gets initialized -khr.) + if (FLAGS_malloc_devmem_start == 0) { + // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to + // try us again next time. + return NULL; + } + + if (!initialized) { + physmem_fd = open("/dev/mem", O_RDWR); + if (physmem_fd < 0) { + return NULL; + } + physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL; + physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL; + initialized = true; + } + + // Enforce page alignment + if (pagesize == 0) pagesize = getpagesize(); + if (alignment < pagesize) alignment = pagesize; + size_t aligned_size = ((size + alignment - 1) / alignment) * alignment; + if (aligned_size < size) { + return NULL; + } + size = aligned_size; + + // "actual_size" indicates that the bytes from the returned pointer + // p up to and including (p + actual_size - 1) have been allocated. + if (actual_size) { + *actual_size = size; + } + + // Ask for extra memory if alignment > pagesize + size_t extra = 0; + if (alignment > pagesize) { + extra = alignment - pagesize; + } + + // check to see if we have any memory left + if (physmem_limit != 0 && + ((size + extra) > (physmem_limit - physmem_base))) { + return NULL; + } + + // Note: size + extra does not overflow since: + // size + alignment < (1<(MAP_FAILED)) { + return NULL; + } + uintptr_t ptr = reinterpret_cast(result); + + // Adjust the return memory so it is aligned + size_t adjust = 0; + if ((ptr & (alignment - 1)) != 0) { + adjust = alignment - (ptr & (alignment - 1)); + } + + // Return the unused virtual memory to the system + if (adjust > 0) { + munmap(reinterpret_cast(ptr), adjust); + } + if (adjust < extra) { + munmap(reinterpret_cast(ptr + adjust + size), extra - adjust); + } + + ptr += adjust; + physmem_base += adjust + size; + + return reinterpret_cast(ptr); +#endif // HAVE_MMAP +} + +void* DefaultSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { + for (int i = 0; i < kMaxAllocators; i++) { + if (!failed_[i] && allocs_[i] != NULL) { + void* result = allocs_[i]->Alloc(size, actual_size, alignment); + if (result != NULL) { + return result; + } + failed_[i] = true; + } + } + // After both failed, reset "failed_" to false so that a single failed + // allocation won't make the allocator never work again. + for (int i = 0; i < kMaxAllocators; i++) { + failed_[i] = false; + } + return NULL; +} + +ATTRIBUTE_WEAK ATTRIBUTE_NOINLINE +SysAllocator *tc_get_sysalloc_override(SysAllocator *def) +{ + return def; +} + +static bool system_alloc_inited = false; +void InitSystemAllocators(void) { + MmapSysAllocator *mmap = new (mmap_space.buf) MmapSysAllocator(); + SbrkSysAllocator *sbrk = new (sbrk_space.buf) SbrkSysAllocator(); + + // In 64-bit debug mode, place the mmap allocator first since it + // allocates pointers that do not fit in 32 bits and therefore gives + // us better testing of code's 64-bit correctness. It also leads to + // less false negatives in heap-checking code. (Numbers are less + // likely to look like pointers and therefore the conservative gc in + // the heap-checker is less likely to misinterpret a number as a + // pointer). + DefaultSysAllocator *sdef = new (default_space.buf) DefaultSysAllocator(); + if (kDebugMode && sizeof(void*) > 4) { + sdef->SetChildAllocator(mmap, 0, mmap_name); + sdef->SetChildAllocator(sbrk, 1, sbrk_name); + } else { + sdef->SetChildAllocator(sbrk, 0, sbrk_name); + sdef->SetChildAllocator(mmap, 1, mmap_name); + } + + tcmalloc_sys_alloc = tc_get_sysalloc_override(sdef); +} + +void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, + size_t alignment) { + // Discard requests that overflow + if (size + alignment < size) return NULL; + + SpinLockHolder lock_holder(&spinlock); + + if (!system_alloc_inited) { + InitSystemAllocators(); + system_alloc_inited = true; + } + + // Enforce minimum alignment + if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); + + size_t actual_size_storage; + if (actual_size == NULL) { + actual_size = &actual_size_storage; + } + + void* result = tcmalloc_sys_alloc->Alloc(size, actual_size, alignment); + if (result != NULL) { + CHECK_CONDITION( + CheckAddressBits(reinterpret_cast(result) + *actual_size - 1)); + TCMalloc_SystemTaken += *actual_size; + } + return result; +} + +bool TCMalloc_SystemRelease(void* start, size_t length) { +#ifdef MADV_FREE + if (FLAGS_malloc_devmem_start) { + // It's not safe to use MADV_FREE/MADV_DONTNEED if we've been + // mapping /dev/mem for heap memory. + return false; + } + if (FLAGS_malloc_disable_memory_release) return false; + if (pagesize == 0) pagesize = getpagesize(); + const size_t pagemask = pagesize - 1; + + size_t new_start = reinterpret_cast(start); + size_t end = new_start + length; + size_t new_end = end; + + // Round up the starting address and round down the ending address + // to be page aligned: + new_start = (new_start + pagesize - 1) & ~pagemask; + new_end = new_end & ~pagemask; + + ASSERT((new_start & pagemask) == 0); + ASSERT((new_end & pagemask) == 0); + ASSERT(new_start >= reinterpret_cast(start)); + ASSERT(new_end <= end); + + if (new_end > new_start) { + int result; + do { + result = madvise(reinterpret_cast(new_start), + new_end - new_start, MADV_FREE); + } while (result == -1 && errno == EAGAIN); + + return result != -1; + } +#endif + return false; +} + +void TCMalloc_SystemCommit(void* start, size_t length) { + // Nothing to do here. TCMalloc_SystemRelease does not alter pages + // such that they need to be re-committed before they can be used by the + // application. +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/system-alloc.h b/trunk/3rdparty/gperftools-2-fit/src/system-alloc.h new file mode 100644 index 000000000..e88948d67 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/system-alloc.h @@ -0,0 +1,92 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// Routine that uses sbrk/mmap to allocate memory from the system. +// Useful for implementing malloc. + +#ifndef TCMALLOC_SYSTEM_ALLOC_H_ +#define TCMALLOC_SYSTEM_ALLOC_H_ + +#include +#include // for size_t + +class SysAllocator; + +// REQUIRES: "alignment" is a power of two or "0" to indicate default alignment +// +// 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. The +// returned pointer will always be aligned suitably for holding a +// void*, double, or size_t. In addition, if this platform defines +// CACHELINE_ALIGNED, the return pointer will always be cacheline +// aligned. +// +// Returns NULL when out of memory. +extern PERFTOOLS_DLL_DECL +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 +// while, and can be released for use by other processes or the OS. +// Pages which are released in this way may be destroyed (zeroed) by +// the OS. The benefit of this function is that it frees memory for +// use by the system, the cost is that the pages are faulted back into +// the address space next time they are touched, which can impact +// performance. (Only pages fully covered by the memory region will +// be released, partial pages will not.) +// +// Returns false if release failed or not supported. +extern PERFTOOLS_DLL_DECL +bool TCMalloc_SystemRelease(void* start, size_t length); + +// Called to ressurect memory which has been previously released +// to the system via TCMalloc_SystemRelease. An attempt to +// commit a page that is already committed does not cause this +// function to fail. +extern PERFTOOLS_DLL_DECL +void TCMalloc_SystemCommit(void* start, size_t length); + +// The current system allocator. +extern PERFTOOLS_DLL_DECL SysAllocator* tcmalloc_sys_alloc; + +// Number of bytes taken from system. +extern PERFTOOLS_DLL_DECL size_t TCMalloc_SystemTaken; + +#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.cc b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.cc new file mode 100644 index 000000000..9ec663e25 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.cc @@ -0,0 +1,2225 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat +// +// A malloc that uses a per-thread cache to satisfy small malloc requests. +// (The time for malloc/free of a small object drops from 300 ns to 50 ns.) +// +// See docs/tcmalloc.html for a high-level +// description of how this malloc works. +// +// SYNCHRONIZATION +// 1. The thread-specific lists are accessed without acquiring any locks. +// This is safe because each such list is only accessed by one thread. +// 2. We have a lock per central free-list, and hold it while manipulating +// the central free list for a particular size. +// 3. The central page allocator is protected by "pageheap_lock". +// 4. The pagemap (which maps from page-number to descriptor), +// can be read without holding any locks, and written while holding +// the "pageheap_lock". +// 5. To improve performance, a subset of the information one can get +// from the pagemap is cached in a data structure, pagemap_cache_, +// that atomically reads and writes its entries. This cache can be +// read and written without locking. +// +// This multi-threaded access to the pagemap is safe for fairly +// subtle reasons. We basically assume that when an object X is +// allocated by thread A and deallocated by thread B, there must +// have been appropriate synchronization in the handoff of object +// X from thread A to thread B. The same logic applies to pagemap_cache_. +// +// THE PAGEID-TO-SIZECLASS CACHE +// Hot PageID-to-sizeclass mappings are held by pagemap_cache_. If this cache +// returns 0 for a particular PageID then that means "no information," not that +// the sizeclass is 0. The cache may have stale information for pages that do +// not hold the beginning of any free()'able object. Staleness is eliminated +// in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and +// do_memalign() for all other relevant pages. +// +// PAGEMAP +// ------- +// Page map contains a mapping from page id to Span. +// +// If Span s occupies pages [p..q], +// pagemap[p] == s +// pagemap[q] == s +// pagemap[p+1..q-1] are undefined +// pagemap[p-1] and pagemap[q+1] are defined: +// NULL if the corresponding page is not yet in the address space. +// Otherwise it points to a Span. This span may be free +// or allocated. If free, it is in one of pageheap's freelist. +// +// TODO: Bias reclamation to larger addresses +// TODO: implement mallinfo/mallopt +// TODO: Better testing +// +// 9/28/2003 (new page-level allocator replaces ptmalloc2): +// * malloc/free of small objects goes from ~300 ns to ~50 ns. +// * allocation of a reasonably complicated struct +// goes from about 1100 ns to about 300 ns. + +#include "config.h" +// At least for gcc on Linux/i386 and Linux/amd64 not adding throw() +// to tc_xxx functions actually ends up generating better code. +#define PERFTOOLS_NOTHROW +#include + +#include // for ENOMEM, EINVAL, errno +#if defined HAVE_STDINT_H +#include +#elif defined HAVE_INTTYPES_H +#include +#else +#include +#endif +#include // for size_t, NULL +#include // for getenv +#include // for strcmp, memset, strlen, etc +#ifdef HAVE_UNISTD_H +#include // for getpagesize, write, etc +#endif +#include // for max, min +#include // for numeric_limits +#include // for nothrow_t (ptr only), etc +#include // for vector + +#include +#include // for MallocHook +#include +#include "base/basictypes.h" // for int64 +#include "base/commandlineflags.h" // for RegisterFlagValidator, etc +#include "base/dynamic_annotations.h" // for RunningOnValgrind +#include "base/spinlock.h" // for SpinLockHolder +#include "central_freelist.h" // for CentralFreeListPadded +#include "common.h" // for StackTrace, kPageShift, etc +#include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc +#include "linked_list.h" // for SLL_SetNext +#include "malloc_hook-inl.h" // for MallocHook::InvokeNewHook, etc +#include "page_heap.h" // for PageHeap, PageHeap::Stats +#include "page_heap_allocator.h" // for PageHeapAllocator +#include "span.h" // for Span, DLL_Prepend, etc +#include "stack_trace_table.h" // for StackTraceTable +#include "static_vars.h" // for Static +#include "system-alloc.h" // for DumpSystemAllocatorStats, etc +#include "tcmalloc_guard.h" // for TCMallocGuard +#include "thread_cache.h" // for ThreadCache + +#include "maybe_emergency_malloc.h" + +#if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defined(WIN32_OVERRIDE_ALLOCATORS) +# define WIN32_DO_PATCHING 1 +#endif + +// Some windows file somewhere (at least on cygwin) #define's small (!) +#undef small + +using std::max; +using std::min; +using std::numeric_limits; +using std::vector; + +#include "libc_override.h" + +using tcmalloc::AlignmentForSize; +using tcmalloc::kLog; +using tcmalloc::kCrash; +using tcmalloc::kCrashWithStats; +using tcmalloc::Log; +using tcmalloc::PageHeap; +using tcmalloc::PageHeapAllocator; +using tcmalloc::SizeMap; +using tcmalloc::Span; +using tcmalloc::StackTrace; +using tcmalloc::Static; +using tcmalloc::ThreadCache; + +DECLARE_double(tcmalloc_release_rate); +DECLARE_int64(tcmalloc_heap_limit_mb); + +// Those common architectures are known to be safe w.r.t. aliasing function +// with "extra" unused args to function with fewer arguments (e.g. +// tc_delete_nothrow being aliased to tc_delete). +// +// Benefit of aliasing is relatively moderate. It reduces instruction +// cache pressure a bit (not relevant for largely unused +// tc_delete_nothrow, but is potentially relevant for +// tc_delete_aligned (or sized)). It also used to be the case that gcc +// 5+ optimization for merging identical functions kicked in and +// "screwed" one of the otherwise identical functions with extra +// jump. I am not able to reproduce that anymore. +#if !defined(__i386__) && !defined(__x86_64__) && \ + !defined(__ppc__) && !defined(__PPC__) && \ + !defined(__aarch64__) && !defined(__mips__) && !defined(__arm__) +#undef TCMALLOC_NO_ALIASES +#define TCMALLOC_NO_ALIASES +#endif + +#if defined(__GNUC__) && defined(__ELF__) && !defined(TCMALLOC_NO_ALIASES) +#define TC_ALIAS(name) __attribute__((alias(#name))) +#endif + +// For windows, the printf we use to report large allocs is +// potentially dangerous: it could cause a malloc that would cause an +// infinite loop. So by default we set the threshold to a huge number +// on windows, so this bad situation will never trigger. You can +// always set TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD manually if you +// want this functionality. +#ifdef _WIN32 +const int64 kDefaultLargeAllocReportThreshold = static_cast(1) << 62; +#else +const int64 kDefaultLargeAllocReportThreshold = static_cast(1) << 30; +#endif +DEFINE_int64(tcmalloc_large_alloc_report_threshold, + EnvToInt64("TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD", + kDefaultLargeAllocReportThreshold), + "Allocations larger than this value cause a stack " + "trace to be dumped to stderr. The threshold for " + "dumping stack traces is increased by a factor of 1.125 " + "every time we print a message so that the threshold " + "automatically goes up by a factor of ~1000 every 60 " + "messages. This bounds the amount of extra logging " + "generated by this flag. Default value of this flag " + "is very large and therefore you should see no extra " + "logging unless the flag is overridden. Set to 0 to " + "disable reporting entirely."); + + +// We already declared these functions in tcmalloc.h, but we have to +// declare them again to give them an ATTRIBUTE_SECTION: we want to +// put all callers of MallocHook::Invoke* in this module into +// ATTRIBUTE_SECTION(google_malloc) section, so that +// MallocHook::GetCallerStackTrace can function accurately. +#ifndef _WIN32 // windows doesn't have attribute_section, so don't bother +extern "C" { + void* tc_malloc(size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_free(void* ptr) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_free_sized(void* ptr, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_cfree(void* ptr) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + + void* tc_memalign(size_t __alignment, size_t __size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + int tc_posix_memalign(void** ptr, size_t align, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_valloc(size_t __size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_pvalloc(size_t __size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + + void tc_malloc_stats(void) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); +#ifdef HAVE_STRUCT_MALLINFO + struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); +#endif + + void* tc_new(size_t size) + ATTRIBUTE_SECTION(google_malloc); + void tc_delete(void* p) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_newarray(size_t size) + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray(void* p) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + + // And the nothrow variants of these: + void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + // Surprisingly, standard C++ library implementations use a + // nothrow-delete internally. See, eg: + // http://www.dinkumware.com/manuals/?manual=compleat&page=new.html + void tc_delete_nothrow(void* ptr, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray_nothrow(void* ptr, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + + void* tc_new_aligned(size_t size, std::align_val_t al) + ATTRIBUTE_SECTION(google_malloc); + void tc_delete_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_newarray_aligned(size_t size, std::align_val_t al) + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + + // And the nothrow variants of these: + void* tc_new_aligned_nothrow(size_t size, std::align_val_t al, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t al, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_delete_aligned_nothrow(void* ptr, std::align_val_t al, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + void tc_deletearray_aligned_nothrow(void* ptr, std::align_val_t al, const std::nothrow_t&) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + + // Some non-standard extensions that we support. + + // This is equivalent to + // OS X: malloc_size() + // glibc: malloc_usable_size() + // Windows: _msize() + size_t tc_malloc_size(void* p) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); +} // extern "C" +#endif // #ifndef _WIN32 + +// ----------------------- IMPLEMENTATION ------------------------------- + +static int tc_new_mode = 0; // See tc_set_new_mode(). + +// Routines such as free() and realloc() catch some erroneous pointers +// passed to them, and invoke the below when they do. (An erroneous pointer +// won't be caught if it's within a valid span or a stale span for which +// the pagemap cache has a non-zero sizeclass.) This is a cheap (source-editing +// required) kind of exception handling for these routines. +namespace { +ATTRIBUTE_NOINLINE void InvalidFree(void* ptr) { + if (tcmalloc::IsEmergencyPtr(ptr)) { + tcmalloc::EmergencyFree(ptr); + return; + } + Log(kCrash, __FILE__, __LINE__, "Attempt to free invalid pointer", ptr); +} + +size_t InvalidGetSizeForRealloc(const void* old_ptr) { + Log(kCrash, __FILE__, __LINE__, + "Attempt to realloc invalid pointer", old_ptr); + return 0; +} + +size_t InvalidGetAllocatedSize(const void* ptr) { + Log(kCrash, __FILE__, __LINE__, + "Attempt to get the size of an invalid pointer", ptr); + return 0; +} +} // unnamed namespace + +// Extract interesting stats +struct TCMallocStats { + uint64_t thread_bytes; // Bytes in thread caches + uint64_t central_bytes; // Bytes in central cache + uint64_t transfer_bytes; // Bytes in central transfer cache + uint64_t metadata_bytes; // Bytes alloced for metadata + PageHeap::Stats pageheap; // Stats from page heap +}; + +// Get stats into "r". Also, if class_count != NULL, class_count[k] +// will be set to the total number of objects of size class k in the +// central cache, transfer cache, and per-thread caches. If small_spans +// is non-NULL, it is filled. Same for large_spans. +static void ExtractStats(TCMallocStats* r, uint64_t* class_count, + PageHeap::SmallSpanStats* small_spans, + PageHeap::LargeSpanStats* large_spans) { + r->central_bytes = 0; + r->transfer_bytes = 0; + for (int cl = 0; cl < Static::num_size_classes(); ++cl) { + const int length = Static::central_cache()[cl].length(); + const int tc_length = Static::central_cache()[cl].tc_length(); + const size_t cache_overhead = Static::central_cache()[cl].OverheadBytes(); + const size_t size = static_cast( + Static::sizemap()->ByteSizeForClass(cl)); + r->central_bytes += (size * length) + cache_overhead; + r->transfer_bytes += (size * tc_length); + if (class_count) { + // Sum the lengths of all per-class freelists, except the per-thread + // freelists, which get counted when we call GetThreadStats(), below. + class_count[cl] = length + tc_length; + } + + } + + // Add stats from per-thread heaps + r->thread_bytes = 0; + { // scope + SpinLockHolder h(Static::pageheap_lock()); + ThreadCache::GetThreadStats(&r->thread_bytes, class_count); + r->metadata_bytes = tcmalloc::metadata_system_bytes(); + r->pageheap = Static::pageheap()->stats(); + if (small_spans != NULL) { + Static::pageheap()->GetSmallSpanStats(small_spans); + } + if (large_spans != NULL) { + Static::pageheap()->GetLargeSpanStats(large_spans); + } + } +} + +static double PagesToMiB(uint64_t pages) { + return (pages << kPageShift) / 1048576.0; +} + +// WRITE stats to "out" +static void DumpStats(TCMalloc_Printer* out, int level) { + TCMallocStats stats; + uint64_t class_count[kClassSizesMax]; + PageHeap::SmallSpanStats small; + PageHeap::LargeSpanStats large; + if (level >= 2) { + ExtractStats(&stats, class_count, &small, &large); + } else { + ExtractStats(&stats, NULL, NULL, NULL); + } + + static const double MiB = 1048576.0; + + const uint64_t virtual_memory_used = (stats.pageheap.system_bytes + + stats.metadata_bytes); + const uint64_t physical_memory_used = (virtual_memory_used + - stats.pageheap.unmapped_bytes); + const uint64_t bytes_in_use_by_app = (physical_memory_used + - stats.metadata_bytes + - stats.pageheap.free_bytes + - stats.central_bytes + - stats.transfer_bytes + - stats.thread_bytes); + +#ifdef TCMALLOC_SMALL_BUT_SLOW + out->printf( + "NOTE: SMALL MEMORY MODEL IS IN USE, PERFORMANCE MAY SUFFER.\n"); +#endif + out->printf( + "------------------------------------------------\n" + "MALLOC: %12" PRIu64 " (%7.1f MiB) Bytes in use by application\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in page heap freelist\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in central cache freelist\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in transfer cache freelist\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in thread cache freelists\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes in malloc metadata\n" + "MALLOC: ------------\n" + "MALLOC: = %12" PRIu64 " (%7.1f MiB) Actual memory used (physical + swap)\n" + "MALLOC: + %12" PRIu64 " (%7.1f MiB) Bytes released to OS (aka unmapped)\n" + "MALLOC: ------------\n" + "MALLOC: = %12" PRIu64 " (%7.1f MiB) Virtual address space used\n" + "MALLOC:\n" + "MALLOC: %12" PRIu64 " Spans in use\n" + "MALLOC: %12" PRIu64 " Thread heaps in use\n" + "MALLOC: %12" PRIu64 " Tcmalloc page size\n" + "------------------------------------------------\n" + "Call ReleaseFreeMemory() to release freelist memory to the OS" + " (via madvise()).\n" + "Bytes released to the OS take up virtual address space" + " but no physical memory.\n", + bytes_in_use_by_app, bytes_in_use_by_app / MiB, + stats.pageheap.free_bytes, stats.pageheap.free_bytes / MiB, + stats.central_bytes, stats.central_bytes / MiB, + stats.transfer_bytes, stats.transfer_bytes / MiB, + stats.thread_bytes, stats.thread_bytes / MiB, + stats.metadata_bytes, stats.metadata_bytes / MiB, + physical_memory_used, physical_memory_used / MiB, + stats.pageheap.unmapped_bytes, stats.pageheap.unmapped_bytes / MiB, + virtual_memory_used, virtual_memory_used / MiB, + uint64_t(Static::span_allocator()->inuse()), + uint64_t(ThreadCache::HeapsInUse()), + uint64_t(kPageSize)); + + if (level >= 2) { + out->printf("------------------------------------------------\n"); + out->printf("Total size of freelists for per-thread caches,\n"); + out->printf("transfer cache, and central cache, by size class\n"); + out->printf("------------------------------------------------\n"); + uint64_t cumulative_bytes = 0; + uint64_t cumulative_overhead = 0; + for (uint32 cl = 0; cl < Static::num_size_classes(); ++cl) { + if (class_count[cl] > 0) { + size_t cl_size = Static::sizemap()->ByteSizeForClass(cl); + const uint64_t class_bytes = class_count[cl] * cl_size; + cumulative_bytes += class_bytes; + const uint64_t class_overhead = + Static::central_cache()[cl].OverheadBytes(); + cumulative_overhead += class_overhead; + out->printf("class %3d [ %8zu bytes ] : " + "%8" PRIu64 " objs; %5.1f MiB; %5.1f cum MiB; " + "%8.3f overhead MiB; %8.3f cum overhead MiB\n", + cl, cl_size, + class_count[cl], + class_bytes / MiB, + cumulative_bytes / MiB, + class_overhead / MiB, + cumulative_overhead / MiB); + } + } + + // append page heap info + int nonempty_sizes = 0; + for (int s = 0; s < kMaxPages; s++) { + if (small.normal_length[s] + small.returned_length[s] > 0) { + nonempty_sizes++; + } + } + out->printf("------------------------------------------------\n"); + out->printf("PageHeap: %d sizes; %6.1f MiB free; %6.1f MiB unmapped\n", + nonempty_sizes, stats.pageheap.free_bytes / MiB, + stats.pageheap.unmapped_bytes / MiB); + out->printf("------------------------------------------------\n"); + uint64_t total_normal = 0; + uint64_t total_returned = 0; + for (int s = 1; s <= kMaxPages; s++) { + const int n_length = small.normal_length[s - 1]; + const int r_length = small.returned_length[s - 1]; + if (n_length + r_length > 0) { + uint64_t n_pages = s * n_length; + uint64_t r_pages = s * r_length; + total_normal += n_pages; + total_returned += r_pages; + out->printf("%6u pages * %6u spans ~ %6.1f MiB; %6.1f MiB cum" + "; unmapped: %6.1f MiB; %6.1f MiB cum\n", + s, + (n_length + r_length), + PagesToMiB(n_pages + r_pages), + PagesToMiB(total_normal + total_returned), + PagesToMiB(r_pages), + PagesToMiB(total_returned)); + } + } + + total_normal += large.normal_pages; + total_returned += large.returned_pages; + out->printf(">%-5u large * %6u spans ~ %6.1f MiB; %6.1f MiB cum" + "; unmapped: %6.1f MiB; %6.1f MiB cum\n", + static_cast(kMaxPages), + static_cast(large.spans), + PagesToMiB(large.normal_pages + large.returned_pages), + PagesToMiB(total_normal + total_returned), + PagesToMiB(large.returned_pages), + PagesToMiB(total_returned)); + } +} + +static void PrintStats(int level) { + const int kBufferSize = 16 << 10; + char* buffer = new char[kBufferSize]; + TCMalloc_Printer printer(buffer, kBufferSize); + DumpStats(&printer, level); + write(STDERR_FILENO, buffer, strlen(buffer)); + delete[] buffer; +} + +static void** DumpHeapGrowthStackTraces() { + // Count how much space we need + int needed_slots = 0; + { + SpinLockHolder h(Static::pageheap_lock()); + for (StackTrace* t = Static::growth_stacks(); + t != NULL; + t = reinterpret_cast( + t->stack[tcmalloc::kMaxStackDepth-1])) { + needed_slots += 3 + t->depth; + } + needed_slots += 100; // Slop in case list grows + needed_slots += needed_slots/8; // An extra 12.5% slop + } + + void** result = new void*[needed_slots]; + if (result == NULL) { + Log(kLog, __FILE__, __LINE__, + "tcmalloc: allocation failed for stack trace slots", + needed_slots * sizeof(*result)); + return NULL; + } + + SpinLockHolder h(Static::pageheap_lock()); + int used_slots = 0; + for (StackTrace* t = Static::growth_stacks(); + t != NULL; + t = reinterpret_cast( + t->stack[tcmalloc::kMaxStackDepth-1])) { + ASSERT(used_slots < needed_slots); // Need to leave room for terminator + if (used_slots + 3 + t->depth >= needed_slots) { + // No more room + break; + } + + result[used_slots+0] = reinterpret_cast(static_cast(1)); + result[used_slots+1] = reinterpret_cast(t->size); + result[used_slots+2] = reinterpret_cast(t->depth); + for (int d = 0; d < t->depth; d++) { + result[used_slots+3+d] = t->stack[d]; + } + used_slots += 3 + t->depth; + } + result[used_slots] = reinterpret_cast(static_cast(0)); + return result; +} + +static void IterateOverRanges(void* arg, MallocExtension::RangeFunction func) { + PageID page = 1; // Some code may assume that page==0 is never used + bool done = false; + while (!done) { + // Accumulate a small number of ranges in a local buffer + static const int kNumRanges = 16; + static base::MallocRange ranges[kNumRanges]; + int n = 0; + { + SpinLockHolder h(Static::pageheap_lock()); + while (n < kNumRanges) { + if (!Static::pageheap()->GetNextRange(page, &ranges[n])) { + done = true; + break; + } else { + uintptr_t limit = ranges[n].address + ranges[n].length; + page = (limit + kPageSize - 1) >> kPageShift; + n++; + } + } + } + + for (int i = 0; i < n; i++) { + (*func)(arg, &ranges[i]); + } + } +} + +// TCMalloc's support for extra malloc interfaces +class TCMallocImplementation : public MallocExtension { + private: + // ReleaseToSystem() might release more than the requested bytes because + // the page heap releases at the span granularity, and spans are of wildly + // different sizes. This member keeps track of the extra bytes bytes + // released so that the app can periodically call ReleaseToSystem() to + // release memory at a constant rate. + // NOTE: Protected by Static::pageheap_lock(). + size_t extra_bytes_released_; + + public: + TCMallocImplementation() + : extra_bytes_released_(0) { + } + + virtual void GetStats(char* buffer, int buffer_length) { + ASSERT(buffer_length > 0); + TCMalloc_Printer printer(buffer, buffer_length); + + // Print level one stats unless lots of space is available + if (buffer_length < 10000) { + DumpStats(&printer, 1); + } else { + DumpStats(&printer, 2); + } + } + + // We may print an extra, tcmalloc-specific warning message here. + virtual void GetHeapSample(MallocExtensionWriter* writer) { + if (FLAGS_tcmalloc_sample_parameter == 0) { + const char* const kWarningMsg = + "%warn\n" + "%warn This heap profile does not have any data in it, because\n" + "%warn the application was run with heap sampling turned off.\n" + "%warn To get useful data from GetHeapSample(), you must\n" + "%warn set the environment variable TCMALLOC_SAMPLE_PARAMETER to\n" + "%warn a positive sampling period, such as 524288.\n" + "%warn\n"; + writer->append(kWarningMsg, strlen(kWarningMsg)); + } + MallocExtension::GetHeapSample(writer); + } + + virtual void** ReadStackTraces(int* sample_period) { + tcmalloc::StackTraceTable table; + { + SpinLockHolder h(Static::pageheap_lock()); + Span* sampled = Static::sampled_objects(); + for (Span* s = sampled->next; s != sampled; s = s->next) { + table.AddTrace(*reinterpret_cast(s->objects)); + } + } + *sample_period = ThreadCache::GetCache()->GetSamplePeriod(); + return table.ReadStackTracesAndClear(); // grabs and releases pageheap_lock + } + + virtual void** ReadHeapGrowthStackTraces() { + return DumpHeapGrowthStackTraces(); + } + + virtual size_t GetThreadCacheSize() { + ThreadCache* tc = ThreadCache::GetCacheIfPresent(); + if (!tc) + return 0; + return tc->Size(); + } + + virtual void MarkThreadTemporarilyIdle() { + ThreadCache::BecomeTemporarilyIdle(); + } + + virtual void Ranges(void* arg, RangeFunction func) { + IterateOverRanges(arg, func); + } + + virtual bool GetNumericProperty(const char* name, size_t* value) { + ASSERT(name != NULL); + + if (strcmp(name, "generic.current_allocated_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.pageheap.system_bytes + - stats.thread_bytes + - stats.central_bytes + - stats.transfer_bytes + - stats.pageheap.free_bytes + - stats.pageheap.unmapped_bytes; + return true; + } + + if (strcmp(name, "generic.heap_size") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.pageheap.system_bytes; + return true; + } + + if (strcmp(name, "generic.total_physical_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.pageheap.system_bytes + stats.metadata_bytes - + stats.pageheap.unmapped_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.slack_bytes") == 0) { + // Kept for backwards compatibility. Now defined externally as: + // pageheap_free_bytes + pageheap_unmapped_bytes. + SpinLockHolder l(Static::pageheap_lock()); + PageHeap::Stats stats = Static::pageheap()->stats(); + *value = stats.free_bytes + stats.unmapped_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.central_cache_free_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.central_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.transfer_cache_free_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.transfer_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.thread_cache_free_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.thread_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_free_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().free_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_unmapped_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().unmapped_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_committed_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().committed_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_scavenge_count") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().scavenge_count; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_commit_count") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().commit_count; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_total_commit_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().total_commit_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_decommit_count") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().decommit_count; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_total_decommit_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().total_decommit_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_reserve_count") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().reserve_count; + return true; + } + + if (strcmp(name, "tcmalloc.pageheap_total_reserve_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = Static::pageheap()->stats().total_reserve_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = ThreadCache::overall_thread_cache_size(); + return true; + } + + if (strcmp(name, "tcmalloc.current_total_thread_cache_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + *value = stats.thread_bytes; + return true; + } + + if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = size_t(Static::pageheap()->GetAggressiveDecommit()); + return true; + } + + if (strcmp(name, "tcmalloc.heap_limit_mb") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + *value = FLAGS_tcmalloc_heap_limit_mb; + return true; + } + + return false; + } + + virtual bool SetNumericProperty(const char* name, size_t value) { + ASSERT(name != NULL); + + if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + ThreadCache::set_overall_thread_cache_size(value); + return true; + } + + if (strcmp(name, "tcmalloc.aggressive_memory_decommit") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + Static::pageheap()->SetAggressiveDecommit(value != 0); + return true; + } + + if (strcmp(name, "tcmalloc.heap_limit_mb") == 0) { + SpinLockHolder l(Static::pageheap_lock()); + FLAGS_tcmalloc_heap_limit_mb = value; + return true; + } + + return false; + } + + virtual void MarkThreadIdle() { + ThreadCache::BecomeIdle(); + } + + virtual void MarkThreadBusy(); // Implemented below + + virtual SysAllocator* GetSystemAllocator() { + SpinLockHolder h(Static::pageheap_lock()); + return tcmalloc_sys_alloc; + } + + virtual void SetSystemAllocator(SysAllocator* alloc) { + SpinLockHolder h(Static::pageheap_lock()); + tcmalloc_sys_alloc = alloc; + } + + virtual void ReleaseToSystem(size_t num_bytes) { + SpinLockHolder h(Static::pageheap_lock()); + if (num_bytes <= extra_bytes_released_) { + // We released too much on a prior call, so don't release any + // more this time. + extra_bytes_released_ = extra_bytes_released_ - num_bytes; + return; + } + num_bytes = num_bytes - extra_bytes_released_; + // num_bytes might be less than one page. If we pass zero to + // ReleaseAtLeastNPages, it won't do anything, so we release a whole + // page now and let extra_bytes_released_ smooth it out over time. + Length num_pages = max(num_bytes >> kPageShift, 1); + size_t bytes_released = Static::pageheap()->ReleaseAtLeastNPages( + num_pages) << kPageShift; + if (bytes_released > num_bytes) { + extra_bytes_released_ = bytes_released - num_bytes; + } else { + // The PageHeap wasn't able to release num_bytes. Don't try to + // compensate with a big release next time. Specifically, + // ReleaseFreeMemory() calls ReleaseToSystem(LONG_MAX). + extra_bytes_released_ = 0; + } + } + + virtual void SetMemoryReleaseRate(double rate) { + FLAGS_tcmalloc_release_rate = rate; + } + + virtual double GetMemoryReleaseRate() { + return FLAGS_tcmalloc_release_rate; + } + virtual size_t GetEstimatedAllocatedSize(size_t size); + + // This just calls GetSizeWithCallback, but because that's in an + // unnamed namespace, we need to move the definition below it in the + // file. + virtual size_t GetAllocatedSize(const void* ptr); + + // This duplicates some of the logic in GetSizeWithCallback, but is + // faster. This is important on OS X, where this function is called + // on every allocation operation. + virtual Ownership GetOwnership(const void* ptr) { + const PageID p = reinterpret_cast(ptr) >> kPageShift; + // The rest of tcmalloc assumes that all allocated pointers use at + // most kAddressBits bits. If ptr doesn't, then it definitely + // wasn't alloacted by tcmalloc. + if ((p >> (kAddressBits - kPageShift)) > 0) { + return kNotOwned; + } + uint32 cl; + if (Static::pageheap()->TryGetSizeClass(p, &cl)) { + return kOwned; + } + const Span *span = Static::pageheap()->GetDescriptor(p); + return span ? kOwned : kNotOwned; + } + + virtual void GetFreeListSizes(vector* v) { + static const char kCentralCacheType[] = "tcmalloc.central"; + static const char kTransferCacheType[] = "tcmalloc.transfer"; + static const char kThreadCacheType[] = "tcmalloc.thread"; + static const char kPageHeapType[] = "tcmalloc.page"; + static const char kPageHeapUnmappedType[] = "tcmalloc.page_unmapped"; + static const char kLargeSpanType[] = "tcmalloc.large"; + static const char kLargeUnmappedSpanType[] = "tcmalloc.large_unmapped"; + + v->clear(); + + // central class information + int64 prev_class_size = 0; + for (int cl = 1; cl < Static::num_size_classes(); ++cl) { + size_t class_size = Static::sizemap()->ByteSizeForClass(cl); + MallocExtension::FreeListInfo i; + i.min_object_size = prev_class_size + 1; + i.max_object_size = class_size; + i.total_bytes_free = + Static::central_cache()[cl].length() * class_size; + i.type = kCentralCacheType; + v->push_back(i); + + // transfer cache + i.total_bytes_free = + Static::central_cache()[cl].tc_length() * class_size; + i.type = kTransferCacheType; + v->push_back(i); + + prev_class_size = Static::sizemap()->ByteSizeForClass(cl); + } + + // Add stats from per-thread heaps + uint64_t class_count[kClassSizesMax]; + memset(class_count, 0, sizeof(class_count)); + { + SpinLockHolder h(Static::pageheap_lock()); + uint64_t thread_bytes = 0; + ThreadCache::GetThreadStats(&thread_bytes, class_count); + } + + prev_class_size = 0; + for (int cl = 1; cl < Static::num_size_classes(); ++cl) { + MallocExtension::FreeListInfo i; + i.min_object_size = prev_class_size + 1; + i.max_object_size = Static::sizemap()->ByteSizeForClass(cl); + i.total_bytes_free = + class_count[cl] * Static::sizemap()->ByteSizeForClass(cl); + i.type = kThreadCacheType; + v->push_back(i); + + prev_class_size = Static::sizemap()->ByteSizeForClass(cl); + } + + // append page heap info + PageHeap::SmallSpanStats small; + PageHeap::LargeSpanStats large; + { + SpinLockHolder h(Static::pageheap_lock()); + Static::pageheap()->GetSmallSpanStats(&small); + Static::pageheap()->GetLargeSpanStats(&large); + } + + // large spans: mapped + MallocExtension::FreeListInfo span_info; + span_info.type = kLargeSpanType; + span_info.max_object_size = (numeric_limits::max)(); + span_info.min_object_size = kMaxPages << kPageShift; + span_info.total_bytes_free = large.normal_pages << kPageShift; + v->push_back(span_info); + + // large spans: unmapped + span_info.type = kLargeUnmappedSpanType; + span_info.total_bytes_free = large.returned_pages << kPageShift; + v->push_back(span_info); + + // small spans + for (int s = 1; s <= kMaxPages; s++) { + MallocExtension::FreeListInfo i; + i.max_object_size = (s << kPageShift); + i.min_object_size = ((s - 1) << kPageShift); + + i.type = kPageHeapType; + i.total_bytes_free = (s << kPageShift) * small.normal_length[s - 1]; + v->push_back(i); + + i.type = kPageHeapUnmappedType; + i.total_bytes_free = (s << kPageShift) * small.returned_length[s - 1]; + v->push_back(i); + } + } +}; + +static inline ATTRIBUTE_ALWAYS_INLINE +size_t align_size_up(size_t size, size_t align) { + ASSERT(align <= kPageSize); + size_t new_size = (size + align - 1) & ~(align - 1); + if (PREDICT_FALSE(new_size == 0)) { + // Note, new_size == 0 catches both integer overflow and size + // being 0. + if (size == 0) { + new_size = align; + } else { + new_size = size; + } + } + return new_size; +} + +// Puts in *cl size class that is suitable for allocation of size bytes with +// align alignment. Returns true if such size class exists and false otherwise. +static bool size_class_with_alignment(size_t size, size_t align, uint32_t* cl) { + if (PREDICT_FALSE(align > kPageSize)) { + return false; + } + size = align_size_up(size, align); + if (PREDICT_FALSE(!Static::sizemap()->GetSizeClass(size, cl))) { + return false; + } + ASSERT((Static::sizemap()->class_to_size(*cl) & (align - 1)) == 0); + return true; +} + +// nallocx slow path. Moved to a separate function because +// ThreadCache::InitModule is not inlined which would cause nallocx to +// become non-leaf function with stack frame and stack spills. +static ATTRIBUTE_NOINLINE size_t nallocx_slow(size_t size, int flags) { + if (PREDICT_FALSE(!Static::IsInited())) ThreadCache::InitModule(); + + size_t align = static_cast(1ull << (flags & 0x3f)); + uint32 cl; + bool ok = size_class_with_alignment(size, align, &cl); + if (ok) { + return Static::sizemap()->ByteSizeForClass(cl); + } else { + return tcmalloc::pages(size) << kPageShift; + } +} + +// The nallocx function allocates no memory, but it performs the same size +// computation as the malloc function, and returns the real size of the +// allocation that would result from the equivalent malloc function call. +// nallocx is a malloc extension originally implemented by jemalloc: +// http://www.unix.com/man-page/freebsd/3/nallocx/ +extern "C" PERFTOOLS_DLL_DECL +size_t tc_nallocx(size_t size, int flags) { + if (PREDICT_FALSE(flags != 0)) { + return nallocx_slow(size, flags); + } + uint32 cl; + // size class 0 is only possible if malloc is not yet initialized + if (Static::sizemap()->GetSizeClass(size, &cl) && cl != 0) { + return Static::sizemap()->ByteSizeForClass(cl); + } else { + return nallocx_slow(size, 0); + } +} + +extern "C" PERFTOOLS_DLL_DECL +size_t nallocx(size_t size, int flags) +#ifdef TC_ALIAS + TC_ALIAS(tc_nallocx); +#else +{ + return nallocx_slow(size, flags); +} +#endif + + +size_t TCMallocImplementation::GetEstimatedAllocatedSize(size_t size) { + return tc_nallocx(size, 0); +} + +// The constructor allocates an object to ensure that initialization +// runs before main(), and therefore we do not have a chance to become +// multi-threaded before initialization. We also create the TSD key +// here. Presumably by the time this constructor runs, glibc is in +// good enough shape to handle pthread_key_create(). +// +// The constructor also takes the opportunity to tell STL to use +// tcmalloc. We want to do this early, before construct time, so +// all user STL allocations go through tcmalloc (which works really +// well for STL). +// +// The destructor prints stats when the program exits. +static int tcmallocguard_refcount = 0; // no lock needed: runs before main() +TCMallocGuard::TCMallocGuard() { + if (tcmallocguard_refcount++ == 0) { + ReplaceSystemAlloc(); // defined in libc_override_*.h + tc_free(tc_malloc(1)); + ThreadCache::InitTSD(); + tc_free(tc_malloc(1)); + // Either we, or debugallocation.cc, or valgrind will control memory + // management. We register our extension if we're the winner. +#ifdef TCMALLOC_USING_DEBUGALLOCATION + // Let debugallocation register its extension. +#else + if (RunningOnValgrind()) { + // Let Valgrind uses its own malloc (so don't register our extension). + } else { + MallocExtension::Register(new TCMallocImplementation); + } +#endif + } +} + +TCMallocGuard::~TCMallocGuard() { + if (--tcmallocguard_refcount == 0) { + const char* env = NULL; + if (!RunningOnValgrind()) { + // Valgrind uses it's own malloc so we cannot do MALLOCSTATS + env = getenv("MALLOCSTATS"); + } + if (env != NULL) { + int level = atoi(env); + if (level < 1) level = 1; + PrintStats(level); + } + } +} +#ifndef WIN32_OVERRIDE_ALLOCATORS +static TCMallocGuard module_enter_exit_hook; +#endif + +//------------------------------------------------------------------- +// Helpers for the exported routines below +//------------------------------------------------------------------- + +static inline bool CheckCachedSizeClass(void *ptr) { + PageID p = reinterpret_cast(ptr) >> kPageShift; + uint32 cached_value; + if (!Static::pageheap()->TryGetSizeClass(p, &cached_value)) { + return true; + } + return cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass; +} + +static inline ATTRIBUTE_ALWAYS_INLINE void* CheckedMallocResult(void *result) { + ASSERT(result == NULL || CheckCachedSizeClass(result)); + return result; +} + +static inline ATTRIBUTE_ALWAYS_INLINE void* SpanToMallocResult(Span *span) { + Static::pageheap()->InvalidateCachedSizeClass(span->start); + return + CheckedMallocResult(reinterpret_cast(span->start << kPageShift)); +} + +static void* DoSampledAllocation(size_t size) { +#ifndef NO_TCMALLOC_SAMPLES + // Grab the stack trace outside the heap lock + StackTrace tmp; + tmp.depth = GetStackTrace(tmp.stack, tcmalloc::kMaxStackDepth, 1); + tmp.size = size; + + SpinLockHolder h(Static::pageheap_lock()); + // Allocate span + Span *span = Static::pageheap()->New(tcmalloc::pages(size == 0 ? 1 : size)); + if (PREDICT_FALSE(span == NULL)) { + return NULL; + } + + // Allocate stack trace + StackTrace *stack = Static::stacktrace_allocator()->New(); + if (PREDICT_FALSE(stack == NULL)) { + // Sampling failed because of lack of memory + return span; + } + *stack = tmp; + span->sample = 1; + span->objects = stack; + tcmalloc::DLL_Prepend(Static::sampled_objects(), span); + + return SpanToMallocResult(span); +#else + abort(); +#endif +} + +namespace { + +typedef void* (*malloc_fn)(void *arg); + +SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED); + +void* handle_oom(malloc_fn retry_fn, + void* retry_arg, + bool from_operator, + bool nothrow) { + // we hit out of memory condition, usually if it happens we've + // called sbrk or mmap and failed, and thus errno is set. But there + // is support for setting up custom system allocator or setting up + // page heap size limit, in which cases errno may remain + // untouched. + // + // So we set errno here. C++ operator new doesn't require ENOMEM to + // be set, but doesn't forbid it too (and often C++ oom does happen + // with ENOMEM set). + errno = ENOMEM; + if (!from_operator && !tc_new_mode) { + // we're out of memory in C library function (malloc etc) and no + // "new mode" forced on us. Just return NULL + return NULL; + } + // we're OOM in operator new or "new mode" is set. We might have to + // call new_handle and maybe retry allocation. + + for (;;) { + // Get the current new handler. NB: this function is not + // thread-safe. We make a feeble stab at making it so here, but + // this lock only protects against tcmalloc interfering with + // itself, not with other libraries calling set_new_handler. + std::new_handler nh; + { + SpinLockHolder h(&set_new_handler_lock); + nh = std::set_new_handler(0); + (void) std::set_new_handler(nh); + } +#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) + if (!nh) { + return NULL; + } + // Since exceptions are disabled, we don't really know if new_handler + // failed. Assume it will abort if it fails. + (*nh)(); +#else + // If no new_handler is established, the allocation failed. + if (!nh) { + if (nothrow) { + return NULL; + } + throw std::bad_alloc(); + } + // Otherwise, try the new_handler. If it returns, retry the + // allocation. If it throws std::bad_alloc, fail the allocation. + // if it throws something else, don't interfere. + try { + (*nh)(); + } catch (const std::bad_alloc&) { + if (!nothrow) throw; + return NULL; + } +#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) + + // we get here if new_handler returns successfully. So we retry + // allocation. + void* rv = retry_fn(retry_arg); + if (rv != NULL) { + return rv; + } + + // if allocation failed again we go to next loop iteration + } +} + +// Copy of FLAGS_tcmalloc_large_alloc_report_threshold with +// automatic increases factored in. +#ifdef ENABLE_LARGE_ALLOC_REPORT +static int64_t large_alloc_threshold = + (kPageSize > FLAGS_tcmalloc_large_alloc_report_threshold + ? kPageSize : FLAGS_tcmalloc_large_alloc_report_threshold); +#endif + +static void ReportLargeAlloc(Length num_pages, void* result) { + StackTrace stack; + stack.depth = GetStackTrace(stack.stack, tcmalloc::kMaxStackDepth, 1); + + static const int N = 1000; + char buffer[N]; + TCMalloc_Printer printer(buffer, N); + printer.printf("tcmalloc: large alloc %" PRIu64 " bytes == %p @ ", + static_cast(num_pages) << kPageShift, + result); + for (int i = 0; i < stack.depth; i++) { + printer.printf(" %p", stack.stack[i]); + } + printer.printf("\n"); + write(STDERR_FILENO, buffer, strlen(buffer)); +} + +// Must be called with the page lock held. +inline bool should_report_large(Length num_pages) { +#ifdef ENABLE_LARGE_ALLOC_REPORT + const int64 threshold = large_alloc_threshold; + if (threshold > 0 && num_pages >= (threshold >> kPageShift)) { + // Increase the threshold by 1/8 every time we generate a report. + // We cap the threshold at 8GiB to avoid overflow problems. + large_alloc_threshold = (threshold + threshold/8 < 8ll<<30 + ? threshold + threshold/8 : 8ll<<30); + return true; + } +#endif + return false; +} + +// Helper for do_malloc(). +static void* do_malloc_pages(ThreadCache* heap, size_t size) { + void* result; + bool report_large; + + Length num_pages = tcmalloc::pages(size); + + // NOTE: we're passing original size here as opposed to rounded-up + // size as we do in do_malloc_small. The difference is small here + // (at most 4k out of at least 256k). And not rounding up saves us + // from possibility of overflow, which rounding up could produce. + // + // See https://github.com/gperftools/gperftools/issues/723 + if (heap->SampleAllocation(size)) { + result = DoSampledAllocation(size); + + SpinLockHolder h(Static::pageheap_lock()); + report_large = should_report_large(num_pages); + } else { + SpinLockHolder h(Static::pageheap_lock()); + Span* span = Static::pageheap()->New(num_pages); + result = (PREDICT_FALSE(span == NULL) ? NULL : SpanToMallocResult(span)); + report_large = should_report_large(num_pages); + } + + if (report_large) { + ReportLargeAlloc(num_pages, result); + } + return result; +} + +static void *nop_oom_handler(size_t size) { + return NULL; +} + +ATTRIBUTE_ALWAYS_INLINE inline void* do_malloc(size_t size) { + if (PREDICT_FALSE(ThreadCache::IsUseEmergencyMalloc())) { + return tcmalloc::EmergencyMalloc(size); + } + + // note: it will force initialization of malloc if necessary + ThreadCache* cache = ThreadCache::GetCache(); + uint32 cl; + + ASSERT(Static::IsInited()); + ASSERT(cache != NULL); + + if (PREDICT_FALSE(!Static::sizemap()->GetSizeClass(size, &cl))) { + return do_malloc_pages(cache, size); + } + + size_t allocated_size = Static::sizemap()->class_to_size(cl); + if (PREDICT_FALSE(cache->SampleAllocation(allocated_size))) { + return DoSampledAllocation(size); + } + + // The common case, and also the simplest. This just pops the + // size-appropriate freelist, after replenishing it if it's empty. + return CheckedMallocResult(cache->Allocate(allocated_size, cl, nop_oom_handler)); +} + +static void *retry_malloc(void* size) { + return do_malloc(reinterpret_cast(size)); +} + +ATTRIBUTE_ALWAYS_INLINE inline void* do_malloc_or_cpp_alloc(size_t size) { + void *rv = do_malloc(size); + if (PREDICT_TRUE(rv != NULL)) { + return rv; + } + return handle_oom(retry_malloc, reinterpret_cast(size), + false, true); +} + +ATTRIBUTE_ALWAYS_INLINE inline void* do_calloc(size_t n, size_t elem_size) { + // Overflow check + const size_t size = n * elem_size; + if (elem_size != 0 && size / elem_size != n) return NULL; + + void* result = do_malloc_or_cpp_alloc(size); + if (result != NULL) { + memset(result, 0, tc_nallocx(size, 0)); + } + return result; +} + +// If ptr is NULL, do nothing. Otherwise invoke the given function. +inline void free_null_or_invalid(void* ptr, void (*invalid_free_fn)(void*)) { + if (ptr != NULL) { + (*invalid_free_fn)(ptr); + } +} + +static ATTRIBUTE_NOINLINE void do_free_pages(Span* span, void* ptr) { + SpinLockHolder h(Static::pageheap_lock()); + if (span->sample) { + StackTrace* st = reinterpret_cast(span->objects); + tcmalloc::DLL_Remove(span); + Static::stacktrace_allocator()->Delete(st); + span->objects = NULL; + } + Static::pageheap()->Delete(span); +} + +#ifndef NDEBUG +// note, with sized deletions we have no means to support win32 +// behavior where we detect "not ours" points and delegate them native +// memory management. This is because nature of sized deletes +// bypassing addr -> size class checks. So in this validation code we +// also assume that sized delete is always used with "our" pointers. +bool ValidateSizeHint(void* ptr, size_t size_hint) { + const PageID p = reinterpret_cast(ptr) >> kPageShift; + Span* span = Static::pageheap()->GetDescriptor(p); + uint32 cl = 0; + Static::sizemap()->GetSizeClass(size_hint, &cl); + return (span->sizeclass == cl); +} +#endif + +// Helper for the object deletion (free, delete, etc.). Inputs: +// ptr is object to be freed +// invalid_free_fn is a function that gets invoked on certain "bad frees" +// +// We can usually detect the case where ptr is not pointing to a page that +// tcmalloc is using, and in those cases we invoke invalid_free_fn. +ATTRIBUTE_ALWAYS_INLINE inline +void do_free_with_callback(void* ptr, + void (*invalid_free_fn)(void*), + bool use_hint, size_t size_hint) { + ThreadCache* heap = ThreadCache::GetCacheIfPresent(); + + const PageID p = reinterpret_cast(ptr) >> kPageShift; + uint32 cl; + + ASSERT(!use_hint || ValidateSizeHint(ptr, size_hint)); + + if (!use_hint || PREDICT_FALSE(!Static::sizemap()->GetSizeClass(size_hint, &cl))) { + // if we're in sized delete, but size is too large, no need to + // probe size cache + bool cache_hit = !use_hint && Static::pageheap()->TryGetSizeClass(p, &cl); + if (PREDICT_FALSE(!cache_hit)) { + Span* span = Static::pageheap()->GetDescriptor(p); + if (PREDICT_FALSE(!span)) { + // span can be NULL because the pointer passed in is NULL or invalid + // (not something returned by malloc or friends), or because the + // pointer was allocated with some other allocator besides + // tcmalloc. The latter can happen if tcmalloc is linked in via + // a dynamic library, but is not listed last on the link line. + // In that case, libraries after it on the link line will + // allocate with libc malloc, but free with tcmalloc's free. + free_null_or_invalid(ptr, invalid_free_fn); + return; + } + cl = span->sizeclass; + if (PREDICT_FALSE(cl == 0)) { + ASSERT(reinterpret_cast(ptr) % kPageSize == 0); + ASSERT(span != NULL && span->start == p); + do_free_pages(span, ptr); + return; + } + if (!use_hint) { + Static::pageheap()->SetCachedSizeClass(p, cl); + } + } + } + + if (PREDICT_TRUE(heap != NULL)) { + ASSERT(Static::IsInited()); + // If we've hit initialized thread cache, so we're done. + heap->Deallocate(ptr, cl); + return; + } + + if (PREDICT_FALSE(!Static::IsInited())) { + // if free was called very early we've could have missed the case + // of invalid or nullptr free. I.e. because probing size classes + // cache could return bogus result (cl = 0 as of this + // writing). But since there is no way we could be dealing with + // ptr we've allocated, since successfull malloc implies IsInited, + // we can just call "invalid free" handling code. + free_null_or_invalid(ptr, invalid_free_fn); + return; + } + + // Otherwise, delete directly into central cache + tcmalloc::SLL_SetNext(ptr, NULL); + Static::central_cache()[cl].InsertRange(ptr, ptr, 1); +} + +// The default "do_free" that uses the default callback. +ATTRIBUTE_ALWAYS_INLINE inline void do_free(void* ptr) { + return do_free_with_callback(ptr, &InvalidFree, false, 0); +} + +// NOTE: some logic here is duplicated in GetOwnership (above), for +// speed. If you change this function, look at that one too. +inline size_t GetSizeWithCallback(const void* ptr, + size_t (*invalid_getsize_fn)(const void*)) { + if (ptr == NULL) + return 0; + const PageID p = reinterpret_cast(ptr) >> kPageShift; + uint32 cl; + if (Static::pageheap()->TryGetSizeClass(p, &cl)) { + return Static::sizemap()->ByteSizeForClass(cl); + } + + const Span *span = Static::pageheap()->GetDescriptor(p); + if (PREDICT_FALSE(span == NULL)) { // means we do not own this memory + return (*invalid_getsize_fn)(ptr); + } + + if (span->sizeclass != 0) { + return Static::sizemap()->ByteSizeForClass(span->sizeclass); + } + + if (span->sample) { + size_t orig_size = reinterpret_cast(span->objects)->size; + return tc_nallocx(orig_size, 0); + } + + return span->length << kPageShift; +} + +// This lets you call back to a given function pointer if ptr is invalid. +// It is used primarily by windows code which wants a specialized callback. +ATTRIBUTE_ALWAYS_INLINE inline void* do_realloc_with_callback( + void* old_ptr, size_t new_size, + void (*invalid_free_fn)(void*), + size_t (*invalid_get_size_fn)(const void*)) { + // Get the size of the old entry + const size_t old_size = GetSizeWithCallback(old_ptr, invalid_get_size_fn); + + // Reallocate if the new size is larger than the old size, + // or if the new size is significantly smaller than the old size. + // We do hysteresis to avoid resizing ping-pongs: + // . If we need to grow, grow to max(new_size, old_size * 1.X) + // . Don't shrink unless new_size < old_size * 0.Y + // X and Y trade-off time for wasted space. For now we do 1.25 and 0.5. + const size_t min_growth = min(old_size / 4, + (std::numeric_limits::max)() - old_size); // Avoid overflow. + const size_t lower_bound_to_grow = old_size + min_growth; + const size_t upper_bound_to_shrink = old_size / 2ul; + if ((new_size > old_size) || (new_size < upper_bound_to_shrink)) { + // Need to reallocate. + void* new_ptr = NULL; + + if (new_size > old_size && new_size < lower_bound_to_grow) { + new_ptr = do_malloc_or_cpp_alloc(lower_bound_to_grow); + } + if (new_ptr == NULL) { + // Either new_size is not a tiny increment, or last do_malloc failed. + new_ptr = do_malloc_or_cpp_alloc(new_size); + } + if (PREDICT_FALSE(new_ptr == NULL)) { + return NULL; + } + MallocHook::InvokeNewHook(new_ptr, new_size); + memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size)); + MallocHook::InvokeDeleteHook(old_ptr); + // We could use a variant of do_free() that leverages the fact + // that we already know the sizeclass of old_ptr. The benefit + // would be small, so don't bother. + do_free_with_callback(old_ptr, invalid_free_fn, false, 0); + return new_ptr; + } else { + // We still need to call hooks to report the updated size: + MallocHook::InvokeDeleteHook(old_ptr); + MallocHook::InvokeNewHook(old_ptr, new_size); + return old_ptr; + } +} + +ATTRIBUTE_ALWAYS_INLINE inline void* do_realloc(void* old_ptr, size_t new_size) { + return do_realloc_with_callback(old_ptr, new_size, + &InvalidFree, &InvalidGetSizeForRealloc); +} + +static ATTRIBUTE_ALWAYS_INLINE inline +void* do_memalign_pages(size_t align, size_t size) { + ASSERT((align & (align - 1)) == 0); + ASSERT(align > kPageSize); + if (size + align < size) return NULL; // Overflow + + if (PREDICT_FALSE(Static::pageheap() == NULL)) ThreadCache::InitModule(); + + // Allocate at least one byte to avoid boundary conditions below + if (size == 0) size = 1; + + // We will allocate directly from the page heap + SpinLockHolder h(Static::pageheap_lock()); + + // Allocate extra pages and carve off an aligned portion + const Length alloc = tcmalloc::pages(size + align); + Span* span = Static::pageheap()->New(alloc); + if (PREDICT_FALSE(span == NULL)) return NULL; + + // Skip starting portion so that we end up aligned + Length skip = 0; + while ((((span->start+skip) << kPageShift) & (align - 1)) != 0) { + skip++; + } + ASSERT(skip < alloc); + if (skip > 0) { + Span* rest = Static::pageheap()->Split(span, skip); + Static::pageheap()->Delete(span); + span = rest; + } + + // Skip trailing portion that we do not need to return + const Length needed = tcmalloc::pages(size); + ASSERT(span->length >= needed); + if (span->length > needed) { + Span* trailer = Static::pageheap()->Split(span, needed); + Static::pageheap()->Delete(trailer); + } + return SpanToMallocResult(span); +} + +// Helpers for use by exported routines below: + +inline void do_malloc_stats() { + PrintStats(1); +} + +inline int do_mallopt(int cmd, int value) { + return 1; // Indicates error +} + +#ifdef HAVE_STRUCT_MALLINFO +inline struct mallinfo do_mallinfo() { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + + // Just some of the fields are filled in. + struct mallinfo info; + memset(&info, 0, sizeof(info)); + + // Unfortunately, the struct contains "int" field, so some of the + // size values will be truncated. + info.arena = static_cast(stats.pageheap.system_bytes); + info.fsmblks = static_cast(stats.thread_bytes + + stats.central_bytes + + stats.transfer_bytes); + info.fordblks = static_cast(stats.pageheap.free_bytes + + stats.pageheap.unmapped_bytes); + info.uordblks = static_cast(stats.pageheap.system_bytes + - stats.thread_bytes + - stats.central_bytes + - stats.transfer_bytes + - stats.pageheap.free_bytes + - stats.pageheap.unmapped_bytes); + + return info; +} +#endif // HAVE_STRUCT_MALLINFO + +} // end unnamed namespace + +// As promised, the definition of this function, declared above. +size_t TCMallocImplementation::GetAllocatedSize(const void* ptr) { + if (ptr == NULL) + return 0; + ASSERT(TCMallocImplementation::GetOwnership(ptr) + != TCMallocImplementation::kNotOwned); + return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize); +} + +void TCMallocImplementation::MarkThreadBusy() { + // Allocate to force the creation of a thread cache, but avoid + // invoking any hooks. + do_free(do_malloc(0)); +} + +//------------------------------------------------------------------- +// Exported routines +//------------------------------------------------------------------- + +extern "C" PERFTOOLS_DLL_DECL const char* tc_version( + int* major, int* minor, const char** patch) PERFTOOLS_NOTHROW { + if (major) *major = TC_VERSION_MAJOR; + if (minor) *minor = TC_VERSION_MINOR; + if (patch) *patch = TC_VERSION_PATCH; + return TC_VERSION_STRING; +} + +// This function behaves similarly to MSVC's _set_new_mode. +// If flag is 0 (default), calls to malloc will behave normally. +// If flag is 1, calls to malloc will behave like calls to new, +// and the std_new_handler will be invoked on failure. +// Returns the previous mode. +extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_NOTHROW { + int old_mode = tc_new_mode; + tc_new_mode = flag; + return old_mode; +} + +extern "C" PERFTOOLS_DLL_DECL int tc_query_new_mode() PERFTOOLS_NOTHROW { + return tc_new_mode; +} + +#ifndef TCMALLOC_USING_DEBUGALLOCATION // debugallocation.cc defines its own + +// 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 +// the call to the (de)allocation function. + +namespace tcmalloc { + + +static ATTRIBUTE_SECTION(google_malloc) +void invoke_hooks_and_free(void *ptr) { + MallocHook::InvokeDeleteHook(ptr); + do_free(ptr); +} + +ATTRIBUTE_SECTION(google_malloc) +void* cpp_throw_oom(size_t size) { + return handle_oom(retry_malloc, reinterpret_cast(size), + true, false); +} + +ATTRIBUTE_SECTION(google_malloc) +void* cpp_nothrow_oom(size_t size) { + return handle_oom(retry_malloc, reinterpret_cast(size), + true, true); +} + +ATTRIBUTE_SECTION(google_malloc) +void* malloc_oom(size_t size) { + return handle_oom(retry_malloc, reinterpret_cast(size), + false, true); +} + +// tcmalloc::allocate_full_XXX is called by fast-path malloc when some +// complex handling is needed (such as fetching object from central +// freelist or malloc sampling). It contains all 'operator new' logic, +// as opposed to malloc_fast_path which only deals with important +// subset of cases. +// +// Note that this is under tcmalloc namespace so that pprof +// can automatically filter it out of growthz/heapz profiles. +// +// We have slightly fancy setup because we need to call hooks from +// function in 'google_malloc' section and we cannot place template +// into this section. Thus 3 separate functions 'built' by macros. +// +// Also note that we're carefully orchestrating for +// MallocHook::GetCallerStackTrace to work even if compiler isn't +// optimizing tail calls (e.g. -O0 is given). We still require +// ATTRIBUTE_ALWAYS_INLINE to work for that case, but it was seen to +// work for -O0 -fno-inline across both GCC and clang. I.e. in this +// case we'll get stack frame for tc_new, followed by stack frame for +// allocate_full_cpp_throw_oom, followed by hooks machinery and user +// code's stack frames. So GetCallerStackTrace will find 2 +// subsequent stack frames in google_malloc section and correctly +// 'cut' stack trace just before tc_new. +template +ATTRIBUTE_ALWAYS_INLINE inline +static void* do_allocate_full(size_t size) { + void* p = do_malloc(size); + if (PREDICT_FALSE(p == NULL)) { + p = OOMHandler(size); + } + MallocHook::InvokeNewHook(p, size); + return CheckedMallocResult(p); +} + +#define AF(oom) \ + ATTRIBUTE_SECTION(google_malloc) \ + void* allocate_full_##oom(size_t size) { \ + return do_allocate_full(size); \ + } + +AF(cpp_throw_oom) +AF(cpp_nothrow_oom) +AF(malloc_oom) + +#undef AF + +template +static ATTRIBUTE_ALWAYS_INLINE inline void* dispatch_allocate_full(size_t size) { + if (OOMHandler == cpp_throw_oom) { + return allocate_full_cpp_throw_oom(size); + } + if (OOMHandler == cpp_nothrow_oom) { + return allocate_full_cpp_nothrow_oom(size); + } + ASSERT(OOMHandler == malloc_oom); + return allocate_full_malloc_oom(size); +} + +struct retry_memalign_data { + size_t align; + size_t size; +}; + +static void *retry_do_memalign(void *arg) { + retry_memalign_data *data = static_cast(arg); + return do_memalign_pages(data->align, data->size); +} + +static ATTRIBUTE_SECTION(google_malloc) +void* memalign_pages(size_t align, size_t size, + bool from_operator, bool nothrow) { + void *rv = do_memalign_pages(align, size); + if (PREDICT_FALSE(rv == NULL)) { + retry_memalign_data data; + data.align = align; + data.size = size; + rv = handle_oom(retry_do_memalign, &data, + from_operator, nothrow); + } + MallocHook::InvokeNewHook(rv, size); + return CheckedMallocResult(rv); +} + +} // namespace tcmalloc + +// This is quick, fast-path-only implementation of malloc/new. It is +// designed to only have support for fast-path. It checks if more +// complex handling is needed (such as a pageheap allocation or +// sampling) and only performs allocation if none of those uncommon +// conditions hold. When we have one of those odd cases it simply +// tail-calls to one of tcmalloc::allocate_full_XXX defined above. +// +// Such approach was found to be quite effective. Generated code for +// tc_{new,malloc} either succeeds quickly or tail-calls to +// allocate_full. Terseness of the source and lack of +// non-tail calls enables compiler to produce better code. Also +// produced code is short enough to enable effort-less human +// comprehension. Which itself led to elimination of various checks +// that were not necessary for fast-path. +template +ATTRIBUTE_ALWAYS_INLINE inline +static void * malloc_fast_path(size_t size) { + if (PREDICT_FALSE(!base::internal::new_hooks_.empty())) { + return tcmalloc::dispatch_allocate_full(size); + } + + ThreadCache *cache = ThreadCache::GetFastPathCache(); + + if (PREDICT_FALSE(cache == NULL)) { + return tcmalloc::dispatch_allocate_full(size); + } + + uint32 cl; + if (PREDICT_FALSE(!Static::sizemap()->GetSizeClass(size, &cl))) { + return tcmalloc::dispatch_allocate_full(size); + } + + size_t allocated_size = Static::sizemap()->ByteSizeForClass(cl); + + if (PREDICT_FALSE(!cache->TryRecordAllocationFast(allocated_size))) { + return tcmalloc::dispatch_allocate_full(size); + } + + return CheckedMallocResult(cache->Allocate(allocated_size, cl, OOMHandler)); +} + +template +ATTRIBUTE_ALWAYS_INLINE inline +static void* memalign_fast_path(size_t align, size_t size) { + if (PREDICT_FALSE(align > kPageSize)) { + if (OOMHandler == tcmalloc::cpp_throw_oom) { + return tcmalloc::memalign_pages(align, size, true, false); + } else if (OOMHandler == tcmalloc::cpp_nothrow_oom) { + return tcmalloc::memalign_pages(align, size, true, true); + } else { + ASSERT(OOMHandler == tcmalloc::malloc_oom); + return tcmalloc::memalign_pages(align, size, false, true); + } + } + + // Everything with alignment <= kPageSize we can easily delegate to + // regular malloc + + return malloc_fast_path(align_size_up(size, align)); +} + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void* tc_malloc(size_t size) PERFTOOLS_NOTHROW { + return malloc_fast_path(size); +} + +static ATTRIBUTE_ALWAYS_INLINE inline +void free_fast_path(void *ptr) { + if (PREDICT_FALSE(!base::internal::delete_hooks_.empty())) { + tcmalloc::invoke_hooks_and_free(ptr); + return; + } + do_free(ptr); +} + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void tc_free(void* ptr) PERFTOOLS_NOTHROW { + free_fast_path(ptr); +} + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW { + if (PREDICT_FALSE(!base::internal::delete_hooks_.empty())) { + tcmalloc::invoke_hooks_and_free(ptr); + return; + } +#ifndef NO_TCMALLOC_SAMPLES + // if ptr is kPageSize-aligned, then it could be sampled allocation, + // thus we don't trust hint and just do plain free. It also handles + // nullptr for us. + if (PREDICT_FALSE((reinterpret_cast(ptr) & (kPageSize-1)) == 0)) { + tc_free(ptr); + return; + } +#else + if (!ptr) { + return; + } +#endif + do_free_with_callback(ptr, &InvalidFree, true, size); +} + +#ifdef TC_ALIAS + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) PERFTOOLS_NOTHROW + TC_ALIAS(tc_free_sized); +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) PERFTOOLS_NOTHROW + TC_ALIAS(tc_free_sized); + +#else + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) PERFTOOLS_NOTHROW { + tc_free_sized(p, size); +} +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) PERFTOOLS_NOTHROW { + tc_free_sized(p, size); +} + +#endif + +extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n, + size_t elem_size) PERFTOOLS_NOTHROW { + if (ThreadCache::IsUseEmergencyMalloc()) { + return tcmalloc::EmergencyCalloc(n, elem_size); + } + void* result = do_calloc(n, elem_size); + MallocHook::InvokeNewHook(result, n * elem_size); + return result; +} + +extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_free); +#else +{ + free_fast_path(ptr); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* old_ptr, + size_t new_size) PERFTOOLS_NOTHROW { + if (old_ptr == NULL) { + void* result = do_malloc_or_cpp_alloc(new_size); + MallocHook::InvokeNewHook(result, new_size); + return result; + } + if (new_size == 0) { + MallocHook::InvokeDeleteHook(old_ptr); + do_free(old_ptr); + return NULL; + } + if (PREDICT_FALSE(tcmalloc::IsEmergencyPtr(old_ptr))) { + return tcmalloc::EmergencyRealloc(old_ptr, new_size); + } + return do_realloc(old_ptr, new_size); +} + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void* tc_new(size_t size) { + return malloc_fast_path(size); +} + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void* tc_new_nothrow(size_t size, const std::nothrow_t&) PERFTOOLS_NOTHROW { + return malloc_fast_path(size); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_free); +#else +{ + free_fast_path(p); +} +#endif + +// Standard C++ library implementations define and use this +// (via ::operator delete(ptr, nothrow)). +// But it's really the same as normal delete, so we just do the same thing. +extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_NOTHROW +{ + if (PREDICT_FALSE(!base::internal::delete_hooks_.empty())) { + tcmalloc::invoke_hooks_and_free(p); + return; + } + do_free(p); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) +#ifdef TC_ALIAS +TC_ALIAS(tc_new); +#else +{ + return malloc_fast_path(size); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) + PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_new_nothrow); +#else +{ + return malloc_fast_path(size); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_free); +#else +{ + free_fast_path(p); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_delete_nothrow); +#else +{ + free_fast_path(p); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL CACHELINE_ALIGNED_FN +void* tc_memalign(size_t align, size_t size) PERFTOOLS_NOTHROW { + return memalign_fast_path(align, size); +} + +extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign( + void** result_ptr, size_t align, size_t size) PERFTOOLS_NOTHROW { + if (((align % sizeof(void*)) != 0) || + ((align & (align - 1)) != 0) || + (align == 0)) { + return EINVAL; + } + + void* result = tc_memalign(align, size); + if (PREDICT_FALSE(result == NULL)) { + return ENOMEM; + } else { + *result_ptr = result; + return 0; + } +} + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + +extern "C" PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t align) { + return memalign_fast_path(static_cast(align), size); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t align, const std::nothrow_t&) PERFTOOLS_NOTHROW { + return memalign_fast_path(static_cast(align), size); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t) PERFTOOLS_NOTHROW +{ + free_fast_path(p); +} + +// There is no easy way to obtain the actual size used by do_memalign to allocate aligned storage, so for now +// just ignore the size. It might get useful in the future. +extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t align) PERFTOOLS_NOTHROW +{ + free_fast_path(p); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t, const std::nothrow_t&) PERFTOOLS_NOTHROW +{ + free_fast_path(p); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t align) +#ifdef TC_ALIAS +TC_ALIAS(tc_new_aligned); +#else +{ + return memalign_fast_path(static_cast(align), size); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t align, const std::nothrow_t& nt) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_new_aligned_nothrow); +#else +{ + return memalign_fast_path(static_cast(align), size); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_delete_aligned); +#else +{ + free_fast_path(p); +} +#endif + +// There is no easy way to obtain the actual size used by do_memalign to allocate aligned storage, so for now +// just ignore the size. It might get useful in the future. +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t align) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_delete_sized_aligned); +#else +{ + free_fast_path(p); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t, const std::nothrow_t&) PERFTOOLS_NOTHROW +#ifdef TC_ALIAS +TC_ALIAS(tc_delete_aligned_nothrow); +#else +{ + free_fast_path(p); +} +#endif + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + +static size_t pagesize = 0; + +extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) PERFTOOLS_NOTHROW { + // Allocate page-aligned object of length >= size bytes + if (pagesize == 0) pagesize = getpagesize(); + return tc_memalign(pagesize, size); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) PERFTOOLS_NOTHROW { + // Round up size to a multiple of pagesize + if (pagesize == 0) pagesize = getpagesize(); + if (size == 0) { // pvalloc(0) should allocate one page, according to + size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html + } + size = (size + pagesize - 1) & ~(pagesize - 1); + return tc_memalign(pagesize, size); +} + +extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW { + do_malloc_stats(); +} + +extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW { + return do_mallopt(cmd, value); +} + +#ifdef HAVE_STRUCT_MALLINFO +extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW { + return do_mallinfo(); +} +#endif + +extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW { + return MallocExtension::instance()->GetAllocatedSize(ptr); +} + +extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW { + void* result = do_malloc(size); + MallocHook::InvokeNewHook(result, size); + return result; +} + +#endif // TCMALLOC_USING_DEBUGALLOCATION diff --git a/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.h b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.h new file mode 100644 index 000000000..016c805d1 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc.h @@ -0,0 +1,70 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein +// +// Some obscure memory-allocation routines may not be declared on all +// systems. In those cases, we'll just declare them ourselves. +// This file is meant to be used only internally, for unittests. + +#include + +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 600 // for posix_memalign +#endif +#include // for posix_memalign +// FreeBSD has malloc.h, but complains if you use it +#if defined(HAVE_MALLOC_H) && !defined(__FreeBSD__) +#include // for memalign, valloc, pvalloc +#endif + +// __THROW is defined in glibc systems. It means, counter-intuitively, +// "This function will never throw an exception." It's an optional +// optimization tool, but we may need to use it to match glibc prototypes. +#ifndef __THROW // I guess we're not on a glibc system +# define __THROW // __THROW is just an optimization, so ok to make it "" +#endif + +#if !HAVE_DECL_CFREE +extern "C" void cfree(void* ptr) __THROW; +#endif +#if !HAVE_DECL_POSIX_MEMALIGN +extern "C" int posix_memalign(void** ptr, size_t align, size_t size) __THROW; +#endif +#if !HAVE_DECL_MEMALIGN +extern "C" void* memalign(size_t __alignment, size_t __size) __THROW; +#endif +#if !HAVE_DECL_VALLOC +extern "C" void* valloc(size_t __size) __THROW; +#endif +#if !HAVE_DECL_PVALLOC +extern "C" void* pvalloc(size_t __size) __THROW; +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/tcmalloc_guard.h b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc_guard.h new file mode 100644 index 000000000..84952bac2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tcmalloc_guard.h @@ -0,0 +1,49 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 +// +// We expose the TCMallocGuard class -- which initializes the tcmalloc +// allocator -- so classes that need to be sure tcmalloc is loaded +// before they do stuff -- notably heap-profiler -- can. To use this +// create a static TCMallocGuard instance at the top of a file where +// you need tcmalloc to be initialized before global constructors run. + +#ifndef TCMALLOC_TCMALLOC_GUARD_H_ +#define TCMALLOC_TCMALLOC_GUARD_H_ + +class TCMallocGuard { + public: + TCMallocGuard(); + ~TCMallocGuard(); +}; + +#endif // TCMALLOC_TCMALLOC_GUARD_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/addressmap_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/addressmap_unittest.cc new file mode 100644 index 000000000..45781f3a3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/addressmap_unittest.cc @@ -0,0 +1,174 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Sanjay Ghemawat + +#include // for rand() +#include +#include +#include +#include +#include +#include "addressmap-inl.h" +#include "base/logging.h" +#include "base/commandlineflags.h" + +DEFINE_int32(iters, 20, "Number of test iterations"); +DEFINE_int32(N, 100000, "Number of elements to test per iteration"); + +using std::pair; +using std::make_pair; +using std::vector; +using std::set; +using std::shuffle; + +struct UniformRandomNumberGenerator { + size_t Uniform(size_t max_size) { + if (max_size == 0) + return 0; + return rand() % max_size; // not a great random-number fn, but portable + } +}; +static UniformRandomNumberGenerator rnd; + + +// pair of associated value and object size +typedef pair ValueT; + +struct PtrAndSize { + char* ptr; + size_t size; + PtrAndSize(char* p, size_t s) : ptr(p), size(s) {} +}; + +size_t SizeFunc(const ValueT& v) { return v.second; } + +static void SetCheckCallback(const void* ptr, ValueT* val, + set >* check_set) { + check_set->insert(make_pair(ptr, val->first)); +} + +int main(int argc, char** argv) { + // Get a bunch of pointers + const int N = FLAGS_N; + static const int kMaxRealSize = 49; + // 100Mb to stress not finding previous object (AddressMap's cluster is 1Mb): + static const size_t kMaxSize = 100*1000*1000; + vector ptrs_and_sizes; + for (int i = 0; i < N; ++i) { + size_t s = rnd.Uniform(kMaxRealSize); + ptrs_and_sizes.push_back(PtrAndSize(new char[s], s)); + } + + for (int x = 0; x < FLAGS_iters; ++x) { + RAW_LOG(INFO, "Iteration %d/%d...\n", x, FLAGS_iters); + + // Permute pointers to get rid of allocation order issues + std::random_device rd; + std::mt19937 g(rd()); + shuffle(ptrs_and_sizes.begin(), ptrs_and_sizes.end(), g); + + AddressMap map(malloc, free); + const ValueT* result; + const void* res_p; + + // Insert a bunch of entries + for (int i = 0; i < N; ++i) { + char* p = ptrs_and_sizes[i].ptr; + CHECK(!map.Find(p)); + int offs = rnd.Uniform(ptrs_and_sizes[i].size); + CHECK(!map.FindInside(&SizeFunc, kMaxSize, p + offs, &res_p)); + map.Insert(p, make_pair(i, ptrs_and_sizes[i].size)); + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i); + CHECK(result = map.FindInside(&SizeFunc, kMaxRealSize, p + offs, &res_p)); + CHECK_EQ(res_p, p); + CHECK_EQ(result->first, i); + map.Insert(p, make_pair(i + N, ptrs_and_sizes[i].size)); + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i + N); + } + + // Delete the even entries + for (int i = 0; i < N; i += 2) { + void* p = ptrs_and_sizes[i].ptr; + ValueT removed; + CHECK(map.FindAndRemove(p, &removed)); + CHECK_EQ(removed.first, i + N); + } + + // Lookup the odd entries and adjust them + for (int i = 1; i < N; i += 2) { + char* p = ptrs_and_sizes[i].ptr; + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i + N); + int offs = rnd.Uniform(ptrs_and_sizes[i].size); + CHECK(result = map.FindInside(&SizeFunc, kMaxRealSize, p + offs, &res_p)); + CHECK_EQ(res_p, p); + CHECK_EQ(result->first, i + N); + map.Insert(p, make_pair(i + 2*N, ptrs_and_sizes[i].size)); + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i + 2*N); + } + + // Insert even entries back + for (int i = 0; i < N; i += 2) { + char* p = ptrs_and_sizes[i].ptr; + int offs = rnd.Uniform(ptrs_and_sizes[i].size); + CHECK(!map.FindInside(&SizeFunc, kMaxSize, p + offs, &res_p)); + map.Insert(p, make_pair(i + 2*N, ptrs_and_sizes[i].size)); + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i + 2*N); + CHECK(result = map.FindInside(&SizeFunc, kMaxRealSize, p + offs, &res_p)); + CHECK_EQ(res_p, p); + CHECK_EQ(result->first, i + 2*N); + } + + // Check all entries + set > check_set; + map.Iterate(SetCheckCallback, &check_set); + CHECK_EQ(check_set.size(), N); + for (int i = 0; i < N; ++i) { + void* p = ptrs_and_sizes[i].ptr; + check_set.erase(make_pair(p, i + 2*N)); + CHECK(result = map.Find(p)); + CHECK_EQ(result->first, i + 2*N); + } + CHECK_EQ(check_set.size(), 0); + } + + for (int i = 0; i < N; ++i) { + delete[] ptrs_and_sizes[i].ptr; + } + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/atomicops_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/atomicops_unittest.cc new file mode 100644 index 000000000..22be83958 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/atomicops_unittest.cc @@ -0,0 +1,152 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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: Sanjay Ghemawat + */ + +#include +#include "base/logging.h" +#include "base/atomicops.h" + +#define GG_ULONGLONG(x) static_cast(x) + + +#define NUM_BITS(T) (sizeof(T) * 8) + + +template +static void TestCompareAndSwap(AtomicType (*compare_and_swap_func) + (volatile AtomicType*, AtomicType, AtomicType)) { + AtomicType value = 0; + AtomicType prev = (*compare_and_swap_func)(&value, 0, 1); + ASSERT_EQ(1, value); + ASSERT_EQ(0, prev); + + // Use test value that has non-zero bits in both halves, more for testing + // 64-bit implementation on 32-bit platforms. + const AtomicType k_test_val = (GG_ULONGLONG(1) << + (NUM_BITS(AtomicType) - 2)) + 11; + value = k_test_val; + prev = (*compare_and_swap_func)(&value, 0, 5); + ASSERT_EQ(k_test_val, value); + ASSERT_EQ(k_test_val, prev); + + value = k_test_val; + prev = (*compare_and_swap_func)(&value, k_test_val, 5); + ASSERT_EQ(5, value); + ASSERT_EQ(k_test_val, prev); +} + + +template +static void TestAtomicExchange(AtomicType (*atomic_exchange_func) + (volatile AtomicType*, AtomicType)) { + AtomicType value = 0; + AtomicType new_value = (*atomic_exchange_func)(&value, 1); + ASSERT_EQ(1, value); + ASSERT_EQ(0, new_value); + + // Use test value that has non-zero bits in both halves, more for testing + // 64-bit implementation on 32-bit platforms. + const AtomicType k_test_val = (GG_ULONGLONG(1) << + (NUM_BITS(AtomicType) - 2)) + 11; + value = k_test_val; + new_value = (*atomic_exchange_func)(&value, k_test_val); + ASSERT_EQ(k_test_val, value); + ASSERT_EQ(k_test_val, new_value); + + value = k_test_val; + new_value = (*atomic_exchange_func)(&value, 5); + ASSERT_EQ(5, value); + ASSERT_EQ(k_test_val, new_value); +} + + +// This is a simple sanity check that values are correct. Not testing +// atomicity +template +static void TestStore() { + const AtomicType kVal1 = static_cast(0xa5a5a5a5a5a5a5a5LL); + const AtomicType kVal2 = static_cast(-1); + + AtomicType value; + + base::subtle::NoBarrier_Store(&value, kVal1); + ASSERT_EQ(kVal1, value); + base::subtle::NoBarrier_Store(&value, kVal2); + ASSERT_EQ(kVal2, value); + + base::subtle::Release_Store(&value, kVal1); + ASSERT_EQ(kVal1, value); + base::subtle::Release_Store(&value, kVal2); + ASSERT_EQ(kVal2, value); +} + +// This is a simple sanity check that values are correct. Not testing +// atomicity +template +static void TestLoad() { + const AtomicType kVal1 = static_cast(0xa5a5a5a5a5a5a5a5LL); + const AtomicType kVal2 = static_cast(-1); + + AtomicType value; + + value = kVal1; + ASSERT_EQ(kVal1, base::subtle::NoBarrier_Load(&value)); + value = kVal2; + ASSERT_EQ(kVal2, base::subtle::NoBarrier_Load(&value)); + + value = kVal1; + ASSERT_EQ(kVal1, base::subtle::Acquire_Load(&value)); + value = kVal2; + ASSERT_EQ(kVal2, base::subtle::Acquire_Load(&value)); +} + +template +static void TestAtomicOps() { + TestCompareAndSwap(base::subtle::NoBarrier_CompareAndSwap); + TestCompareAndSwap(base::subtle::Acquire_CompareAndSwap); + TestCompareAndSwap(base::subtle::Release_CompareAndSwap); + + TestAtomicExchange(base::subtle::NoBarrier_AtomicExchange); + TestAtomicExchange(base::subtle::Acquire_AtomicExchange); + TestAtomicExchange(base::subtle::Release_AtomicExchange); + + TestStore(); + TestLoad(); +} + +int main(int argc, char** argv) { + TestAtomicOps(); + TestAtomicOps(); + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/current_allocated_bytes_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/current_allocated_bytes_test.cc new file mode 100644 index 000000000..49b7dc34b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/current_allocated_bytes_test.cc @@ -0,0 +1,64 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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 tests the accounting done by tcmalloc. When we allocate and +// free a small buffer, the number of bytes used by the application +// before the alloc+free should match the number of bytes used after. +// However, the internal data structures used by tcmalloc will be +// quite different -- new spans will have been allocated, etc. This +// is, thus, a simple test that we account properly for the internal +// data structures, so that we report the actual application-used +// bytes properly. + +#include "config_for_unittests.h" +#include +#include +#include +#include "base/logging.h" + +int main() { + // We don't do accounting right when using debugallocation.cc, so + // turn off the test then. TODO(csilvers): get this working too. +#ifdef NDEBUG + static const char kCurrent[] = "generic.current_allocated_bytes"; + + size_t before_bytes, after_bytes; + MallocExtension::instance()->GetNumericProperty(kCurrent, &before_bytes); + free(malloc(200)); + MallocExtension::instance()->GetNumericProperty(kCurrent, &after_bytes); + + CHECK_EQ(before_bytes, after_bytes); +#endif + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.cc new file mode 100644 index 000000000..1e45db6ad --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.cc @@ -0,0 +1,333 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Fred Akalin + +#include +#include +#include // for memcmp +#include +#include "gperftools/malloc_extension.h" +#include "gperftools/tcmalloc.h" +#include "base/logging.h" +#include "tests/testutil.h" + +using std::vector; + +vector g_testlist; // the tests to run + +#define TEST(a, b) \ + struct Test_##a##_##b { \ + Test_##a##_##b() { g_testlist.push_back(&Run); } \ + static void Run(); \ + }; \ + static Test_##a##_##b g_test_##a##_##b; \ + void Test_##a##_##b::Run() + + +static int RUN_ALL_TESTS() { + vector::const_iterator it; + for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { + (*it)(); // The test will error-exit if there's a problem. + } + fprintf(stderr, "\nPassed %d tests\n\nPASS\n", + static_cast(g_testlist.size())); + return 0; +} + +// The death tests are meant to be run from a shell-script driver, which +// passes in an integer saying which death test to run. We store that +// test-to-run here, and in the macro use a counter to see when we get +// to that test, so we can run it. +static int test_to_run = 0; // set in main() based on argv +static int test_counter = 0; // incremented every time the macro is called +#define IF_DEBUG_EXPECT_DEATH(statement, regex) do { \ + if (test_counter++ == test_to_run) { \ + fprintf(stderr, "Expected regex:%s\n", regex); \ + statement; \ + } \ +} while (false) + +// This flag won't be compiled in in opt mode. +DECLARE_int32(max_free_queue_size); + +// Test match as well as mismatch rules. But do not test on OS X; on +// OS X the OS converts new/new[] to malloc before it gets to us, so +// we are unable to catch these mismatch errors. +#ifndef __APPLE__ +TEST(DebugAllocationTest, DeallocMismatch) { + // malloc can be matched only by free + // new can be matched only by delete and delete(nothrow) + // new[] can be matched only by delete[] and delete[](nothrow) + // new(nothrow) can be matched only by delete and delete(nothrow) + // new(nothrow)[] can be matched only by delete[] and delete[](nothrow) + + // Allocate with malloc. + { + int* x = static_cast(noopt(malloc(sizeof(*x)))); + IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); + IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); + // Should work fine. + free(x); + } + + // Allocate with new. + { + int* x = noopt(new int); + int* y = noopt(new int); + IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); + IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); + delete x; + ::operator delete(y, std::nothrow); + } + + // Allocate with new[]. + { + int* x = noopt(new int[1]); + int* y = noopt(new int[1]); + IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); + IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); + delete [] x; + ::operator delete[](y, std::nothrow); + } + + // Allocate with new(nothrow). + { + int* x = noopt(new (std::nothrow) int); + int* y = noopt(new (std::nothrow) int); + IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); + IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); + delete x; + ::operator delete(y, std::nothrow); + } + + // Allocate with new(nothrow)[]. + { + int* x = noopt(new (std::nothrow) int[1]); + int* y = noopt(new (std::nothrow) int[1]); + IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); + IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); + delete [] x; + ::operator delete[](y, std::nothrow); + } +} +#endif // #ifdef OS_MACOSX + +TEST(DebugAllocationTest, DoubleFree) { + int* pint = noopt(new int); + delete pint; + IF_DEBUG_EXPECT_DEATH(delete pint, "has been already deallocated"); +} + +TEST(DebugAllocationTest, StompBefore) { + int* pint = noopt(new int); +#ifndef NDEBUG // don't stomp memory if we're not in a position to detect it + pint[-1] = 5; + IF_DEBUG_EXPECT_DEATH(delete pint, "a word before object"); +#endif +} + +TEST(DebugAllocationTest, StompAfter) { + int* pint = noopt(new int); +#ifndef NDEBUG // don't stomp memory if we're not in a position to detect it + pint[1] = 5; + IF_DEBUG_EXPECT_DEATH(delete pint, "a word after object"); +#endif +} + +TEST(DebugAllocationTest, FreeQueueTest) { + // Verify that the allocator doesn't return blocks that were recently freed. + int* x = noopt(new int); + int* old_x = x; + delete x; + x = noopt(new int); + #if 1 + // This check should not be read as a universal guarantee of behavior. If + // other threads are executing, it would be theoretically possible for this + // check to fail despite the efforts of debugallocation.cc to the contrary. + // It should always hold under the controlled conditions of this unittest, + // however. + EXPECT_NE(x, old_x); // Allocator shouldn't return recently freed blocks + #else + // The below check passes, but since it isn't *required* to pass, I've left + // it commented out. + // EXPECT_EQ(x, old_x); + #endif + old_x = NULL; // avoid breaking opt build with an unused variable warning. + delete x; +} + +TEST(DebugAllocationTest, DanglingPointerWriteTest) { + // This test can only be run if debugging. + // + // If not debugging, the 'new' following the dangling write might not be + // safe. When debugging, we expect the (trashed) deleted block to be on the + // list of recently-freed blocks, so the following 'new' will be safe. +#if 1 + int* x = noopt(new int); + delete x; + int poisoned_x_value = *x; + *x = 1; // a dangling write. + + char* s = noopt(new char[FLAGS_max_free_queue_size]); + // When we delete s, we push the storage that was previously allocated to x + // off the end of the free queue. At that point, the write to that memory + // will be detected. + IF_DEBUG_EXPECT_DEATH(delete [] s, "Memory was written to after being freed."); + + // restore the poisoned value of x so that we can delete s without causing a + // crash. + *x = poisoned_x_value; + delete [] s; +#endif +} + +TEST(DebugAllocationTest, DanglingWriteAtExitTest) { + int *x = noopt(new int); + delete x; + int old_x_value = *x; + *x = 1; + // verify that dangling writes are caught at program termination if the + // corrupted block never got pushed off of the end of the free queue. + IF_DEBUG_EXPECT_DEATH(exit(0), "Memory was written to after being freed."); + *x = old_x_value; // restore x so that the test can exit successfully. +} + +TEST(DebugAllocationTest, StackTraceWithDanglingWriteAtExitTest) { + int *x = noopt(new int); + delete x; + int old_x_value = *x; + *x = 1; + // verify that we also get a stack trace when we have a dangling write. + // The " @ " is part of the stack trace output. + IF_DEBUG_EXPECT_DEATH(exit(0), " @ .*main"); + *x = old_x_value; // restore x so that the test can exit successfully. +} + +static size_t CurrentlyAllocatedBytes() { + size_t value; + CHECK(MallocExtension::instance()->GetNumericProperty( + "generic.current_allocated_bytes", &value)); + return value; +} + +TEST(DebugAllocationTest, CurrentlyAllocated) { + // Clear the free queue +#if 1 + FLAGS_max_free_queue_size = 0; + // Force a round-trip through the queue management code so that the + // new size is seen and the queue of recently-freed blocks is flushed. + free(noopt(malloc(1))); + FLAGS_max_free_queue_size = 1048576; +#endif + + // Free something and check that it disappears from allocated bytes + // immediately. + char* p = noopt(new char[1000]); + size_t after_malloc = CurrentlyAllocatedBytes(); + delete[] p; + size_t after_free = CurrentlyAllocatedBytes(); + EXPECT_LE(after_free, after_malloc - 1000); +} + +TEST(DebugAllocationTest, GetAllocatedSizeTest) { +#if 1 + // When debug_allocation is in effect, GetAllocatedSize should return + // exactly requested size, since debug_allocation doesn't allow users + // to write more than that. + for (int i = 0; i < 10; ++i) { + void *p = noopt(malloc(i)); + EXPECT_EQ(i, MallocExtension::instance()->GetAllocatedSize(p)); + free(p); + } +#endif + void* a = noopt(malloc(1000)); + EXPECT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000); + // This is just a sanity check. If we allocated too much, alloc is broken + EXPECT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000); + EXPECT_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000); + free(a); +} + +TEST(DebugAllocationTest, HugeAlloc) { + // This must not be a const variable so it doesn't form an + // integral-constant-expression which can be *statically* rejected by the + // compiler as too large for the allocation. + size_t kTooBig = ~static_cast(0); + void* a = NULL; + +#ifndef NDEBUG + + a = noopt(malloc(noopt(kTooBig))); + EXPECT_EQ(NULL, a); + + // kAlsoTooBig is small enough not to get caught by debugallocation's check, + // but will still fall through to tcmalloc's check. This must also be + // a non-const variable. See kTooBig for more details. + size_t kAlsoTooBig = kTooBig - 1024; + + a = noopt(malloc(noopt(kAlsoTooBig))); + EXPECT_EQ(NULL, a); +#endif +} + +// based on test program contributed by mikesart@gmail.com aka +// mikesart@valvesoftware.com. See issue-464. +TEST(DebugAllocationTest, ReallocAfterMemalign) { + char stuff[50]; + memset(stuff, 0x11, sizeof(stuff)); + void *p = tc_memalign(16, sizeof(stuff)); + EXPECT_NE(p, NULL); + memcpy(stuff, p, sizeof(stuff)); + + p = noopt(realloc(p, sizeof(stuff) + 10)); + EXPECT_NE(p, NULL); + + int rv = memcmp(stuff, p, sizeof(stuff)); + EXPECT_EQ(rv, 0); +} + +int main(int argc, char** argv) { + // If you run without args, we run the non-death parts of the test. + // Otherwise, argv[1] should be a number saying which death-test + // to run. We will output a regexp we expect the death-message + // to include, and then run the given death test (which hopefully + // will produce that error message). If argv[1] > the number of + // death tests, we will run only the non-death parts. One way to + // tell when you are done with all tests is when no 'expected + // regexp' message is printed for a given argv[1]. + if (argc < 2) { + test_to_run = -1; // will never match + } else { + test_to_run = atoi(argv[1]); + } + return RUN_ALL_TESTS(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.sh new file mode 100755 index 000000000..0f94ad084 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/debugallocation_test.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +# Copyright (c) 2009, 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 + +BINDIR="${BINDIR:-.}" +# We expect PPROF_PATH to be set in the environment. +# If not, we set it to some reasonable value +export PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir]" + echo " By default, unittest_dir=$BINDIR" + exit 1 +fi + +DEBUGALLOCATION_TEST="${1:-$BINDIR/debugallocation_test}" + +num_failures=0 + +# Run the i-th death test and make sure the test has the expected +# regexp. We can depend on the first line of the output being +# Expected regex: +# Evaluates to "done" if we are not actually a death-test (so $1 is +# too big a number, and we can stop). Evaluates to "" otherwise. +# Increments num_failures if the death test does not succeed. +OneDeathTest() { + "$DEBUGALLOCATION_TEST" "$1" 2>&1 | { + regex_line='dummy' + # Normally the regex_line is the first line of output, but not + # always (if tcmalloc itself does any logging to stderr). + while test -n "$regex_line"; do + read regex_line + regex=`expr "$regex_line" : "Expected regex:\(.*\)"` + test -n "$regex" && break # found the regex line + done + test -z "$regex" && echo "done" || grep "$regex" 2>&1 + } +} + +death_test_num=0 # which death test to run +while :; do # same as 'while true', but more portable + echo -n "Running death test $death_test_num..." + output="`OneDeathTest $death_test_num`" + case $output in + # Empty string means grep didn't find anything. + "") echo "FAILED"; num_failures=`expr $num_failures + 1`;; + "done"*) echo "done with death tests"; break;; + # Any other string means grep found something, like it ought to. + *) echo "OK";; + esac + death_test_num=`expr $death_test_num + 1` +done + +# Test the non-death parts of the test too +echo -n "Running non-death tests..." +if "$DEBUGALLOCATION_TEST"; then + echo "OK" +else + echo "FAILED" + num_failures=`expr $num_failures + 1` +fi + +if [ "$num_failures" = 0 ]; then + echo "PASS" +else + echo "Failed with $num_failures failures" +fi +exit $num_failures diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/frag_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/frag_unittest.cc new file mode 100644 index 000000000..6d2619f3e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/frag_unittest.cc @@ -0,0 +1,133 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2003, 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: Sanjay Ghemawat +// +// Test speed of handling fragmented heap + +#include "config_for_unittests.h" +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include // for struct timeval +#include // for getrusage +#endif +#ifdef _WIN32 +#include // for GetTickCount() +#endif +#include +#include "base/logging.h" +#include "common.h" +#include + +using std::vector; + +int main(int argc, char** argv) { + // Make kAllocSize one page larger than the maximum small object size. + static const int kAllocSize = kMaxSize + kPageSize; + // Allocate 400MB in total. + static const int kTotalAlloc = 400 << 20; + static const int kAllocIterations = kTotalAlloc / kAllocSize; + + // Allocate lots of objects + vector saved(kAllocIterations); + for (int i = 0; i < kAllocIterations; i++) { + saved[i] = new char[kAllocSize]; + } + + // Check the current "slack". + size_t slack_before; + MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes", + &slack_before); + + // Free alternating ones to fragment heap + size_t free_bytes = 0; + for (int i = 0; i < saved.size(); i += 2) { + delete[] saved[i]; + free_bytes += kAllocSize; + } + + // Check that slack delta is within 10% of expected. + size_t slack_after; + MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes", + &slack_after); + CHECK_GE(slack_after, slack_before); + size_t slack = slack_after - slack_before; + + CHECK_GT(double(slack), 0.9*free_bytes); + CHECK_LT(double(slack), 1.1*free_bytes); + + // Dump malloc stats + static const int kBufSize = 1<<20; + char* buffer = new char[kBufSize]; + MallocExtension::instance()->GetStats(buffer, kBufSize); + VLOG(1, "%s", buffer); + delete[] buffer; + + // Now do timing tests + for (int i = 0; i < 5; i++) { + static const int kIterations = 100000; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage r; + getrusage(RUSAGE_SELF, &r); // figure out user-time spent on this + struct timeval tv_start = r.ru_utime; +#elif defined(_WIN32) + long long int tv_start = GetTickCount(); +#else +# error No way to calculate time on your system +#endif + + for (int i = 0; i < kIterations; i++) { + size_t s; + MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes", + &s); + } + +#ifdef HAVE_SYS_RESOURCE_H + getrusage(RUSAGE_SELF, &r); + struct timeval tv_end = r.ru_utime; + int64 sumsec = static_cast(tv_end.tv_sec) - tv_start.tv_sec; + int64 sumusec = static_cast(tv_end.tv_usec) - tv_start.tv_usec; +#elif defined(_WIN32) + long long int tv_end = GetTickCount(); + int64 sumsec = (tv_end - tv_start) / 1000; + // Resolution in windows is only to the millisecond, alas + int64 sumusec = ((tv_end - tv_start) % 1000) * 1000; +#else +# error No way to calculate time on your system +#endif + fprintf(stderr, "getproperty: %6.1f ns/call\n", + (sumsec * 1e9 + sumusec * 1e3) / kIterations); + } + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/getpc_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/getpc_test.cc new file mode 100644 index 000000000..d75e40bb0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/getpc_test.cc @@ -0,0 +1,123 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 +#include +#include +#include // 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(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, ppc64v1, 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. + // NOTE: ppc64 ELFv2 (Little Endian) does not have function pointers +#if defined(__ia64) || \ + (defined(__powerpc64__) && _CALL_ELF != 2) + 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/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker-death_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker-death_unittest.sh new file mode 100755 index 000000000..69db0c9e0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker-death_unittest.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# 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: Maxim Lifantsev +# +# Run the heap checker unittest in a mode where it is supposed to crash and +# return an error if it doesn't. + +# We expect BINDIR to be set in the environment. +# If not, we set it to some reasonable value. +BINDIR="${BINDIR:-.}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir]" + echo " By default, unittest_dir=$BINDIR" + exit 1 +fi + +EXE="${1:-$BINDIR/heap-checker_unittest}" +TMPDIR="/tmp/heap_check_death_info" + +ALARM() { + # You need perl to run pprof, so I assume it's installed + perl -e ' + $timeout=$ARGV[0]; shift; + $retval = 255; # the default retval, for the case where we timed out + eval { # need to run in an eval-block to trigger during system() + local $SIG{ALRM} = sub { die "alarm\n" }; # \n is required! + alarm $timeout; + $retval = system(@ARGV); + # Make retval bash-style: exit status, or 128+n if terminated by signal n + $retval = ($retval & 127) ? (128 + $retval) : ($retval >> 8); + alarm 0; + }; + exit $retval; # return system()-retval, or 255 if system() never returned +' "$@" +} + +# $1: timeout for alarm; +# $2: regexp of expected exit code(s); +# $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 +Test() { + # Note: make sure these varnames don't conflict with any vars outside Test()! + timeout="$1" + shift + expected_ec="$1" + shift + expected_regexp="$1" + shift + unexpected_regexp="$1" + shift + + echo -n "Testing $EXE with $@ ... " + output="$TMPDIR/output" + ALARM $timeout env "$@" $EXE > "$output" 2>&1 + actual_ec=$? + ec_ok=`expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false` + matches_ok=`test -z "$expected_regexp" || \ + grep "$expected_regexp" "$output" >/dev/null 2>&1 || echo false` + negmatches_ok=`test -z "$unexpected_regexp" || \ + ! grep "$unexpected_regexp" "$output" >/dev/null 2>&1 || echo false` + if $ec_ok && $matches_ok && $negmatches_ok; then + echo "PASS" + return 0 # 0: success + fi + # If we get here, we failed. Now we just need to report why + echo "FAIL" + if [ $actual_ec -eq 255 ]; then # 255 == SIGTERM due to $ALARM + echo "Test was taking unexpectedly long time to run and so we aborted it." + echo "Try the test case manually or raise the timeout from $timeout" + echo "to distinguish test slowness from a real problem." + else + $ec_ok || \ + echo "Wrong exit code: expected: '$expected_ec'; actual: $actual_ec" + $matches_ok || \ + echo "Output did not match '$expected_regexp'" + $negmatches_ok || \ + echo "Output unexpectedly matched '$unexpected_regexp'" + fi + echo "Output from failed run:" + echo "---" + cat "$output" + echo "---" + return 1 # 1: failure +} + +TMPDIR=/tmp/heap_check_death_info +rm -rf $TMPDIR || exit 1 +mkdir $TMPDIR || exit 2 + +export HEAPCHECK=strict # default mode + +# These invocations should pass (0 == PASS): + +# This tests that turning leak-checker off dynamically works fine +Test 120 0 "^PASS$" "" HEAPCHECK="" || exit 1 + +# This disables threads so we can cause leaks reliably and test finding them +Test 120 0 "^PASS$" "" HEAP_CHECKER_TEST_NO_THREADS=1 || exit 2 + +# Test that --test_cancel_global_check works +Test 20 0 "Canceling .* whole-program .* leak check$" "" \ + HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 3 +Test 20 0 "Canceling .* whole-program .* leak check$" "" \ + HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 4 + +# Test that very early log messages are present and controllable: +EARLY_MSG="Starting tracking the heap$" + +Test 60 0 "$EARLY_MSG" "" \ + HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ + PERFTOOLS_VERBOSE=10 || exit 5 +Test 60 0 "MemoryRegionMap Init$" "" \ + HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ + PERFTOOLS_VERBOSE=11 || exit 6 +Test 60 0 "" "$EARLY_MSG" \ + HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ + PERFTOOLS_VERBOSE=-11 || exit 7 + +# These invocations should fail with very high probability, +# rather than return 0 or hang (1 == exit(1), 134 == abort(), 139 = SIGSEGV): + +Test 60 1 "Exiting .* because of .* leaks$" "" \ + HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 8 +Test 60 1 "Exiting .* because of .* leaks$" "" \ + HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 9 + +# Test that we produce a reasonable textual leak report. +Test 60 1 "MakeALeak" "" \ + HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ + || exit 10 + +# Test that very early log messages are present and controllable: +Test 60 1 "Starting tracking the heap$" "" \ + HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=10 \ + || exit 11 +Test 60 1 "" "Starting tracking the heap" \ + HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=-10 \ + || exit 12 + +cd / # so we're not in TMPDIR when we delete it +rm -rf $TMPDIR + +echo "PASS" + +exit 0 diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.cc new file mode 100644 index 000000000..b4bcb5265 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.cc @@ -0,0 +1,1538 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Maxim Lifantsev +// +// Running: +// ./heap-checker_unittest +// +// If the unittest crashes because it can't find pprof, try: +// PPROF_PATH=/usr/local/someplace/bin/pprof ./heap-checker_unittest +// +// To test that the whole-program heap checker will actually cause a leak, try: +// HEAPCHECK_TEST_LEAK= ./heap-checker_unittest +// HEAPCHECK_TEST_LOOP_LEAK= ./heap-checker_unittest +// +// Note: Both of the above commands *should* abort with an error message. + +// CAVEAT: Do not use vector<> and string on-heap objects in this test, +// otherwise the test can sometimes fail for tricky leak checks +// when we want some allocated object not to be found live by the heap checker. +// This can happen with memory allocators like tcmalloc that can allocate +// heap objects back to back without any book-keeping data in between. +// What happens is that end-of-storage pointers of a live vector +// (or a string depending on the STL implementation used) +// can happen to point to that other heap-allocated +// object that is not reachable otherwise and that +// we don't want to be reachable. +// +// The implication of this for real leak checking +// is just one more chance for the liveness flood to be inexact +// (see the comment in our .h file). + +#include "config_for_unittests.h" +#ifdef HAVE_POLL_H +#include +#endif +#if defined HAVE_STDINT_H +#include // to get uint16_t (ISO naming madness) +#elif defined HAVE_INTTYPES_H +#include // another place uint16_t might be defined +#endif +#include +#include +#include // errno +#ifdef HAVE_UNISTD_H +#include // for sleep(), geteuid() +#endif +#ifdef HAVE_MMAP +#include +#endif +#include // for open(), close() +#ifdef HAVE_EXECINFO_H +#include // backtrace +#endif +#ifdef HAVE_GRP_H +#include // getgrent, getgrnam +#endif +#ifdef HAVE_PWD_H +#include +#endif + +#include +#include // for cout +#include // for hex +#include +#include +#include +#include +#include +#include + +#include "base/commandlineflags.h" +#include "base/googleinit.h" +#include "base/logging.h" +#include "base/commandlineflags.h" +#include "base/thread_lister.h" +#include +#include "memory_region_map.h" +#include +#include + +// 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; + +// ========================================================================= // + +// TODO(maxim): write a shell script to test that these indeed crash us +// (i.e. we do detect leaks) +// Maybe add more such crash tests. + +DEFINE_bool(test_leak, + EnvToBool("HEAP_CHECKER_TEST_TEST_LEAK", false), + "If should cause a leak crash"); +DEFINE_bool(test_loop_leak, + EnvToBool("HEAP_CHECKER_TEST_TEST_LOOP_LEAK", false), + "If should cause a looped leak crash"); +DEFINE_bool(test_register_leak, + EnvToBool("HEAP_CHECKER_TEST_TEST_REGISTER_LEAK", false), + "If should cause a leak crash by hiding a pointer " + "that is only in a register"); +DEFINE_bool(test_cancel_global_check, + EnvToBool("HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK", false), + "If should test HeapLeakChecker::CancelGlobalCheck " + "when --test_leak or --test_loop_leak are given; " + "the test should not fail then"); +DEFINE_bool(maybe_stripped, + EnvToBool("HEAP_CHECKER_TEST_MAYBE_STRIPPED", true), + "If we think we can be a stripped binary"); +DEFINE_bool(interfering_threads, + EnvToBool("HEAP_CHECKER_TEST_INTERFERING_THREADS", true), + "If we should use threads trying " + "to interfere with leak checking"); +DEFINE_bool(hoarding_threads, + EnvToBool("HEAP_CHECKER_TEST_HOARDING_THREADS", true), + "If threads (usually the manager thread) are known " + "to retain some old state in their global buffers, " + "so that it's hard to force leaks when threads are around"); + // TODO(maxim): Chage the default to false + // when the standard environment used NTPL threads: + // they do not seem to have this problem. +DEFINE_bool(no_threads, + EnvToBool("HEAP_CHECKER_TEST_NO_THREADS", false), + "If we should not use any threads"); + // This is used so we can make can_create_leaks_reliably true + // for any pthread implementation and test with that. + +DECLARE_int64(heap_check_max_pointer_offset); // heap-checker.cc +DECLARE_string(heap_check); // in heap-checker.cc + +#define WARN_IF(cond, msg) LOG_IF(WARNING, cond, msg) + +// This is an evil macro! Be very careful using it... +#undef VLOG // and we start by evilling overriding logging.h VLOG +#define VLOG(lvl) if (FLAGS_verbose >= (lvl)) cout << "\n" +// This is, likewise, evil +#define LOGF VLOG(INFO) + +static void RunHeapBusyThreads(); // below + + +class Closure { + public: + virtual ~Closure() { } + virtual void Run() = 0; +}; + +class Callback0 : public Closure { + public: + typedef void (*FunctionSignature)(); + + inline Callback0(FunctionSignature f) : f_(f) {} + virtual void Run() { (*f_)(); delete this; } + + private: + FunctionSignature f_; +}; + +template class Callback1 : public Closure { + public: + typedef void (*FunctionSignature)(P1); + + inline Callback1(FunctionSignature f, P1 p1) : f_(f), p1_(p1) {} + virtual void Run() { (*f_)(p1_); delete this; } + + private: + FunctionSignature f_; + P1 p1_; +}; + +template class Callback2 : public Closure { + public: + typedef void (*FunctionSignature)(P1,P2); + + inline Callback2(FunctionSignature f, P1 p1, P2 p2) : f_(f), p1_(p1), p2_(p2) {} + virtual void Run() { (*f_)(p1_, p2_); delete this; } + + private: + FunctionSignature f_; + P1 p1_; + P2 p2_; +}; + +inline Callback0* NewCallback(void (*function)()) { + return new Callback0(function); +} + +template +inline Callback1* NewCallback(void (*function)(P1), P1 p1) { + return new Callback1(function, p1); +} + +template +inline Callback2* NewCallback(void (*function)(P1,P2), P1 p1, P2 p2) { + return new Callback2(function, p1, p2); +} + + +// Set to true at end of main, so threads know. Not entirely thread-safe!, +// but probably good enough. +static bool g_have_exited_main = false; + +// If we can reliably create leaks (i.e. make leaked object +// really unreachable from any global data). +static bool can_create_leaks_reliably = false; + +// We use a simple allocation wrapper +// to make sure we wipe out the newly allocated objects +// in case they still happened to contain some pointer data +// accidentally left by the memory allocator. +struct Initialized { }; +static Initialized initialized; +void* operator new(size_t size, const Initialized&) { + // Below we use "p = new(initialized) Foo[1];" and "delete[] p;" + // instead of "p = new(initialized) Foo;" + // when we need to delete an allocated object. + void* p = malloc(size); + memset(p, 0, size); + return p; +} +void* operator new[](size_t size, const Initialized&) { + char* p = new char[size]; + memset(p, 0, size); + return p; +} + +static void DoWipeStack(int n); // defined below +static void WipeStack() { DoWipeStack(20); } + +static void Pause() { + poll(NULL, 0, 77); // time for thread activity in HeapBusyThreadBody + + // Indirectly test malloc_extension.*: + CHECK(MallocExtension::instance()->VerifyAllMemory()); + int blocks; + size_t total; + int histogram[kMallocHistogramSize]; + if (MallocExtension::instance() + ->MallocMemoryStats(&blocks, &total, histogram) && total != 0) { + VLOG(3) << "Malloc stats: " << blocks << " blocks of " + << total << " bytes"; + for (int i = 0; i < kMallocHistogramSize; ++i) { + if (histogram[i]) { + VLOG(3) << " Malloc histogram at " << i << " : " << histogram[i]; + } + } + } + WipeStack(); // e.g. MallocExtension::VerifyAllMemory + // can leave pointers to heap objects on stack +} + +// Make gcc think a pointer is "used" +template +static void Use(T** foo) { + VLOG(2) << "Dummy-using " << static_cast(*foo) << " at " << foo; +} + +// Arbitrary value, but not such that xor'ing with it is likely +// to map one valid pointer to another valid pointer: +static const uintptr_t kHideMask = + static_cast(0xF03A5F7BF03A5F7BLL); + +// Helpers to hide a pointer from live data traversal. +// We just xor the pointer so that (with high probability) +// it's not a valid address of a heap object anymore. +// Both Hide and UnHide must be executed within RunHidden() below +// to prevent leaving stale data on active stack that can be a pointer +// to a heap object that is not actually reachable via live variables. +// (UnHide might leave heap pointer value for an object +// that will be deallocated but later another object +// can be allocated at the same heap address.) +template +static void Hide(T** ptr) { + // we cast values, not dereferenced pointers, so no aliasing issues: + *ptr = reinterpret_cast(reinterpret_cast(*ptr) ^ kHideMask); + VLOG(2) << "hid: " << static_cast(*ptr); +} + +template +static void UnHide(T** ptr) { + VLOG(2) << "unhiding: " << static_cast(*ptr); + // we cast values, not dereferenced pointers, so no aliasing issues: + *ptr = reinterpret_cast(reinterpret_cast(*ptr) ^ kHideMask); +} + +static void LogHidden(const char* message, const void* ptr) { + LOGF << message << " : " + << ptr << " ^ " << reinterpret_cast(kHideMask) << endl; +} + +// volatile to fool the compiler against inlining the calls to these +void (*volatile run_hidden_ptr)(Closure* c, int n); +void (*volatile wipe_stack_ptr)(int n); + +static void DoRunHidden(Closure* c, int n) { + if (n) { + VLOG(10) << "Level " << n << " at " << &n; + (*run_hidden_ptr)(c, n-1); + (*wipe_stack_ptr)(n); + sleep(0); // undo -foptimize-sibling-calls + } else { + c->Run(); + } +} + +/*static*/ void DoWipeStack(int n) { + VLOG(10) << "Wipe level " << n << " at " << &n; + if (n) { + const int sz = 30; + volatile int arr[sz] ATTRIBUTE_UNUSED; + for (int i = 0; i < sz; ++i) arr[i] = 0; + (*wipe_stack_ptr)(n-1); + sleep(0); // undo -foptimize-sibling-calls + } +} + +// This executes closure c several stack frames down from the current one +// and then makes an effort to also wipe out the stack data that was used by +// the closure. +// This way we prevent leak checker from finding any temporary pointers +// of the closure execution on the stack and deciding that +// these pointers (and the pointed objects) are still live. +static void RunHidden(Closure* c) { + DoRunHidden(c, 15); + DoWipeStack(20); +} + +static void DoAllocHidden(size_t size, void** ptr) { + void* p = new(initialized) char[size]; + Hide(&p); + Use(&p); // use only hidden versions + VLOG(2) << "Allocated hidden " << p << " at " << &p; + *ptr = p; // assign the hidden versions +} + +static void* AllocHidden(size_t size) { + void* r; + RunHidden(NewCallback(DoAllocHidden, size, &r)); + return r; +} + +static void DoDeAllocHidden(void** ptr) { + Use(ptr); // use only hidden versions + void* p = *ptr; + VLOG(2) << "Deallocating hidden " << p; + UnHide(&p); + delete [] reinterpret_cast(p); +} + +static void DeAllocHidden(void** ptr) { + RunHidden(NewCallback(DoDeAllocHidden, ptr)); + *ptr = NULL; + Use(ptr); +} + +void PreventHeapReclaiming(size_t size) { +#ifdef NDEBUG + if (true) { + static void** no_reclaim_list = NULL; + CHECK(size >= sizeof(void*)); + // We can't use malloc_reclaim_memory flag in opt mode as debugallocation.cc + // is not used. Instead we allocate a bunch of heap objects that are + // of the same size as what we are going to leak to ensure that the object + // we are about to leak is not at the same address as some old allocated + // and freed object that might still have pointers leading to it. + for (int i = 0; i < 100; ++i) { + void** p = reinterpret_cast(new(initialized) char[size]); + p[0] = no_reclaim_list; + no_reclaim_list = p; + } + } +#endif +} + +static bool RunSilent(HeapLeakChecker* check, + bool (HeapLeakChecker::* func)()) { + // By default, don't print the 'we detected a leak' message in the + // cases we're expecting a leak (we still print when --v is >= 1). + // This way, the logging output is less confusing: we only print + // "we detected a leak", and how to diagnose it, for *unexpected* leaks. + int32 old_FLAGS_verbose = FLAGS_verbose; + if (!VLOG_IS_ON(1)) // not on a verbose setting + FLAGS_verbose = FATAL; // only log fatal errors + const bool retval = (check->*func)(); + FLAGS_verbose = old_FLAGS_verbose; + return retval; +} + +#define RUN_SILENT(check, func) RunSilent(&(check), &HeapLeakChecker::func) + +enum CheckType { SAME_HEAP, NO_LEAKS }; + +static void VerifyLeaks(HeapLeakChecker* check, CheckType type, + int leaked_bytes, int leaked_objects) { + WipeStack(); // to help with can_create_leaks_reliably + const bool no_leaks = + type == NO_LEAKS ? RUN_SILENT(*check, BriefNoLeaks) + : RUN_SILENT(*check, BriefSameHeap); + if (can_create_leaks_reliably) { + // these might still fail occasionally, but it should be very rare + CHECK_EQ(no_leaks, false); + CHECK_EQ(check->BytesLeaked(), leaked_bytes); + CHECK_EQ(check->ObjectsLeaked(), leaked_objects); + } else { + WARN_IF(no_leaks != false, + "Expected leaks not found: " + "Some liveness flood must be too optimistic"); + } +} + +// not deallocates +static void TestHeapLeakCheckerDeathSimple() { + HeapLeakChecker check("death_simple"); + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + void* bar = AllocHidden(300); + Use(&bar); + LogHidden("Leaking", foo); + LogHidden("Leaking", bar); + Pause(); + VerifyLeaks(&check, NO_LEAKS, 300 + 100 * sizeof(int), 2); + DeAllocHidden(&foo); + DeAllocHidden(&bar); +} + +static void MakeDeathLoop(void** arr1, void** arr2) { + PreventHeapReclaiming(2 * sizeof(void*)); + void** a1 = new(initialized) void*[2]; + void** a2 = new(initialized) void*[2]; + a1[1] = reinterpret_cast(a2); + a2[1] = reinterpret_cast(a1); + Hide(&a1); + Hide(&a2); + Use(&a1); + Use(&a2); + VLOG(2) << "Made hidden loop at " << &a1 << " to " << arr1; + *arr1 = a1; + *arr2 = a2; +} + +// not deallocates two objects linked together +static void TestHeapLeakCheckerDeathLoop() { + HeapLeakChecker check("death_loop"); + void* arr1; + void* arr2; + RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2)); + Use(&arr1); + Use(&arr2); + LogHidden("Leaking", arr1); + LogHidden("Leaking", arr2); + Pause(); + VerifyLeaks(&check, NO_LEAKS, 4 * sizeof(void*), 2); + DeAllocHidden(&arr1); + DeAllocHidden(&arr2); +} + +// deallocates more than allocates +static void TestHeapLeakCheckerDeathInverse() { + void* bar = AllocHidden(250 * sizeof(int)); + Use(&bar); + LogHidden("Pre leaking", bar); + Pause(); + HeapLeakChecker check("death_inverse"); + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + LogHidden("Leaking", foo); + DeAllocHidden(&bar); + Pause(); + VerifyLeaks(&check, SAME_HEAP, + 100 * static_cast(sizeof(int)), + 1); + DeAllocHidden(&foo); +} + +// deallocates more than allocates +static void TestHeapLeakCheckerDeathNoLeaks() { + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + void* bar = AllocHidden(250 * sizeof(int)); + Use(&bar); + HeapLeakChecker check("death_noleaks"); + DeAllocHidden(&bar); + CHECK_EQ(check.BriefNoLeaks(), true); + DeAllocHidden(&foo); +} + +// have less objecs +static void TestHeapLeakCheckerDeathCountLess() { + void* bar1 = AllocHidden(50 * sizeof(int)); + Use(&bar1); + void* bar2 = AllocHidden(50 * sizeof(int)); + Use(&bar2); + LogHidden("Pre leaking", bar1); + LogHidden("Pre leaking", bar2); + Pause(); + HeapLeakChecker check("death_count_less"); + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + LogHidden("Leaking", foo); + DeAllocHidden(&bar1); + DeAllocHidden(&bar2); + Pause(); + VerifyLeaks(&check, SAME_HEAP, + 100 * sizeof(int), + 1); + DeAllocHidden(&foo); +} + +// have more objecs +static void TestHeapLeakCheckerDeathCountMore() { + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + LogHidden("Pre leaking", foo); + Pause(); + HeapLeakChecker check("death_count_more"); + void* bar1 = AllocHidden(50 * sizeof(int)); + Use(&bar1); + void* bar2 = AllocHidden(50 * sizeof(int)); + Use(&bar2); + LogHidden("Leaking", bar1); + LogHidden("Leaking", bar2); + DeAllocHidden(&foo); + Pause(); + VerifyLeaks(&check, SAME_HEAP, + 100 * sizeof(int), + 2); + DeAllocHidden(&bar1); + DeAllocHidden(&bar2); +} + +static void TestHiddenPointer() { + int i; + void* foo = &i; + HiddenPointer p(foo); + CHECK_EQ(foo, p.get()); + + // Confirm pointer doesn't appear to contain a byte sequence + // that == the pointer. We don't really need to test that + // the xor trick itself works, as without it nothing in this + // test suite would work. See the Hide/Unhide/*Hidden* set + // of helper methods. + void **pvoid = reinterpret_cast(&p); + CHECK_NE(foo, *pvoid); +} + +// simple tests that deallocate what they allocated +static void TestHeapLeakChecker() { + { HeapLeakChecker check("trivial"); + int foo = 5; + int* p = &foo; + Use(&p); + Pause(); + CHECK(check.BriefSameHeap()); + } + Pause(); + { HeapLeakChecker check("simple"); + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + void* bar = AllocHidden(200 * sizeof(int)); + Use(&bar); + DeAllocHidden(&foo); + DeAllocHidden(&bar); + Pause(); + CHECK(check.BriefSameHeap()); + } +} + +// no false positives +static void TestHeapLeakCheckerNoFalsePositives() { + { HeapLeakChecker check("trivial_p"); + int foo = 5; + int* p = &foo; + Use(&p); + Pause(); + CHECK(check.BriefSameHeap()); + } + Pause(); + { HeapLeakChecker check("simple_p"); + void* foo = AllocHidden(100 * sizeof(int)); + Use(&foo); + void* bar = AllocHidden(200 * sizeof(int)); + Use(&bar); + DeAllocHidden(&foo); + DeAllocHidden(&bar); + Pause(); + CHECK(check.SameHeap()); + } +} + +// test that we detect leaks when we have same total # of bytes and +// objects, but different individual object sizes +static void TestLeakButTotalsMatch() { + void* bar1 = AllocHidden(240 * sizeof(int)); + Use(&bar1); + void* bar2 = AllocHidden(160 * sizeof(int)); + Use(&bar2); + LogHidden("Pre leaking", bar1); + LogHidden("Pre leaking", bar2); + Pause(); + HeapLeakChecker check("trick"); + void* foo1 = AllocHidden(280 * sizeof(int)); + Use(&foo1); + void* foo2 = AllocHidden(120 * sizeof(int)); + Use(&foo2); + LogHidden("Leaking", foo1); + LogHidden("Leaking", foo2); + DeAllocHidden(&bar1); + DeAllocHidden(&bar2); + Pause(); + + // foo1 and foo2 leaked + VerifyLeaks(&check, NO_LEAKS, (280+120)*sizeof(int), 2); + + DeAllocHidden(&foo1); + DeAllocHidden(&foo2); +} + +// no false negatives from pprof +static void TestHeapLeakCheckerDeathTrick() { + void* bar1 = AllocHidden(240 * sizeof(int)); + Use(&bar1); + void* bar2 = AllocHidden(160 * sizeof(int)); + Use(&bar2); + HeapLeakChecker check("death_trick"); + DeAllocHidden(&bar1); + DeAllocHidden(&bar2); + void* foo1 = AllocHidden(280 * sizeof(int)); + Use(&foo1); + void* foo2 = AllocHidden(120 * sizeof(int)); + Use(&foo2); + // TODO(maxim): use the above if we make pprof work in automated test runs + if (!FLAGS_maybe_stripped) { + CHECK_EQ(RUN_SILENT(check, SameHeap), false); + // pprof checking should catch the leak + } else { + WARN_IF(RUN_SILENT(check, SameHeap) != false, + "death_trick leak is not caught; " + "we must be using a stripped binary"); + } + DeAllocHidden(&foo1); + DeAllocHidden(&foo2); +} + +// simple leak +static void TransLeaks() { + AllocHidden(1 * sizeof(char)); +} + +// range-based disabling using Disabler +static void ScopedDisabledLeaks() { + HeapLeakChecker::Disabler disabler; + AllocHidden(3 * sizeof(int)); + TransLeaks(); + (void)malloc(10); // Direct leak +} + +// have different disabled leaks +static void* RunDisabledLeaks(void* a) { + ScopedDisabledLeaks(); + return a; +} + +// have different disabled leaks inside of a thread +static void ThreadDisabledLeaks() { + if (FLAGS_no_threads) return; + pthread_t tid; + pthread_attr_t attr; + CHECK_EQ(pthread_attr_init(&attr), 0); + CHECK_EQ(pthread_create(&tid, &attr, RunDisabledLeaks, NULL), 0); + void* res; + CHECK_EQ(pthread_join(tid, &res), 0); +} + +// different disabled leaks (some in threads) +static void TestHeapLeakCheckerDisabling() { + HeapLeakChecker check("disabling"); + + RunDisabledLeaks(NULL); + RunDisabledLeaks(NULL); + ThreadDisabledLeaks(); + RunDisabledLeaks(NULL); + ThreadDisabledLeaks(); + ThreadDisabledLeaks(); + + Pause(); + + CHECK(check.SameHeap()); +} + +typedef set IntSet; + +static int some_ints[] = { 1, 2, 3, 21, 22, 23, 24, 25 }; + +static void DoTestSTLAlloc() { + IntSet* x = new(initialized) IntSet[1]; + *x = IntSet(some_ints, some_ints + 6); + for (int i = 0; i < 1000; i++) { + x->insert(i*3); + } + delete [] x; +} + +// Check that normal STL usage does not result in a leak report. +// (In particular we test that there's no complex STL's own allocator +// running on top of our allocator with hooks to heap profiler +// that can result in false leak report in this case.) +static void TestSTLAlloc() { + HeapLeakChecker check("stl"); + RunHidden(NewCallback(DoTestSTLAlloc)); + CHECK_EQ(check.BriefSameHeap(), true); +} + +static void DoTestSTLAllocInverse(IntSet** setx) { + IntSet* x = new(initialized) IntSet[1]; + *x = IntSet(some_ints, some_ints + 3); + for (int i = 0; i < 100; i++) { + x->insert(i*2); + } + Hide(&x); + *setx = x; +} + +static void FreeTestSTLAllocInverse(IntSet** setx) { + IntSet* x = *setx; + UnHide(&x); + delete [] x; +} + +// Check that normal leaked STL usage *does* result in a leak report. +// (In particular we test that there's no complex STL's own allocator +// running on top of our allocator with hooks to heap profiler +// that can result in false absence of leak report in this case.) +static void TestSTLAllocInverse() { + HeapLeakChecker check("death_inverse_stl"); + IntSet* x; + RunHidden(NewCallback(DoTestSTLAllocInverse, &x)); + LogHidden("Leaking", x); + if (can_create_leaks_reliably) { + WipeStack(); // to help with can_create_leaks_reliably + // these might still fail occasionally, but it should be very rare + CHECK_EQ(RUN_SILENT(check, BriefNoLeaks), false); + CHECK_GE(check.BytesLeaked(), 100 * sizeof(int)); + CHECK_GE(check.ObjectsLeaked(), 100); + // assumes set<>s are represented by some kind of binary tree + // or something else allocating >=1 heap object per set object + } else { + WARN_IF(RUN_SILENT(check, BriefNoLeaks) != false, + "Expected leaks not found: " + "Some liveness flood must be too optimistic"); + } + RunHidden(NewCallback(FreeTestSTLAllocInverse, &x)); +} + +template +static void DirectTestSTLAlloc(Alloc allocator, const char* name) { + HeapLeakChecker check((string("direct_stl-") + name).c_str()); + static const int kSize = 1000; + typename Alloc::value_type* ptrs[kSize]; + for (int i = 0; i < kSize; ++i) { + typename Alloc::value_type* p = allocator.allocate(i*3+1); + HeapLeakChecker::IgnoreObject(p); + // This will crash if p is not known to heap profiler: + // (i.e. STL's "allocator" does not have a direct hook to heap profiler) + HeapLeakChecker::UnIgnoreObject(p); + ptrs[i] = p; + } + for (int i = 0; i < kSize; ++i) { + allocator.deallocate(ptrs[i], i*3+1); + ptrs[i] = NULL; + } + CHECK(check.BriefSameHeap()); // just in case +} + +static struct group* grp = NULL; +static const int kKeys = 50; +static pthread_key_t key[kKeys]; + +static void KeyFree(void* ptr) { + delete [] reinterpret_cast(ptr); +} + +static bool key_init_has_run = false; + +static void KeyInit() { + for (int i = 0; i < kKeys; ++i) { + CHECK_EQ(pthread_key_create(&key[i], KeyFree), 0); + VLOG(2) << "pthread key " << i << " : " << key[i]; + } + key_init_has_run = true; // needed for a sanity-check +} + +// force various C library static and thread-specific allocations +static void TestLibCAllocate() { + CHECK(key_init_has_run); + for (int i = 0; i < kKeys; ++i) { + void* p = pthread_getspecific(key[i]); + if (NULL == p) { + if (i == 0) { + // Test-logging inside threads which (potentially) creates and uses + // thread-local data inside standard C++ library: + VLOG(0) << "Adding pthread-specifics for thread " << pthread_self() + << " pid " << getpid(); + } + p = new(initialized) char[77 + i]; + VLOG(2) << "pthread specific " << i << " : " << p; + pthread_setspecific(key[i], p); + } + } + + strerror(errno); + const time_t now = time(NULL); + ctime(&now); +#ifdef HAVE_EXECINFO_H + void *stack[1]; + backtrace(stack, 1); +#endif +#ifdef HAVE_GRP_H + gid_t gid = getgid(); + getgrgid(gid); + if (grp == NULL) grp = getgrent(); // a race condition here is okay + getgrnam(grp->gr_name); +#endif +#ifdef HAVE_PWD_H + getpwuid(geteuid()); +#endif +} + +// Continuous random heap memory activity to try to disrupt heap checking. +static void* HeapBusyThreadBody(void* a) { + const int thread_num = reinterpret_cast(a); + VLOG(0) << "A new HeapBusyThread " << thread_num; + TestLibCAllocate(); + + int user = 0; + // Try to hide ptr from heap checker in a CPU register: + // Here we are just making a best effort to put the only pointer + // to a heap object into a thread register to test + // the thread-register finding machinery in the heap checker. +#if defined(__i386__) && defined(__GNUC__) + register int** ptr asm("esi"); +#elif defined(__x86_64__) && defined(__GNUC__) + register int** ptr asm("r15"); +#else + register int** ptr; +#endif + ptr = NULL; + typedef set Set; + Set s1; + while (1) { + // TestLibCAllocate() calls libc functions that don't work so well + // after main() has exited. So we just don't do the test then. + if (!g_have_exited_main) + TestLibCAllocate(); + + if (ptr == NULL) { + ptr = new(initialized) int*[1]; + *ptr = new(initialized) int[1]; + } + set* s2 = new(initialized) set[1]; + s1.insert(random()); + s2->insert(*s1.begin()); + user += *s2->begin(); + **ptr += user; + if (random() % 51 == 0) { + s1.clear(); + if (random() % 2 == 0) { + s1.~Set(); + new(&s1) Set; + } + } + VLOG(3) << pthread_self() << " (" << getpid() << "): in wait: " + << ptr << ", " << *ptr << "; " << s1.size(); + VLOG(2) << pthread_self() << " (" << getpid() << "): in wait, ptr = " + << reinterpret_cast( + reinterpret_cast(ptr) ^ kHideMask) + << "^" << reinterpret_cast(kHideMask); + if (FLAGS_test_register_leak && thread_num % 5 == 0) { + // Hide the register "ptr" value with an xor mask. + // If one provides --test_register_leak flag, the test should + // (with very high probability) crash on some leak check + // with a leak report (of some x * sizeof(int) + y * sizeof(int*) bytes) + // pointing at the two lines above in this function + // with "new(initialized) int" in them as the allocators + // of the leaked objects. + // CAVEAT: We can't really prevent a compiler to save some + // temporary values of "ptr" on the stack and thus let us find + // the heap objects not via the register. + // Hence it's normal if for certain compilers or optimization modes + // --test_register_leak does not cause a leak crash of the above form + // (this happens e.g. for gcc 4.0.1 in opt mode). + ptr = reinterpret_cast( + reinterpret_cast(ptr) ^ kHideMask); + // busy loop to get the thread interrupted at: + for (int i = 1; i < 10000000; ++i) user += (1 + user * user * 5) / i; + ptr = reinterpret_cast( + reinterpret_cast(ptr) ^ kHideMask); + } else { + poll(NULL, 0, random() % 100); + } + VLOG(2) << pthread_self() << ": continuing"; + if (random() % 3 == 0) { + delete [] *ptr; + delete [] ptr; + ptr = NULL; + } + delete [] s2; + } + return a; +} + +static void RunHeapBusyThreads() { + KeyInit(); + if (!FLAGS_interfering_threads || FLAGS_no_threads) return; + + const int n = 17; // make many threads + + pthread_t tid; + pthread_attr_t attr; + CHECK_EQ(pthread_attr_init(&attr), 0); + // make them and let them run + for (int i = 0; i < n; ++i) { + VLOG(0) << "Creating extra thread " << i + 1; + CHECK(pthread_create(&tid, &attr, HeapBusyThreadBody, + reinterpret_cast(i)) == 0); + } + + Pause(); + Pause(); +} + +// ========================================================================= // + +// This code section is to test that objects that are reachable from global +// variables are not reported as leaks +// as well as that (Un)IgnoreObject work for such objects fine. + +// An object making functions: +// returns a "weird" pointer to a new object for which +// it's worth checking that the object is reachable via that pointer. +typedef void* (*ObjMakerFunc)(); +static list obj_makers; // list of registered object makers + +// Helper macro to register an object making function +// 'name' is an identifier of this object maker, +// 'body' is its function body that must declare +// pointer 'p' to the nex object to return. +// Usage example: +// REGISTER_OBJ_MAKER(trivial, int* p = new(initialized) int;) +#define REGISTER_OBJ_MAKER(name, body) \ + void* ObjMaker_##name##_() { \ + VLOG(1) << "Obj making " << #name; \ + body; \ + return p; \ + } \ + static ObjMakerRegistrar maker_reg_##name##__(&ObjMaker_##name##_); +// helper class for REGISTER_OBJ_MAKER +struct ObjMakerRegistrar { + ObjMakerRegistrar(ObjMakerFunc obj_maker) { obj_makers.push_back(obj_maker); } +}; + +// List of the objects/pointers made with all the obj_makers +// to test reachability via global data pointers during leak checks. +static list* live_objects = new list; + // pointer so that it does not get destructed on exit + +// Exerciser for one ObjMakerFunc. +static void TestPointerReach(ObjMakerFunc obj_maker) { + HeapLeakChecker::IgnoreObject(obj_maker()); // test IgnoreObject + + void* obj = obj_maker(); + HeapLeakChecker::IgnoreObject(obj); + HeapLeakChecker::UnIgnoreObject(obj); // test UnIgnoreObject + HeapLeakChecker::IgnoreObject(obj); // not to need deletion for obj + + live_objects->push_back(obj_maker()); // test reachability at leak check +} + +// Test all ObjMakerFunc registred via REGISTER_OBJ_MAKER. +static void TestObjMakers() { + for (list::const_iterator i = obj_makers.begin(); + i != obj_makers.end(); ++i) { + TestPointerReach(*i); + TestPointerReach(*i); // a couple more times would not hurt + TestPointerReach(*i); + } +} + +// A dummy class to mimic allocation behavior of string-s. +template +struct Array { + Array() { + size = 3 + random() % 30; + ptr = new(initialized) T[size]; + } + ~Array() { delete [] ptr; } + Array(const Array& x) { + size = x.size; + ptr = new(initialized) T[size]; + for (size_t i = 0; i < size; ++i) { + ptr[i] = x.ptr[i]; + } + } + void operator=(const Array& x) { + delete [] ptr; + size = x.size; + ptr = new(initialized) T[size]; + for (size_t i = 0; i < size; ++i) { + ptr[i] = x.ptr[i]; + } + } + void append(const Array& x) { + T* p = new(initialized) T[size + x.size]; + for (size_t i = 0; i < size; ++i) { + p[i] = ptr[i]; + } + for (size_t i = 0; i < x.size; ++i) { + p[size+i] = x.ptr[i]; + } + size += x.size; + delete [] ptr; + ptr = p; + } + private: + size_t size; + T* ptr; +}; + +// to test pointers to objects, built-in arrays, string, etc: +REGISTER_OBJ_MAKER(plain, int* p = new(initialized) int;) +REGISTER_OBJ_MAKER(int_array_1, int* p = new(initialized) int[1];) +REGISTER_OBJ_MAKER(int_array, int* p = new(initialized) int[10];) +REGISTER_OBJ_MAKER(string, Array* p = new(initialized) Array();) +REGISTER_OBJ_MAKER(string_array, + Array* p = new(initialized) Array[5];) +REGISTER_OBJ_MAKER(char_array, char* p = new(initialized) char[5];) +REGISTER_OBJ_MAKER(appended_string, + Array* p = new Array(); + p->append(Array()); +) +REGISTER_OBJ_MAKER(plain_ptr, int** p = new(initialized) int*;) +REGISTER_OBJ_MAKER(linking_ptr, + int** p = new(initialized) int*; + *p = new(initialized) int; +) + +// small objects: +REGISTER_OBJ_MAKER(0_sized, void* p = malloc(0);) // 0-sized object (important) +REGISTER_OBJ_MAKER(1_sized, void* p = malloc(1);) +REGISTER_OBJ_MAKER(2_sized, void* p = malloc(2);) +REGISTER_OBJ_MAKER(3_sized, void* p = malloc(3);) +REGISTER_OBJ_MAKER(4_sized, void* p = malloc(4);) + +static int set_data[] = { 1, 2, 3, 4, 5, 6, 7, 21, 22, 23, 24, 25, 26, 27 }; +static set live_leak_set(set_data, set_data+7); +static const set live_leak_const_set(set_data, set_data+14); + +REGISTER_OBJ_MAKER(set, + set* p = new(initialized) set(set_data, set_data + 13); +) + +class ClassA { + public: + explicit ClassA(int a) : ptr(NULL) { } + mutable char* ptr; +}; +static const ClassA live_leak_mutable(1); + +template +class TClass { + public: + explicit TClass(int a) : ptr(NULL) { } + mutable C val; + mutable C* ptr; +}; +static const TClass > live_leak_templ_mutable(1); + +class ClassB { + public: + ClassB() { } + char b[7]; + virtual void f() { } + virtual ~ClassB() { } +}; + +class ClassB2 { + public: + ClassB2() { } + char b2[11]; + virtual void f2() { } + virtual ~ClassB2() { } +}; + +class ClassD1 : public ClassB { + char d1[15]; + virtual void f() { } +}; + +class ClassD2 : public ClassB2 { + char d2[19]; + virtual void f2() { } +}; + +class ClassD : public ClassD1, public ClassD2 { + char d[3]; + virtual void f() { } + virtual void f2() { } +}; + +// to test pointers to objects of base subclasses: + +REGISTER_OBJ_MAKER(B, ClassB* p = new(initialized) ClassB;) +REGISTER_OBJ_MAKER(D1, ClassD1* p = new(initialized) ClassD1;) +REGISTER_OBJ_MAKER(D2, ClassD2* p = new(initialized) ClassD2;) +REGISTER_OBJ_MAKER(D, ClassD* p = new(initialized) ClassD;) + +REGISTER_OBJ_MAKER(D1_as_B, ClassB* p = new(initialized) ClassD1;) +REGISTER_OBJ_MAKER(D2_as_B2, ClassB2* p = new(initialized) ClassD2;) +REGISTER_OBJ_MAKER(D_as_B, ClassB* p = new(initialized) ClassD;) +REGISTER_OBJ_MAKER(D_as_D1, ClassD1* p = new(initialized) ClassD;) +// inside-object pointers: +REGISTER_OBJ_MAKER(D_as_B2, ClassB2* p = new(initialized) ClassD;) +REGISTER_OBJ_MAKER(D_as_D2, ClassD2* p = new(initialized) ClassD;) + +class InterfaceA { + public: + virtual void A() = 0; + virtual ~InterfaceA() { } + protected: + InterfaceA() { } +}; + +class InterfaceB { + public: + virtual void B() = 0; + virtual ~InterfaceB() { } + protected: + InterfaceB() { } +}; + +class InterfaceC : public InterfaceA { + public: + virtual void C() = 0; + virtual ~InterfaceC() { } + protected: + InterfaceC() { } +}; + +class ClassMltD1 : public ClassB, public InterfaceB, public InterfaceC { + public: + char d1[11]; + virtual void f() { } + virtual void A() { } + virtual void B() { } + virtual void C() { } +}; + +class ClassMltD2 : public InterfaceA, public InterfaceB, public ClassB { + public: + char d2[15]; + virtual void f() { } + virtual void A() { } + virtual void B() { } +}; + +// to specifically test heap reachability under +// inerface-only multiple inheritance (some use inside-object pointers): +REGISTER_OBJ_MAKER(MltD1, ClassMltD1* p = new(initialized) ClassMltD1;) +REGISTER_OBJ_MAKER(MltD1_as_B, ClassB* p = new(initialized) ClassMltD1;) +REGISTER_OBJ_MAKER(MltD1_as_IA, InterfaceA* p = new(initialized) ClassMltD1;) +REGISTER_OBJ_MAKER(MltD1_as_IB, InterfaceB* p = new(initialized) ClassMltD1;) +REGISTER_OBJ_MAKER(MltD1_as_IC, InterfaceC* p = new(initialized) ClassMltD1;) + +REGISTER_OBJ_MAKER(MltD2, ClassMltD2* p = new(initialized) ClassMltD2;) +REGISTER_OBJ_MAKER(MltD2_as_B, ClassB* p = new(initialized) ClassMltD2;) +REGISTER_OBJ_MAKER(MltD2_as_IA, InterfaceA* p = new(initialized) ClassMltD2;) +REGISTER_OBJ_MAKER(MltD2_as_IB, InterfaceB* p = new(initialized) ClassMltD2;) + +// to mimic UnicodeString defined in third_party/icu, +// which store a platform-independent-sized refcount in the first +// few bytes and keeps a pointer pointing behind the refcount. +REGISTER_OBJ_MAKER(unicode_string, + char* p = new char[sizeof(uint32) * 10]; + p += sizeof(uint32); +) +// similar, but for platform-dependent-sized refcount +REGISTER_OBJ_MAKER(ref_counted, + char* p = new char[sizeof(int) * 20]; + p += sizeof(int); +) + +struct Nesting { + struct Inner { + Nesting* parent; + Inner(Nesting* p) : parent(p) {} + }; + Inner i0; + char n1[5]; + Inner i1; + char n2[11]; + Inner i2; + char n3[27]; + Inner i3; + Nesting() : i0(this), i1(this), i2(this), i3(this) {} +}; + +// to test inside-object pointers pointing at objects nested into heap objects: +REGISTER_OBJ_MAKER(nesting_i0, Nesting::Inner* p = &((new Nesting())->i0);) +REGISTER_OBJ_MAKER(nesting_i1, Nesting::Inner* p = &((new Nesting())->i1);) +REGISTER_OBJ_MAKER(nesting_i2, Nesting::Inner* p = &((new Nesting())->i2);) +REGISTER_OBJ_MAKER(nesting_i3, Nesting::Inner* p = &((new Nesting())->i3);) + +void (* volatile init_forcer)(...); + +// allocate many objects reachable from global data +static void TestHeapLeakCheckerLiveness() { + live_leak_mutable.ptr = new(initialized) char[77]; + live_leak_templ_mutable.ptr = new(initialized) Array(); + live_leak_templ_mutable.val = Array(); + + // smart compiler may see that live_leak_mutable is not used + // anywhere so .ptr assignment is not used. + // + // We force compiler to assume that it is used by having function + // variable (set to 0 which hopefully won't be known to compiler) + // which gets address of those objects. So compiler has to assume + // that .ptr is used. + if (init_forcer) { + init_forcer(&live_leak_mutable, &live_leak_templ_mutable); + } + TestObjMakers(); +} + +// ========================================================================= // + +// Get address (PC value) following the mmap call into addr_after_mmap_call +static void* Mmapper(uintptr_t* addr_after_mmap_call) { + void* r = mmap(NULL, 100, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + // Get current PC value into addr_after_mmap_call + void* stack[1]; + CHECK_EQ(GetStackTrace(stack, 1, 0), 1); + *addr_after_mmap_call = reinterpret_cast(stack[0]); + sleep(0); // undo -foptimize-sibling-calls + return r; +} + +// On PPC64 the stacktrace returned by GetStatcTrace contains the function +// address from .text segment while function pointers points to ODP entries. +// The following code decodes the ODP to get the actual symbol address. +#if defined(__linux) && defined(__PPC64__) && (_CALL_ELF != 2) +static inline uintptr_t GetFunctionAddress (void* (*func)(uintptr_t*)) +{ + struct odp_entry_t { + unsigned long int symbol; + unsigned long int toc; + unsigned long int env; + } *odp_entry = reinterpret_cast(func); + + return static_cast(odp_entry->symbol); +} +#else +static inline uintptr_t GetFunctionAddress (void* (*func)(uintptr_t*)) +{ + return reinterpret_cast(func); +} +#endif + +// to trick complier into preventing inlining +static void* (* volatile mmapper_addr)(uintptr_t* addr) = &Mmapper; + +// TODO(maxim): copy/move this to memory_region_map_unittest +// TODO(maxim): expand this test to include mmap64, mremap and sbrk calls. +static void VerifyMemoryRegionMapStackGet() { + uintptr_t caller_addr_limit; + void* addr = (*mmapper_addr)(&caller_addr_limit); + uintptr_t caller = 0; + { MemoryRegionMap::LockHolder l; + for (MemoryRegionMap::RegionIterator + i = MemoryRegionMap::BeginRegionLocked(); + i != MemoryRegionMap::EndRegionLocked(); ++i) { + if (i->start_addr == reinterpret_cast(addr)) { + CHECK_EQ(caller, 0); + caller = i->caller(); + } + } + } + // caller must point into Mmapper function: + if (!(GetFunctionAddress(mmapper_addr) <= caller && + caller < caller_addr_limit)) { + LOGF << std::hex << "0x" << caller + << " does not seem to point into code of function Mmapper at " + << "0x" << reinterpret_cast(mmapper_addr) + << "! Stack frame collection must be off in MemoryRegionMap!"; + LOG(FATAL, "\n"); + } + munmap(addr, 100); +} + +static void* Mallocer(uintptr_t* addr_after_malloc_call) { + void* r = malloc(100); + sleep(0); // undo -foptimize-sibling-calls + // Get current PC value into addr_after_malloc_call + void* stack[1]; + CHECK_EQ(GetStackTrace(stack, 1, 0), 1); + *addr_after_malloc_call = reinterpret_cast(stack[0]); + return r; +} + +// to trick compiler into preventing inlining +static void* (* volatile mallocer_addr)(uintptr_t* addr) = &Mallocer; + +// non-static for friendship with HeapProfiler +// TODO(maxim): expand this test to include +// realloc, calloc, memalign, valloc, pvalloc, new, and new[]. +extern void VerifyHeapProfileTableStackGet() { + uintptr_t caller_addr_limit; + void* addr = (*mallocer_addr)(&caller_addr_limit); + uintptr_t caller = + reinterpret_cast(HeapLeakChecker::GetAllocCaller(addr)); + // caller must point into Mallocer function: + if (!(GetFunctionAddress(mallocer_addr) <= caller && + caller < caller_addr_limit)) { + LOGF << std::hex << "0x" << caller + << " does not seem to point into code of function Mallocer at " + << "0x" << reinterpret_cast(mallocer_addr) + << "! Stack frame collection must be off in heap profiler!"; + LOG(FATAL, "\n"); + } + free(addr); +} + +// ========================================================================= // + +static void MakeALeak(void** arr) { + PreventHeapReclaiming(10 * sizeof(int)); + void* a = new(initialized) int[10]; + Hide(&a); + *arr = a; +} + +// Helper to do 'return 0;' inside main(): insted we do 'return Pass();' +static int Pass() { + fprintf(stdout, "PASS\n"); + g_have_exited_main = true; + return 0; +} + +int main(int argc, char** argv) { + run_hidden_ptr = DoRunHidden; + wipe_stack_ptr = DoWipeStack; + if (!HeapLeakChecker::IsActive()) { + CHECK_EQ(FLAGS_heap_check, ""); + LOG(WARNING, "HeapLeakChecker got turned off; we won't test much..."); + } else { + VerifyMemoryRegionMapStackGet(); + VerifyHeapProfileTableStackGet(); + } + + KeyInit(); + + // glibc 2.4, on x86_64 at least, has a lock-ordering bug, which + // means deadlock is possible when one thread calls dl_open at the + // same time another thread is calling dl_iterate_phdr. libunwind + // calls dl_iterate_phdr, and TestLibCAllocate calls dl_open (or the + // various syscalls in it do), at least the first time it's run. + // To avoid the deadlock, we run TestLibCAllocate once before getting + // multi-threaded. + // TODO(csilvers): once libc is fixed, or libunwind can work around it, + // get rid of this early call. We *want* our test to + // find potential problems like this one! + TestLibCAllocate(); + + if (FLAGS_interfering_threads) { + RunHeapBusyThreads(); // add interference early + } + TestLibCAllocate(); + + LOGF << "In main(): heap_check=" << FLAGS_heap_check << endl; + + CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good + + if (FLAGS_test_leak) { + void* arr; + RunHidden(NewCallback(MakeALeak, &arr)); + Use(&arr); + LogHidden("Leaking", arr); + if (FLAGS_test_cancel_global_check) { + HeapLeakChecker::CancelGlobalCheck(); + } else { + // Verify we can call NoGlobalLeaks repeatedly without deadlocking + HeapLeakChecker::NoGlobalLeaks(); + HeapLeakChecker::NoGlobalLeaks(); + } + return Pass(); + // whole-program leak-check should (with very high probability) + // catch the leak of arr (10 * sizeof(int) bytes) + // (when !FLAGS_test_cancel_global_check) + } + + if (FLAGS_test_loop_leak) { + void* arr1; + void* arr2; + RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2)); + Use(&arr1); + Use(&arr2); + LogHidden("Loop leaking", arr1); + LogHidden("Loop leaking", arr2); + if (FLAGS_test_cancel_global_check) { + HeapLeakChecker::CancelGlobalCheck(); + } else { + // Verify we can call NoGlobalLeaks repeatedly without deadlocking + HeapLeakChecker::NoGlobalLeaks(); + HeapLeakChecker::NoGlobalLeaks(); + } + return Pass(); + // whole-program leak-check should (with very high probability) + // catch the leak of arr1 and arr2 (4 * sizeof(void*) bytes) + // (when !FLAGS_test_cancel_global_check) + } + + if (FLAGS_test_register_leak) { + // make us fail only where the .sh test expects: + Pause(); + for (int i = 0; i < 100; ++i) { // give it some time to crash + CHECK(HeapLeakChecker::NoGlobalLeaks()); + Pause(); + } + return Pass(); + } + + TestHeapLeakCheckerLiveness(); + + HeapLeakChecker heap_check("all"); + + TestHiddenPointer(); + + TestHeapLeakChecker(); + Pause(); + TestLeakButTotalsMatch(); + Pause(); + + TestHeapLeakCheckerDeathSimple(); + Pause(); + TestHeapLeakCheckerDeathLoop(); + Pause(); + TestHeapLeakCheckerDeathInverse(); + Pause(); + TestHeapLeakCheckerDeathNoLeaks(); + Pause(); + TestHeapLeakCheckerDeathCountLess(); + Pause(); + TestHeapLeakCheckerDeathCountMore(); + Pause(); + + TestHeapLeakCheckerDeathTrick(); + Pause(); + + CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good + + TestHeapLeakCheckerNoFalsePositives(); + Pause(); + + TestHeapLeakCheckerDisabling(); + Pause(); + + TestSTLAlloc(); + Pause(); + TestSTLAllocInverse(); + Pause(); + + // Test that various STL allocators work. Some of these are redundant, but + // we don't know how STL might change in the future. For example, + // http://wiki/Main/StringNeStdString. +#define DTSL(a) { DirectTestSTLAlloc(a, #a); \ + Pause(); } + DTSL(std::allocator()); + DTSL(std::allocator()); + DTSL(std::string().get_allocator()); + DTSL(string().get_allocator()); + DTSL(vector().get_allocator()); + DTSL(vector().get_allocator()); + DTSL(vector >().get_allocator()); + DTSL(vector().get_allocator()); + DTSL((map().get_allocator())); + DTSL((map().get_allocator())); + DTSL(set().get_allocator()); +#undef DTSL + + TestLibCAllocate(); + Pause(); + + CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good + + Pause(); + + if (!FLAGS_maybe_stripped) { + CHECK(heap_check.SameHeap()); + } else { + WARN_IF(heap_check.SameHeap() != true, + "overall leaks are caught; we must be using a stripped binary"); + } + + CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good + + return Pass(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.sh new file mode 100755 index 000000000..3c9c0e96f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-checker_unittest.sh @@ -0,0 +1,89 @@ +#!/bin/sh + +# 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 +# +# Runs the heap-checker unittest with various environment variables. +# This is necessary because we turn on features like the heap profiler +# and heap checker via environment variables. This test makes sure +# they all play well together. + +# We expect BINDIR and PPROF_PATH to be set in the environment. +# If not, we set them to some reasonable values +BINDIR="${BINDIR:-.}" +PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}" + +if [ "x$1" = "x-h" -o "$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir] [path to pprof]" + echo " By default, unittest_dir=$BINDIR, pprof_path=$PPROF_PATH" + exit 1 +fi + +HEAP_CHECKER="${1:-$BINDIR/heap-checker_unittest}" +PPROF_PATH="${2:-$PPROF_PATH}" + +TMPDIR=/tmp/heap_check_info +rm -rf $TMPDIR || exit 2 +mkdir $TMPDIR || exit 3 + +# $1: value of heap-check env. var. +run_check() { + export PPROF_PATH="$PPROF_PATH" + [ -n "$1" ] && export HEAPCHECK="$1" || unset HEAPPROFILE + + echo -n "Testing $HEAP_CHECKER with HEAPCHECK=$1 ... " + if $HEAP_CHECKER > $TMPDIR/output 2>&1; then + echo "OK" + else + echo "FAILED" + echo "Output from the failed run:" + echo "----" + cat $TMPDIR/output + echo "----" + exit 4 + fi + + # If we set HEAPPROFILE, then we expect it to actually have emitted + # a profile. Check that it did. + if [ -n "$HEAPPROFILE" ]; then + [ -e "$HEAPPROFILE.0001.heap" ] || exit 5 + fi +} + +run_check "" +run_check "local" +run_check "normal" +run_check "strict" + +rm -rf $TMPDIR # clean up + +echo "PASS" diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.cc new file mode 100644 index 000000000..addb5f17f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.cc @@ -0,0 +1,168 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 +// +// A small program that just exercises our heap profiler by allocating +// memory and letting the heap-profiler emit a profile. We don't test +// threads (TODO). By itself, this unittest tests that the heap-profiler +// doesn't crash on simple programs, but its output can be analyzed by +// another testing script to actually verify correctness. See, eg, +// heap-profiler_unittest.sh. + +#include "config_for_unittests.h" +#include +#include +#include // for mkdir() +#include // for mkdir() on freebsd and os x +#ifdef HAVE_UNISTD_H +#include // for fork() +#endif +#include // for wait() +#include +#include "base/basictypes.h" +#include "base/logging.h" +#include + +using std::string; + +static const int kMaxCount = 100000; +int* g_array[kMaxCount]; // an array of int-vectors + +static ATTRIBUTE_NOINLINE void Allocate(int start, int end, int size) { + // NOTE: we're using this to prevent gcc 5 from merging otherwise + // identical Allocate & Allocate2 functions. + VLOG(10, "Allocate"); + for (int i = start; i < end; ++i) { + if (i < kMaxCount) + g_array[i] = new int[size]; + } +} + +static ATTRIBUTE_NOINLINE void Allocate2(int start, int end, int size) { + VLOG(10, "Allocate2"); + for (int i = start; i < end; ++i) { + if (i < kMaxCount) + g_array[i] = new int[size]; + } +} + +static void Deallocate(int start, int end) { + for (int i = start; i < end; ++i) { + delete[] g_array[i]; + g_array[i] = 0; + } +} + +static void TestHeapProfilerStartStopIsRunning() { + // If you run this with whole-program heap-profiling on, than + // IsHeapProfilerRunning should return true. + if (!IsHeapProfilerRunning()) { + const char* tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + mkdir(tmpdir, 0755); // if necessary + HeapProfilerStart((string(tmpdir) + "/start_stop").c_str()); + CHECK(IsHeapProfilerRunning()); + + Allocate(0, 40, 100); + Deallocate(0, 40); + + HeapProfilerStop(); + CHECK(!IsHeapProfilerRunning()); + } +} + +static void TestDumpHeapProfiler() { + // If you run this with whole-program heap-profiling on, than + // IsHeapProfilerRunning should return true. + if (!IsHeapProfilerRunning()) { + const char* tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + mkdir(tmpdir, 0755); // if necessary + HeapProfilerStart((string(tmpdir) + "/dump").c_str()); + CHECK(IsHeapProfilerRunning()); + + Allocate(0, 40, 100); + Deallocate(0, 40); + + char* output = GetHeapProfile(); + free(output); + HeapProfilerStop(); + } +} + + +int main(int argc, char** argv) { + if (argc > 2 || (argc == 2 && argv[1][0] == '-')) { + printf("USAGE: %s [number of children to fork]\n", argv[0]); + exit(0); + } + int num_forks = 0; + if (argc == 2) { + num_forks = atoi(argv[1]); + } + + TestHeapProfilerStartStopIsRunning(); + TestDumpHeapProfiler(); + + Allocate(0, 40, 100); + Deallocate(0, 40); + + Allocate(0, 40, 100); + Allocate(0, 40, 100); + Allocate2(40, 400, 1000); + Allocate2(400, 1000, 10000); + Deallocate(0, 1000); + + Allocate(0, 100, 100000); + Deallocate(0, 10); + Deallocate(10, 20); + Deallocate(90, 100); + Deallocate(20, 90); + + while (num_forks-- > 0) { + switch (fork()) { + case -1: + printf("FORK failed!\n"); + return 1; + case 0: // child + return execl(argv[0], argv[0], NULL); // run child with no args + default: + wait(NULL); // we'll let the kids run one at a time + } + } + + printf("DONE.\n"); + + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.sh new file mode 100755 index 000000000..91af04f03 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/heap-profiler_unittest.sh @@ -0,0 +1,147 @@ +#!/bin/sh + +# 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 +# +# Runs the heap-profiler unittest and makes sure the profile looks appropriate. +# +# We run under the assumption that if $HEAP_PROFILER is run with --help, +# it prints a usage line of the form +# USAGE: [...] +# +# This is because libtool sometimes turns the 'executable' into a +# shell script which runs an actual binary somewhere else. + +# We expect BINDIR and PPROF_PATH to be set in the environment. +# If not, we set them to some reasonable values +BINDIR="${BINDIR:-.}" +PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir] [path to pprof]" + echo " By default, unittest_dir=$BINDIR, pprof_path=$PPROF_PATH" + exit 1 +fi + +HEAP_PROFILER="${1:-$BINDIR/heap-profiler_unittest}" +PPROF="${2:-$PPROF_PATH}" +TEST_TMPDIR=`mktemp -d /tmp/heap-profiler_unittest.XXXXXX` + +# It's meaningful to the profiler, so make sure we know its state +unset HEAPPROFILE + +num_failures=0 + +# Given one profile (to check the contents of that profile) or two +# profiles (to check the diff between the profiles), and a function +# name, verify that the function name takes up at least 90% of the +# allocated memory. The function name is actually specified first. +VerifyMemFunction() { + function="$1" + shift + + # get program name. Note we have to unset HEAPPROFILE so running + # help doesn't overwrite existing profiles. + exec=`unset HEAPPROFILE; $HEAP_PROFILER --help | awk '{print $2; exit;}'` + + if [ $# = 2 ]; then + [ -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 + [ -f "$1" ] || { echo "Profile not found: $1"; exit 1; } + $PPROF $exec "$1" >"$TEST_TMPDIR/output.pprof" 2>&1 + fi + + cat "$TEST_TMPDIR/output.pprof" \ + | tr -d % | awk '$6 ~ /^'$function'$/ && $2 > 90 {exit 1;}' + if [ $? != 1 ]; then + echo + echo "--- Test failed for $function: didn't account for 90% of executable memory" + echo "--- Program output:" + cat "$TEST_TMPDIR/output" + echo "--- pprof output:" + cat "$TEST_TMPDIR/output.pprof" + echo "---" + num_failures=`expr $num_failures + 1` + fi +} + +VerifyOutputContains() { + text="$1" + + if ! grep "$text" "$TEST_TMPDIR/output" >/dev/null 2>&1; then + echo "--- Test failed: output does not contain '$text'" + echo "--- Program output:" + cat "$TEST_TMPDIR/output" + echo "---" + num_failures=`expr $num_failures + 1` + fi +} + +HEAPPROFILE="$TEST_TMPDIR/test" +HEAP_PROFILE_INUSE_INTERVAL="10240" # need this to be 10Kb +HEAP_PROFILE_ALLOCATION_INTERVAL="$HEAP_PROFILE_INUSE_INTERVAL" +HEAP_PROFILE_DEALLOCATION_INTERVAL="$HEAP_PROFILE_INUSE_INTERVAL" +export HEAPPROFILE +export HEAP_PROFILE_INUSE_INTERVAL +export HEAP_PROFILE_ALLOCATION_INTERVAL +export HEAP_PROFILE_DEALLOCATION_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 +# parent's toes. If it does, we expect the parent-test to fail. +$HEAP_PROFILER 1 >$TEST_TMPDIR/output 2>&1 # run program, with 1 child proc + +VerifyMemFunction Allocate2 "$HEAPPROFILE.1329.heap" +VerifyMemFunction Allocate "$HEAPPROFILE.1448.heap" "$HEAPPROFILE.1548.heap" + +# Check the child process got to emit its own profile as well. +VerifyMemFunction Allocate2 "$HEAPPROFILE"_*.1329.heap +VerifyMemFunction Allocate "$HEAPPROFILE"_*.1448.heap "$HEAPPROFILE"_*.1548.heap + +# Make sure we logged both about allocating and deallocating memory +VerifyOutputContains "62 MB allocated" +VerifyOutputContains "62 MB freed" + +# Now try running without --heap_profile specified, to allow +# testing of the HeapProfileStart/Stop functionality. +$HEAP_PROFILER >"$TEST_TMPDIR/output2" 2>&1 + +rm -rf $TEST_TMPDIR # clean up + +if [ $num_failures = 0 ]; then + echo "PASS" +else + echo "Tests finished with $num_failures failures" +fi +exit $num_failures diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/large_heap_fragmentation_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/large_heap_fragmentation_unittest.cc new file mode 100644 index 000000000..08865997e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/large_heap_fragmentation_unittest.cc @@ -0,0 +1,62 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// This is a unit test for exercising fragmentation of large (over 1 +// meg) page spans. It makes sure that allocations/releases of +// increasing memory chunks do not blowup memory +// usage. See also https://code.google.com/p/gperftools/issues/detail?id=368 + + +#include +#include +#include + +#include "base/logging.h" +#include "common.h" +#include + + +int main (int argc, char** argv) { + for (int pass = 1; pass <= 3; pass++) { + size_t size = 100*1024*1024; + while (size < 500*1024*1024) { + void *ptr = malloc(size); + free(ptr); + size += 20000; + + size_t heap_size = static_cast(-1); + MallocExtension::instance()->GetNumericProperty("generic.heap_size", + &heap_size); + + + CHECK_LT(heap_size, 1*1024*1024*1024); + } + } + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/low_level_alloc_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/low_level_alloc_unittest.cc new file mode 100644 index 000000000..047444110 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/low_level_alloc_unittest.cc @@ -0,0 +1,197 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2006, 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. + */ + +// A test for low_level_alloc.cc + +#include +#include +#include "base/low_level_alloc.h" +#include "base/logging.h" +#include + +using std::map; + +// a block of memory obtained from the allocator +struct BlockDesc { + char *ptr; // pointer to memory + int len; // number of bytes + int fill; // filled with data starting with this +}; + +// Check that the pattern placed in the block d +// by RandomizeBlockDesc is still there. +static void CheckBlockDesc(const BlockDesc &d) { + for (int i = 0; i != d.len; i++) { + CHECK((d.ptr[i] & 0xff) == ((d.fill + i) & 0xff)); + } +} + +// Fill the block "*d" with a pattern +// starting with a random byte. +static void RandomizeBlockDesc(BlockDesc *d) { + d->fill = rand() & 0xff; + for (int i = 0; i != d->len; i++) { + d->ptr[i] = (d->fill + i) & 0xff; + } +} + +// Use to indicate to the malloc hooks that +// this calls is from LowLevelAlloc. +static bool using_low_level_alloc = false; + +// n times, toss a coin, and based on the outcome +// either allocate a new block or deallocate an old block. +// New blocks are placed in a map with a random key +// and initialized with RandomizeBlockDesc(). +// If keys conflict, the older block is freed. +// Old blocks are always checked with CheckBlockDesc() +// before being freed. At the end of the run, +// all remaining allocated blocks are freed. +// If use_new_arena is true, use a fresh arena, and then delete it. +// If call_malloc_hook is true and user_arena is true, +// allocations and deallocations are reported via the MallocHook +// interface. +static void Test(bool use_new_arena, bool call_malloc_hook, int n) { + typedef map AllocMap; + AllocMap allocated; + AllocMap::iterator it; + BlockDesc block_desc; + int rnd; + LowLevelAlloc::Arena *arena = 0; + if (use_new_arena) { + int32 flags = call_malloc_hook? LowLevelAlloc::kCallMallocHook : 0; + arena = LowLevelAlloc::NewArena(flags, LowLevelAlloc::DefaultArena()); + } + for (int i = 0; i != n; i++) { + if (i != 0 && i % 10000 == 0) { + printf("."); + fflush(stdout); + } + + switch(rand() & 1) { // toss a coin + case 0: // coin came up heads: add a block + using_low_level_alloc = true; + block_desc.len = rand() & 0x3fff; + block_desc.ptr = + reinterpret_cast( + arena == 0 + ? LowLevelAlloc::Alloc(block_desc.len) + : LowLevelAlloc::AllocWithArena(block_desc.len, arena)); + using_low_level_alloc = false; + RandomizeBlockDesc(&block_desc); + rnd = rand(); + it = allocated.find(rnd); + if (it != allocated.end()) { + CheckBlockDesc(it->second); + using_low_level_alloc = true; + LowLevelAlloc::Free(it->second.ptr); + using_low_level_alloc = false; + it->second = block_desc; + } else { + allocated[rnd] = block_desc; + } + break; + case 1: // coin came up tails: remove a block + it = allocated.begin(); + if (it != allocated.end()) { + CheckBlockDesc(it->second); + using_low_level_alloc = true; + LowLevelAlloc::Free(it->second.ptr); + using_low_level_alloc = false; + allocated.erase(it); + } + break; + } + } + // remove all remaniing blocks + while ((it = allocated.begin()) != allocated.end()) { + CheckBlockDesc(it->second); + using_low_level_alloc = true; + LowLevelAlloc::Free(it->second.ptr); + using_low_level_alloc = false; + allocated.erase(it); + } + if (use_new_arena) { + CHECK(LowLevelAlloc::DeleteArena(arena)); + } +} + +// used for counting allocates and frees +static int32 allocates; +static int32 frees; + +// called on each alloc if kCallMallocHook specified +static void AllocHook(const void *p, size_t size) { + if (using_low_level_alloc) { + allocates++; + } +} + +// called on each free if kCallMallocHook specified +static void FreeHook(const void *p) { + if (using_low_level_alloc) { + frees++; + } +} + +int main(int argc, char *argv[]) { + // This is needed by maybe_threads_unittest.sh, which parses argv[0] + // to figure out what directory low_level_alloc_unittest is in. + if (argc != 1) { + fprintf(stderr, "USAGE: %s\n", argv[0]); + return 1; + } + + CHECK(MallocHook::AddNewHook(&AllocHook)); + CHECK(MallocHook::AddDeleteHook(&FreeHook)); + CHECK_EQ(allocates, 0); + CHECK_EQ(frees, 0); + Test(false, false, 50000); + CHECK_NE(allocates, 0); // default arena calls hooks + CHECK_NE(frees, 0); + for (int i = 0; i != 16; i++) { + bool call_hooks = ((i & 1) == 1); + allocates = 0; + frees = 0; + Test(true, call_hooks, 15000); + if (call_hooks) { + CHECK_GT(allocates, 5000); // arena calls hooks + CHECK_GT(frees, 5000); + } else { + CHECK_EQ(allocates, 0); // arena doesn't call hooks + CHECK_EQ(frees, 0); + } + } + printf("\nPASS\n"); + CHECK(MallocHook::RemoveNewHook(&AllocHook)); + CHECK(MallocHook::RemoveDeleteHook(&FreeHook)); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_c_test.c b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_c_test.c new file mode 100644 index 000000000..2868b9c37 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_c_test.c @@ -0,0 +1,182 @@ +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2009, 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 tests the c shims: malloc_extension_c.h and malloc_hook_c.h. + * Mostly, we'll just care that these shims compile under gcc + * (*not* g++!) + * + * NOTE: this is C code, not C++ code! + */ + +#include +#include +#include /* for size_t */ +#include +#include + +#define FAIL(msg) do { \ + fprintf(stderr, "FATAL ERROR: %s\n", msg); \ + exit(1); \ +} while (0) + +static int g_new_hook_calls = 0; +static int g_delete_hook_calls = 0; + +void TestNewHook(const void* ptr, size_t size) { + g_new_hook_calls++; +} + +void TestDeleteHook(const void* ptr) { + g_delete_hook_calls++; +} + +static +void *forced_malloc(size_t size) +{ + extern void *tc_malloc(size_t); + void *rv = tc_malloc(size); + if (!rv) { + FAIL("malloc is not supposed to fail here"); + } + return rv; +} + +void TestMallocHook(void) { + /* TODO(csilvers): figure out why we get: + * E0100 00:00:00.000000 7383 malloc_hook.cc:244] RAW: google_malloc section is missing, thus InHookCaller is broken! + */ +#if 0 + void* result[5]; + + if (MallocHook_GetCallerStackTrace(result, sizeof(result)/sizeof(*result), + 0) < 2) { /* should have this and main */ + FAIL("GetCallerStackTrace failed"); + } +#endif + + if (!MallocHook_AddNewHook(&TestNewHook)) { + FAIL("Failed to add new hook"); + } + if (!MallocHook_AddDeleteHook(&TestDeleteHook)) { + FAIL("Failed to add delete hook"); + } + + free(forced_malloc(10)); + free(forced_malloc(20)); + if (g_new_hook_calls != 2) { + FAIL("Wrong number of calls to the new hook"); + } + if (g_delete_hook_calls != 2) { + FAIL("Wrong number of calls to the delete hook"); + } + if (!MallocHook_RemoveNewHook(&TestNewHook)) { + FAIL("Failed to remove new hook"); + } + if (!MallocHook_RemoveDeleteHook(&TestDeleteHook)) { + FAIL("Failed to remove delete hook"); + } + + free(forced_malloc(10)); + free(forced_malloc(20)); + if (g_new_hook_calls != 2) { + FAIL("Wrong number of calls to the new hook"); + } + + MallocHook_SetNewHook(&TestNewHook); + MallocHook_SetDeleteHook(&TestDeleteHook); + + free(forced_malloc(10)); + free(forced_malloc(20)); + if (g_new_hook_calls != 4) { + FAIL("Wrong number of calls to the singular new hook"); + } + + if (MallocHook_SetNewHook(NULL) == NULL) { + FAIL("Failed to set new hook"); + } + if (MallocHook_SetDeleteHook(NULL) == NULL) { + FAIL("Failed to set delete hook"); + } +} + +void TestMallocExtension(void) { + int blocks; + size_t total; + int hist[64]; + char buffer[200]; + char* x = (char*)malloc(10); + + MallocExtension_VerifyAllMemory(); + MallocExtension_VerifyMallocMemory(x); + MallocExtension_MallocMemoryStats(&blocks, &total, hist); + MallocExtension_GetStats(buffer, sizeof(buffer)); + if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes", + &total)) { + FAIL("GetNumericProperty failed for generic.current_allocated_bytes"); + } + if (total < 10) { + FAIL("GetNumericProperty had bad return for generic.current_allocated_bytes"); + } + if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes", + &total)) { + FAIL("GetNumericProperty failed for generic.current_allocated_bytes"); + } + MallocExtension_MarkThreadIdle(); + MallocExtension_MarkThreadBusy(); + MallocExtension_ReleaseToSystem(1); + MallocExtension_ReleaseFreeMemory(); + if (MallocExtension_GetEstimatedAllocatedSize(10) < 10) { + FAIL("GetEstimatedAllocatedSize returned a bad value (too small)"); + } + if (MallocExtension_GetAllocatedSize(x) < 10) { + FAIL("GetEstimatedAllocatedSize returned a bad value (too small)"); + } + if (MallocExtension_GetOwnership(x) != MallocExtension_kOwned) { + FAIL("DidAllocatePtr returned a bad value (kNotOwned)"); + } + /* TODO(csilvers): this relies on undocumented behavior that + GetOwnership works on stack-allocated variables. Use a better test. */ + if (MallocExtension_GetOwnership(hist) != MallocExtension_kNotOwned) { + FAIL("DidAllocatePtr returned a bad value (kOwned)"); + } + + free(x); +} + +int main(int argc, char** argv) { + TestMallocHook(); + TestMallocExtension(); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_test.cc new file mode 100644 index 000000000..657077239 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_extension_test.cc @@ -0,0 +1,98 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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 +// +// Simple test of malloc_extension. Includes test of C shims. + +#include "config_for_unittests.h" +#include +#include +#include "base/logging.h" +#include +#include + +int main(int argc, char** argv) { + void* a = malloc(1000); + + size_t cxx_bytes_used, c_bytes_used; + ASSERT_TRUE(MallocExtension::instance()->GetNumericProperty( + "generic.current_allocated_bytes", &cxx_bytes_used)); + ASSERT_TRUE(MallocExtension_GetNumericProperty( + "generic.current_allocated_bytes", &c_bytes_used)); + ASSERT_GT(cxx_bytes_used, 1000); + ASSERT_EQ(cxx_bytes_used, c_bytes_used); + + ASSERT_TRUE(MallocExtension::instance()->VerifyAllMemory()); + ASSERT_TRUE(MallocExtension_VerifyAllMemory()); + + ASSERT_EQ(MallocExtension::kOwned, + MallocExtension::instance()->GetOwnership(a)); + // TODO(csilvers): this relies on undocumented behavior that + // GetOwnership works on stack-allocated variables. Use a better test. + ASSERT_EQ(MallocExtension::kNotOwned, + MallocExtension::instance()->GetOwnership(&cxx_bytes_used)); + ASSERT_EQ(MallocExtension::kNotOwned, + MallocExtension::instance()->GetOwnership(NULL)); + ASSERT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000); + // This is just a sanity check. If we allocated too much, tcmalloc is broken + ASSERT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000); + ASSERT_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000); + + for (int i = 0; i < 10; ++i) { + void *p = malloc(i); + ASSERT_GE(MallocExtension::instance()->GetAllocatedSize(p), + MallocExtension::instance()->GetEstimatedAllocatedSize(i)); + free(p); + } + + // Check the c-shim version too. + ASSERT_EQ(MallocExtension_kOwned, MallocExtension_GetOwnership(a)); + ASSERT_EQ(MallocExtension_kNotOwned, + MallocExtension_GetOwnership(&cxx_bytes_used)); + ASSERT_EQ(MallocExtension_kNotOwned, MallocExtension_GetOwnership(NULL)); + ASSERT_GE(MallocExtension_GetAllocatedSize(a), 1000); + ASSERT_LE(MallocExtension_GetAllocatedSize(a), 5000); + ASSERT_GE(MallocExtension_GetEstimatedAllocatedSize(1000), 1000); + + free(a); + + // Verify that the .cc file and .h file have the same enum values. + ASSERT_EQ(static_cast(MallocExtension::kUnknownOwnership), + static_cast(MallocExtension_kUnknownOwnership)); + ASSERT_EQ(static_cast(MallocExtension::kOwned), + static_cast(MallocExtension_kOwned)); + ASSERT_EQ(static_cast(MallocExtension::kNotOwned), + static_cast(MallocExtension_kNotOwned)); + + printf("DONE\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_hook_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_hook_test.cc new file mode 100644 index 000000000..a5cd8606a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/malloc_hook_test.cc @@ -0,0 +1,367 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2011, 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: llib@google.com (Bill Clarke) + +#include "config_for_unittests.h" +#include +#include +#ifdef HAVE_MMAP +#include +#endif +#ifdef HAVE_UNISTD_H +#include // for sleep() +#endif +#include +#include +#include +#include +#include "malloc_hook-inl.h" +#include "base/logging.h" +#include "base/simple_mutex.h" +#include "base/sysinfo.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 + +namespace { + +using std::string; +using std::vector; + +vector g_testlist; // the tests to run + +#define TEST(a, b) \ + struct Test_##a##_##b { \ + Test_##a##_##b() { g_testlist.push_back(&Run); } \ + static void Run(); \ + }; \ + static Test_##a##_##b g_test_##a##_##b; \ + void Test_##a##_##b::Run() + + +static int RUN_ALL_TESTS() { + vector::const_iterator it; + for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { + (*it)(); // The test will error-exit if there's a problem. + } + fprintf(stderr, "\nPassed %d tests\n\nPASS\n", + static_cast(g_testlist.size())); + return 0; +} + +void Sleep(int seconds) { +#ifdef _MSC_VER + _sleep(seconds * 1000); // Windows's _sleep takes milliseconds argument +#else + sleep(seconds); +#endif +} + +using std::min; +using base::internal::kHookListMaxValues; + +// Since HookList is a template and is defined in malloc_hook.cc, we can only +// use an instantiation of it from malloc_hook.cc. We then reinterpret those +// values as integers for testing. +typedef base::internal::HookList TestHookList; + +int TestHookList_Traverse(const TestHookList& list, uintptr_t* output_array, int n) { + MallocHook::NewHook values_as_hooks[kHookListMaxValues]; + int result = list.Traverse(values_as_hooks, min(n, kHookListMaxValues)); + for (int i = 0; i < result; ++i) { + output_array[i] = reinterpret_cast(*values_as_hooks[i]); + } + return result; +} + +bool TestHookList_Add(TestHookList* list, int val) { + return list->Add(reinterpret_cast(val)); +} + +bool TestHookList_Remove(TestHookList* list, int val) { + return list->Remove(reinterpret_cast(val)); +} + +// Note that this is almost the same as INIT_HOOK_LIST in malloc_hook.cc without +// the cast. +#define INIT_HOOK_LIST(initial_value) { 1, { initial_value } } + +TEST(HookListTest, InitialValueExists) { + TestHookList list = INIT_HOOK_LIST(69); + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(1, TestHookList_Traverse(list, values, 2)); + EXPECT_EQ(69, values[0]); + EXPECT_EQ(1, list.priv_end); +} + +TEST(HookListTest, CanRemoveInitialValue) { + TestHookList list = INIT_HOOK_LIST(69); + ASSERT_TRUE(TestHookList_Remove(&list, 69)); + EXPECT_EQ(0, list.priv_end); + + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(0, TestHookList_Traverse(list, values, 2)); +} + +TEST(HookListTest, AddAppends) { + TestHookList list = INIT_HOOK_LIST(69); + ASSERT_TRUE(TestHookList_Add(&list, 42)); + EXPECT_EQ(2, list.priv_end); + + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(2, TestHookList_Traverse(list, values, 2)); + EXPECT_EQ(69, values[0]); + EXPECT_EQ(42, values[1]); +} + +TEST(HookListTest, RemoveWorksAndWillClearSize) { + TestHookList list = INIT_HOOK_LIST(69); + ASSERT_TRUE(TestHookList_Add(&list, 42)); + + ASSERT_TRUE(TestHookList_Remove(&list, 69)); + EXPECT_EQ(2, list.priv_end); + + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(1, TestHookList_Traverse(list, values, 2)); + EXPECT_EQ(42, values[0]); + + ASSERT_TRUE(TestHookList_Remove(&list, 42)); + EXPECT_EQ(0, list.priv_end); + EXPECT_EQ(0, TestHookList_Traverse(list, values, 2)); +} + +TEST(HookListTest, AddPrependsAfterRemove) { + TestHookList list = INIT_HOOK_LIST(69); + ASSERT_TRUE(TestHookList_Add(&list, 42)); + + ASSERT_TRUE(TestHookList_Remove(&list, 69)); + EXPECT_EQ(2, list.priv_end); + + ASSERT_TRUE(TestHookList_Add(&list, 7)); + EXPECT_EQ(2, list.priv_end); + + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(2, TestHookList_Traverse(list, values, 2)); + EXPECT_EQ(7, values[0]); + EXPECT_EQ(42, values[1]); +} + +TEST(HookListTest, InvalidAddRejected) { + TestHookList list = INIT_HOOK_LIST(69); + EXPECT_FALSE(TestHookList_Add(&list, 0)); + + uintptr_t values[2] = { 0, 0 }; + EXPECT_EQ(1, TestHookList_Traverse(list, values, 2)); + EXPECT_EQ(69, values[0]); + EXPECT_EQ(1, list.priv_end); +} + +TEST(HookListTest, FillUpTheList) { + TestHookList list = INIT_HOOK_LIST(69); + int num_inserts = 0; + while (TestHookList_Add(&list, ++num_inserts)) + ; + EXPECT_EQ(kHookListMaxValues, num_inserts); + EXPECT_EQ(kHookListMaxValues, list.priv_end); + + uintptr_t values[kHookListMaxValues + 1]; + EXPECT_EQ(kHookListMaxValues, TestHookList_Traverse(list, values, + kHookListMaxValues)); + EXPECT_EQ(69, values[0]); + for (int i = 1; i < kHookListMaxValues; ++i) { + EXPECT_EQ(i, values[i]); + } +} + +void MultithreadedTestThread(TestHookList* list, int shift, + int thread_num) { + string message; + char buf[64]; + for (int i = 1; i < 1000; ++i) { + // In each loop, we insert a unique value, check it exists, remove it, and + // check it doesn't exist. We also record some stats to log at the end of + // each thread. Each insertion location and the length of the list is + // non-deterministic (except for the very first one, over all threads, and + // after the very last one the list should be empty). + int value = (i << shift) + thread_num; + EXPECT_TRUE(TestHookList_Add(list, value)); + sched_yield(); // Ensure some more interleaving. + uintptr_t values[kHookListMaxValues + 1]; + int num_values = TestHookList_Traverse(*list, values, kHookListMaxValues); + EXPECT_LT(0, num_values); + int value_index; + for (value_index = 0; + value_index < num_values && values[value_index] != value; + ++value_index) + ; + EXPECT_LT(value_index, num_values); // Should have found value. + snprintf(buf, sizeof(buf), "[%d/%d; ", value_index, num_values); + message += buf; + sched_yield(); + EXPECT_TRUE(TestHookList_Remove(list, value)); + sched_yield(); + num_values = TestHookList_Traverse(*list, values, kHookListMaxValues); + for (value_index = 0; + value_index < num_values && values[value_index] != value; + ++value_index) + ; + EXPECT_EQ(value_index, num_values); // Should not have found value. + snprintf(buf, sizeof(buf), "%d]", num_values); + message += buf; + sched_yield(); + } + fprintf(stderr, "thread %d: %s\n", thread_num, message.c_str()); +} + +static volatile int num_threads_remaining; +static TestHookList list = INIT_HOOK_LIST(69); +static Mutex threadcount_lock; + +void MultithreadedTestThreadRunner(int thread_num) { + // Wait for all threads to start running. + { + MutexLock ml(&threadcount_lock); + assert(num_threads_remaining > 0); + --num_threads_remaining; + + // We should use condvars and the like, but for this test, we'll + // go simple and busy-wait. + while (num_threads_remaining > 0) { + threadcount_lock.Unlock(); + Sleep(1); + threadcount_lock.Lock(); + } + } + + // shift is the smallest number such that (1< kHookListMaxValues + int shift = 0; + for (int i = kHookListMaxValues; i > 0; i >>= 1) + shift += 1; + + MultithreadedTestThread(&list, shift, thread_num); +} + + +TEST(HookListTest, MultithreadedTest) { + ASSERT_TRUE(TestHookList_Remove(&list, 69)); + ASSERT_EQ(0, list.priv_end); + + // Run kHookListMaxValues thread, each running MultithreadedTestThread. + // First, we need to set up the rest of the globals. + num_threads_remaining = kHookListMaxValues; // a global var + RunManyThreadsWithId(&MultithreadedTestThreadRunner, num_threads_remaining, + 1 << 15); + + uintptr_t values[kHookListMaxValues + 1]; + EXPECT_EQ(0, TestHookList_Traverse(list, values, kHookListMaxValues)); + EXPECT_EQ(0, list.priv_end); +} + +// We only do mmap-hooking on (some) linux systems. +#if defined(HAVE_MMAP) && defined(__linux) && \ + (defined(__i386__) || defined(__x86_64__) || defined(__PPC__)) + +int mmap_calls = 0; +int mmap_matching_calls = 0; +int munmap_calls = 0; +int munmap_matching_calls = 0; +const int kMmapMagicFd = 1; +void* const kMmapMagicPointer = reinterpret_cast(1); + +int MmapReplacement(const void* start, + size_t size, + int protection, + int flags, + int fd, + off_t offset, + void** result) { + ++mmap_calls; + if (fd == kMmapMagicFd) { + ++mmap_matching_calls; + *result = kMmapMagicPointer; + return true; + } + return false; +} + +int MunmapReplacement(const void* ptr, size_t size, int* result) { + ++munmap_calls; + if (ptr == kMmapMagicPointer) { + ++munmap_matching_calls; + *result = 0; + return true; + } + return false; +} + +TEST(MallocMookTest, MmapReplacements) { + mmap_calls = mmap_matching_calls = munmap_calls = munmap_matching_calls = 0; + MallocHook::SetMmapReplacement(&MmapReplacement); + MallocHook::SetMunmapReplacement(&MunmapReplacement); + EXPECT_EQ(kMmapMagicPointer, mmap(NULL, 1, PROT_READ, MAP_PRIVATE, + kMmapMagicFd, 0)); + EXPECT_EQ(1, mmap_matching_calls); + + char* ptr = reinterpret_cast( + mmap(NULL, 1, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + EXPECT_EQ(2, mmap_calls); + EXPECT_EQ(1, mmap_matching_calls); + ASSERT_NE(MAP_FAILED, ptr); + *ptr = 'a'; + + EXPECT_EQ(0, munmap(kMmapMagicPointer, 1)); + EXPECT_EQ(1, munmap_calls); + EXPECT_EQ(1, munmap_matching_calls); + + EXPECT_EQ(0, munmap(ptr, 1)); + EXPECT_EQ(2, munmap_calls); + EXPECT_EQ(1, munmap_matching_calls); + + // The DEATH test below is flaky, because we've just munmapped the memory, + // making it available for mmap()ing again. There is no guarantee that it + // will stay unmapped, and in fact it gets reused ~10% of the time. + // It the area is reused, then not only we don't die, but we also corrupt + // whoever owns that memory now. + // EXPECT_DEATH(*ptr = 'a', "SIGSEGV"); +} +#endif // #ifdef HAVE_MMAP && linux && ... + +} // namespace + +int main(int argc, char** argv) { + return RUN_ALL_TESTS(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/markidle_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/markidle_unittest.cc new file mode 100644 index 000000000..829c503fe --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/markidle_unittest.cc @@ -0,0 +1,127 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2003, 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: Sanjay Ghemawat +// +// MallocExtension::MarkThreadIdle() testing +#include + +#include "config_for_unittests.h" +#include "base/logging.h" +#include +#include "tests/testutil.h" // for RunThread() + +// Helper routine to do lots of allocations +static void TestAllocation() { + static const int kNum = 100; + void* ptr[kNum]; + for (int size = 8; size <= 65536; size*=2) { + for (int i = 0; i < kNum; i++) { + ptr[i] = malloc(size); + } + for (int i = 0; i < kNum; i++) { + free(ptr[i]); + } + } +} + +// Routine that does a bunch of MarkThreadIdle() calls in sequence +// without any intervening allocations +static void MultipleIdleCalls() { + for (int i = 0; i < 4; i++) { + MallocExtension::instance()->MarkThreadIdle(); + } +} + +// Routine that does a bunch of MarkThreadIdle() calls in sequence +// with intervening allocations +static void MultipleIdleNonIdlePhases() { + for (int i = 0; i < 4; i++) { + TestAllocation(); + MallocExtension::instance()->MarkThreadIdle(); + } +} + +// Get current thread cache usage +static size_t GetTotalThreadCacheSize() { + size_t result; + CHECK(MallocExtension::instance()->GetNumericProperty( + "tcmalloc.current_total_thread_cache_bytes", + &result)); + return result; +} + +// Check that MarkThreadIdle() actually reduces the amount +// of per-thread memory. +static void TestIdleUsage() { + const size_t original = GetTotalThreadCacheSize(); + + TestAllocation(); + const size_t post_allocation = GetTotalThreadCacheSize(); + CHECK_GT(post_allocation, original); + + MallocExtension::instance()->MarkThreadIdle(); + const size_t post_idle = GetTotalThreadCacheSize(); + CHECK_LE(post_idle, original); + + // Log after testing because logging can allocate heap memory. + VLOG(0, "Original usage: %zu\n", original); + VLOG(0, "Post allocation: %zu\n", post_allocation); + VLOG(0, "Post idle: %zu\n", post_idle); +} + +static void TestTemporarilyIdleUsage() { + const size_t original = MallocExtension::instance()->GetThreadCacheSize(); + + TestAllocation(); + const size_t post_allocation = MallocExtension::instance()->GetThreadCacheSize(); + CHECK_GT(post_allocation, original); + + MallocExtension::instance()->MarkThreadIdle(); + const size_t post_idle = MallocExtension::instance()->GetThreadCacheSize(); + CHECK_EQ(post_idle, 0); + + // Log after testing because logging can allocate heap memory. + VLOG(0, "Original usage: %zu\n", original); + VLOG(0, "Post allocation: %zu\n", post_allocation); + VLOG(0, "Post idle: %zu\n", post_idle); +} + +int main(int argc, char** argv) { + RunThread(&TestIdleUsage); + RunThread(&TestAllocation); + RunThread(&MultipleIdleCalls); + RunThread(&MultipleIdleNonIdlePhases); + RunThread(&TestTemporarilyIdleUsage); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/maybe_threads_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/maybe_threads_unittest.sh new file mode 100755 index 000000000..77b3b7885 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/maybe_threads_unittest.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# 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: Craig Silverstein +# +# maybe_threads.cc was written to allow LD_PRELOAD=libtcmalloc.so to +# work even on binaries that were not linked with pthreads. This +# unittest tests that, by running low_level_alloc_unittest with an +# LD_PRELOAD. (low_level_alloc_unittest was chosen because it doesn't +# link in tcmalloc.) +# +# We assume all the .so files are in the same directory as both +# addressmap_unittest and profiler1_unittest. The reason we need +# profiler1_unittest is because it's instrumented to show the directory +# it's "really" in when run without any args. In practice this will either +# be BINDIR, or, when using libtool, BINDIR/.lib. + +# We expect BINDIR to be set in the environment. +# If not, we set them to some reasonable values. +BINDIR="${BINDIR:-.}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir]" + echo " By default, unittest_dir=$BINDIR" + exit 1 +fi + +UNITTEST_DIR=${1:-$BINDIR} + +# Figure out the "real" unittest directory. Also holds the .so files. +UNITTEST_DIR=`$UNITTEST_DIR/low_level_alloc_unittest --help 2>&1 \ + | awk '{print $2; exit;}' \ + | xargs dirname` + +# Figure out where libtcmalloc lives. It should be in UNITTEST_DIR, +# but with libtool it might be in a subdir. +if [ -r "$UNITTEST_DIR/libtcmalloc_minimal.so" ]; then + LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.so" +elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.so" ]; then + LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.so" +elif [ -r "$UNITTEST_DIR/libtcmalloc_minimal.dylib" ]; then # for os x + LIB_PATH="$UNITTEST_DIR/libtcmalloc_minimal.dylib" +elif [ -r "$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib" ]; then + LIB_PATH="$UNITTEST_DIR/.libs/libtcmalloc_minimal.dylib" +else + echo "Cannot run $0: cannot find libtcmalloc_minimal.so" + exit 2 +fi + +LD_PRELOAD="$LIB_PATH" $UNITTEST_DIR/low_level_alloc_unittest diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/memalign_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/memalign_unittest.cc new file mode 100644 index 000000000..035f7098d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/memalign_unittest.cc @@ -0,0 +1,221 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2004, 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: Sanjay Ghemawat +// +// Check memalign related routines. +// +// We can't really do a huge amount of checking, but at the very +// least, the following code checks that return values are properly +// aligned, and that writing into the objects works. + +#include "config_for_unittests.h" + +// 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 // for getpagesize() +#endif +#include "tcmalloc.h" // must come early, to pick up posix_memalign +#include +#include // defines posix_memalign +#include // for the printf at the end +#ifdef HAVE_STDINT_H +#include // for uintptr_t +#endif +#ifdef HAVE_UNISTD_H +#include // for getpagesize() +#endif +// Malloc can be in several places on older versions of OS X. +#if defined(HAVE_MALLOC_H) +#include // for memalign() and valloc() +#elif defined(HAVE_MALLOC_MALLOC_H) +#include +#elif defined(HAVE_SYS_MALLOC_H) +#include +#endif +#include "base/basictypes.h" +#include "base/logging.h" +#include "tests/testutil.h" + + +// Return the next interesting size/delta to check. Returns -1 if no more. +static int NextSize(int size) { + if (size < 100) { + return size+1; + } else if (size < 1048576) { + // Find next power of two + int power = 1; + while (power < size) { + power <<= 1; + } + + // Yield (power-1, power, power+1) + if (size < power-1) { + return power-1; + } else if (size == power-1) { + return power; + } else { + assert(size == power); + return power+1; + } + } else { + return -1; + } +} + +// Shortform for cast +static uintptr_t Number(void* p) { + return reinterpret_cast(p); +} + +// Check alignment +static void CheckAlignment(void* p, int align) { + if ((Number(p) & (align-1)) != 0) + LOG(FATAL, "wrong alignment; wanted 0x%x; got %p\n", align, p); +} + +// Fill a buffer of the specified size with a predetermined pattern +static void Fill(void* p, int n, char seed) { + unsigned char* buffer = reinterpret_cast(p); + for (int i = 0; i < n; i++) { + buffer[i] = ((seed + i) & 0xff); + } +} + +// Check that the specified buffer has the predetermined pattern +// generated by Fill() +static bool Valid(const void* p, int n, char seed) { + const unsigned char* buffer = reinterpret_cast(p); + for (int i = 0; i < n; i++) { + if (buffer[i] != ((seed + i) & 0xff)) { + return false; + } + } + return true; +} + +int main(int argc, char** argv) { + SetTestResourceLimit(); + + // Try allocating data with a bunch of alignments and sizes + for (int a = 1; a < 1048576; a *= 2) { + for (int s = 0; s != -1; s = NextSize(s)) { + void* ptr = memalign(a, s); + CheckAlignment(ptr, a); + Fill(ptr, s, 'x'); + CHECK(Valid(ptr, s, 'x')); + free(ptr); + + if ((a >= sizeof(void*)) && ((a & (a-1)) == 0)) { + CHECK(posix_memalign(&ptr, a, s) == 0); + CheckAlignment(ptr, a); + Fill(ptr, s, 'y'); + CHECK(Valid(ptr, s, 'y')); + free(ptr); + } + } + } + + { + // Check various corner cases + void* p1 = memalign(1<<20, 1<<19); + void* p2 = memalign(1<<19, 1<<19); + void* p3 = memalign(1<<21, 1<<19); + CheckAlignment(p1, 1<<20); + CheckAlignment(p2, 1<<19); + CheckAlignment(p3, 1<<21); + Fill(p1, 1<<19, 'a'); + Fill(p2, 1<<19, 'b'); + Fill(p3, 1<<19, 'c'); + CHECK(Valid(p1, 1<<19, 'a')); + CHECK(Valid(p2, 1<<19, 'b')); + CHECK(Valid(p3, 1<<19, 'c')); + free(p1); + free(p2); + free(p3); + } + + { + // posix_memalign + void* ptr; + CHECK(posix_memalign(&ptr, 0, 1) == EINVAL); + CHECK(posix_memalign(&ptr, sizeof(void*)/2, 1) == EINVAL); + CHECK(posix_memalign(&ptr, sizeof(void*)+1, 1) == EINVAL); + CHECK(posix_memalign(&ptr, 4097, 1) == EINVAL); + + // Grab some memory so that the big allocation below will definitely fail. + void* p_small = malloc(4*1048576); + CHECK(p_small != NULL); + + // Make sure overflow is returned as ENOMEM + const size_t zero = 0; + static const size_t kMinusNTimes = 10; + for ( size_t i = 1; i < kMinusNTimes; ++i ) { + int r = posix_memalign(&ptr, 1024, zero - i); + CHECK(r == ENOMEM); + } + + free(p_small); + } + + const int pagesize = getpagesize(); + { + // valloc + for (int s = 0; s != -1; s = NextSize(s)) { + void* p = valloc(s); + CheckAlignment(p, pagesize); + Fill(p, s, 'v'); + CHECK(Valid(p, s, 'v')); + free(p); + } + } + + { + // pvalloc + for (int s = 0; s != -1; s = NextSize(s)) { + void* p = pvalloc(s); + CheckAlignment(p, pagesize); + int alloc_needed = ((s + pagesize - 1) / pagesize) * pagesize; + Fill(p, alloc_needed, 'x'); + CHECK(Valid(p, alloc_needed, 'x')); + free(p); + } + } + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/packed-cache_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/packed-cache_test.cc new file mode 100644 index 000000000..3984594ca --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/packed-cache_test.cc @@ -0,0 +1,82 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Geoff Pike + +#include +#include "base/logging.h" +#include "packed-cache-inl.h" + +static const int kHashbits = PackedCache<20>::kHashbits; + +template +static size_t MustGet(const PackedCache& cache, uintptr_t key) { + uint32 rv; + CHECK(cache.TryGet(key, &rv)); + return rv; +} + +template +static size_t Has(const PackedCache& cache, uintptr_t key) { + uint32 dummy; + return cache.TryGet(key, &dummy); +} + +// A basic sanity test. +void PackedCacheTest_basic() { + PackedCache<20> cache; + + CHECK(!Has(cache, 0)); + cache.Put(0, 17); + CHECK(Has(cache, 0)); + CHECK_EQ(MustGet(cache, 0), 17); + + cache.Put(19, 99); + CHECK_EQ(MustGet(cache, 0), 17); + CHECK_EQ(MustGet(cache, 19), 99); + + // Knock <0, 17> out by using a conflicting key. + cache.Put(1 << kHashbits, 22); + CHECK(!Has(cache, 0)); + CHECK_EQ(MustGet(cache, 1 << kHashbits), 22); + + cache.Invalidate(19); + CHECK(!Has(cache, 19)); + CHECK(!Has(cache, 0)); + CHECK(Has(cache, 1 << kHashbits)); +} + +int main(int argc, char **argv) { + PackedCacheTest_basic(); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/page_heap_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/page_heap_test.cc new file mode 100644 index 000000000..3caacc0df --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/page_heap_test.cc @@ -0,0 +1,202 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright 2009 Google Inc. All Rights Reserved. +// Author: fikes@google.com (Andrew Fikes) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + +#include "config_for_unittests.h" + +#include + +#include + +#include "page_heap.h" +#include "system-alloc.h" +#include "base/logging.h" +#include "common.h" + +DECLARE_int64(tcmalloc_heap_limit_mb); + +namespace { + +// The system will only release memory if the block size is equal or hight than +// system page size. +static bool HaveSystemRelease = + TCMalloc_SystemRelease( + TCMalloc_SystemAlloc(getpagesize(), NULL, 0), getpagesize()); + +static void CheckStats(const tcmalloc::PageHeap* ph, + uint64_t system_pages, + uint64_t free_pages, + uint64_t unmapped_pages) { + tcmalloc::PageHeap::Stats stats = ph->stats(); + + if (!HaveSystemRelease) { + free_pages += unmapped_pages; + unmapped_pages = 0; + } + + EXPECT_EQ(system_pages, stats.system_bytes >> kPageShift); + EXPECT_EQ(free_pages, stats.free_bytes >> kPageShift); + EXPECT_EQ(unmapped_pages, stats.unmapped_bytes >> kPageShift); +} + +static void TestPageHeap_Stats() { + std::unique_ptr ph(new tcmalloc::PageHeap()); + + // Empty page heap + CheckStats(ph.get(), 0, 0, 0); + + // Allocate a span 's1' + tcmalloc::Span* s1 = ph->New(256); + CheckStats(ph.get(), 256, 0, 0); + + // Split span 's1' into 's1', 's2'. Delete 's2' + tcmalloc::Span* s2 = ph->Split(s1, 128); + ph->Delete(s2); + CheckStats(ph.get(), 256, 128, 0); + + // Unmap deleted span 's2' + ph->ReleaseAtLeastNPages(1); + CheckStats(ph.get(), 256, 0, 128); + + // Delete span 's1' + ph->Delete(s1); + CheckStats(ph.get(), 256, 128, 128); +} + +// The number of kMaxPages-sized Spans we will allocate and free during the +// tests. +// We will also do twice this many kMaxPages/2-sized ones. +static constexpr int kNumberMaxPagesSpans = 10; + +// Allocates all the last-level page tables we will need. Doing this before +// calculating the base heap usage is necessary, because otherwise if any of +// these are allocated during the main test it will throw the heap usage +// calculations off and cause the test to fail. +static void AllocateAllPageTables() { + // Make a separate PageHeap from the main test so the test can start without + // any pages in the lists. + std::unique_ptr ph(new tcmalloc::PageHeap()); + tcmalloc::Span *spans[kNumberMaxPagesSpans * 2]; + for (int i = 0; i < kNumberMaxPagesSpans; ++i) { + spans[i] = ph->New(kMaxPages); + EXPECT_NE(spans[i], NULL); + } + for (int i = 0; i < kNumberMaxPagesSpans; ++i) { + ph->Delete(spans[i]); + } + for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) { + spans[i] = ph->New(kMaxPages >> 1); + EXPECT_NE(spans[i], NULL); + } + for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) { + ph->Delete(spans[i]); + } +} + +static void TestPageHeap_Limit() { + AllocateAllPageTables(); + + std::unique_ptr ph(new tcmalloc::PageHeap()); + + CHECK_EQ(kMaxPages, 1 << (20 - kPageShift)); + + // We do not know much is taken from the system for other purposes, + // so we detect the proper limit: + { + FLAGS_tcmalloc_heap_limit_mb = 1; + tcmalloc::Span* s = NULL; + while((s = ph->New(kMaxPages)) == NULL) { + FLAGS_tcmalloc_heap_limit_mb++; + } + FLAGS_tcmalloc_heap_limit_mb += kNumberMaxPagesSpans - 1; + ph->Delete(s); + // We are [10, 11) mb from the limit now. + } + + // Test AllocLarge and GrowHeap first: + { + tcmalloc::Span * spans[kNumberMaxPagesSpans]; + for (int i=0; iNew(kMaxPages); + EXPECT_NE(spans[i], NULL); + } + EXPECT_EQ(ph->New(kMaxPages), NULL); + + for (int i=0; iDelete(spans[i]); + } + + tcmalloc::Span *defragmented = + ph->New(kNumberMaxPagesSpans / 2 * kMaxPages); + + if (HaveSystemRelease) { + // EnsureLimit should release deleted normal spans + EXPECT_NE(defragmented, NULL); + EXPECT_TRUE(ph->CheckExpensive()); + ph->Delete(defragmented); + } + else + { + EXPECT_EQ(defragmented, NULL); + EXPECT_TRUE(ph->CheckExpensive()); + } + + for (int i=1; iDelete(spans[i]); + } + } + + // Once again, testing small lists this time (twice smaller spans): + { + tcmalloc::Span * spans[kNumberMaxPagesSpans * 2]; + for (int i=0; iNew(kMaxPages >> 1); + EXPECT_NE(spans[i], NULL); + } + // one more half size allocation may be possible: + tcmalloc::Span * lastHalf = ph->New(kMaxPages >> 1); + EXPECT_EQ(ph->New(kMaxPages >> 1), NULL); + + for (int i=0; iDelete(spans[i]); + } + + for (Length len = kMaxPages >> 2; + len < kNumberMaxPagesSpans / 2 * kMaxPages; len = len << 1) { + if(len <= kMaxPages >> 1 || HaveSystemRelease) { + tcmalloc::Span *s = ph->New(len); + EXPECT_NE(s, NULL); + ph->Delete(s); + } + } + + EXPECT_TRUE(ph->CheckExpensive()); + + for (int i=1; iDelete(spans[i]); + } + + if (lastHalf != NULL) { + ph->Delete(lastHalf); + } + } +} + +} // namespace + +int main(int argc, char **argv) { + TestPageHeap_Stats(); + TestPageHeap_Limit(); + printf("PASS\n"); + // on windows as part of library destructors we call getenv which + // calls malloc which fails due to our exhausted heap limit. It then + // causes fancy stack overflow because log message we're printing + // for failed allocation somehow cause malloc calls too + // + // To keep us out of trouble we just drop malloc limit + FLAGS_tcmalloc_heap_limit_mb = 0; + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/pagemap_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/pagemap_unittest.cc new file mode 100644 index 000000000..71a94dc32 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/pagemap_unittest.cc @@ -0,0 +1,178 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2003, 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: Sanjay Ghemawat + +#include "config_for_unittests.h" +#include +#include +#if defined HAVE_STDINT_H +#include // to get intptr_t +#elif defined HAVE_INTTYPES_H +#include // another place intptr_t might be defined +#endif +#include +#include +#include "base/logging.h" +#include "pagemap.h" + +using std::vector; + +static void Permute(vector* elements) { + if (elements->empty()) + return; + const size_t num_elements = elements->size(); + for (size_t i = num_elements - 1; i > 0; --i) { + const size_t newpos = rand() % (i + 1); + const intptr_t tmp = (*elements)[i]; // swap + (*elements)[i] = (*elements)[newpos]; + (*elements)[newpos] = tmp; + } +} + +// Note: we leak memory every time a map is constructed, so do not +// create too many maps. + +// Test specified map type +template +void TestMap(int limit, bool limit_is_below_the_overflow_boundary) { + RAW_LOG(INFO, "Running test with %d iterations...\n", limit); + + { // Test sequential ensure/assignment + Type map(malloc); + for (intptr_t i = 0; i < static_cast(limit); i++) { + map.Ensure(i, 1); + map.set(i, (void*)(i+1)); + CHECK_EQ(map.get(i), (void*)(i+1)); + } + for (intptr_t i = 0; i < static_cast(limit); i++) { + CHECK_EQ(map.get(i), (void*)(i+1)); + } + } + + { // Test bulk Ensure + Type map(malloc); + map.Ensure(0, limit); + for (intptr_t i = 0; i < static_cast(limit); i++) { + map.set(i, (void*)(i+1)); + CHECK_EQ(map.get(i), (void*)(i+1)); + } + for (intptr_t i = 0; i < static_cast(limit); i++) { + CHECK_EQ(map.get(i), (void*)(i+1)); + } + } + + // Test that we correctly notice overflow + { + Type map(malloc); + CHECK_EQ(map.Ensure(limit, limit+1), limit_is_below_the_overflow_boundary); + } + + { // Test randomized accesses + srand(301); // srand isn't great, but it's portable + vector elements; + for (intptr_t i = 0; i < static_cast(limit); i++) elements.push_back(i); + Permute(&elements); + + Type map(malloc); + for (intptr_t i = 0; i < static_cast(limit); i++) { + map.Ensure(elements[i], 1); + map.set(elements[i], (void*)(elements[i]+1)); + CHECK_EQ(map.get(elements[i]), (void*)(elements[i]+1)); + } + for (intptr_t i = 0; i < static_cast(limit); i++) { + CHECK_EQ(map.get(i), (void*)(i+1)); + } + } +} + +// REQUIRES: BITS==10, i.e., valid range is [0,1023]. +// Representations for different types will end up being: +// PageMap1: array[1024] +// PageMap2: array[32][32] +// PageMap3: array[16][16][4] +template +void TestNext(const char* name) { + RAW_LOG(ERROR, "Running NextTest %s\n", name); + Type map(malloc); + char a, b, c, d, e; + + // When map is empty + CHECK(map.Next(0) == NULL); + CHECK(map.Next(5) == NULL); + CHECK(map.Next(1<<30) == NULL); + + // Add a single value + map.Ensure(40, 1); + map.set(40, &a); + CHECK(map.Next(0) == &a); + CHECK(map.Next(39) == &a); + CHECK(map.Next(40) == &a); + CHECK(map.Next(41) == NULL); + CHECK(map.Next(1<<30) == NULL); + + // Add a few values + map.Ensure(41, 1); + map.Ensure(100, 3); + map.set(41, &b); + map.set(100, &c); + map.set(101, &d); + map.set(102, &e); + CHECK(map.Next(0) == &a); + CHECK(map.Next(39) == &a); + CHECK(map.Next(40) == &a); + CHECK(map.Next(41) == &b); + CHECK(map.Next(42) == &c); + CHECK(map.Next(63) == &c); + CHECK(map.Next(64) == &c); + CHECK(map.Next(65) == &c); + CHECK(map.Next(99) == &c); + CHECK(map.Next(100) == &c); + CHECK(map.Next(101) == &d); + CHECK(map.Next(102) == &e); + CHECK(map.Next(103) == NULL); +} + +int main(int argc, char** argv) { + TestMap< TCMalloc_PageMap1<10> > (100, true); + TestMap< TCMalloc_PageMap1<10> > (1 << 10, false); + TestMap< TCMalloc_PageMap2<20> > (100, true); + TestMap< TCMalloc_PageMap2<20> > (1 << 20, false); + TestMap< TCMalloc_PageMap3<20> > (100, true); + TestMap< TCMalloc_PageMap3<20> > (1 << 20, false); + + TestNext< TCMalloc_PageMap1<10> >("PageMap1"); + TestNext< TCMalloc_PageMap2<10> >("PageMap2"); + TestNext< TCMalloc_PageMap3<10> >("PageMap3"); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/profile-handler_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/profile-handler_unittest.cc new file mode 100644 index 000000000..a8afbca06 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/profile-handler_unittest.cc @@ -0,0 +1,398 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright 2009 Google Inc. All Rights Reserved. +// Author: Nabeel Mian (nabeelmian@google.com) +// Chris Demetriou (cgd@google.com) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. +// +// +// This file contains the unit tests for profile-handler.h interface. + +#include "config.h" +#include "profile-handler.h" + +#include +#include +#include +#include +#include "base/logging.h" +#include "base/simple_mutex.h" + +// Some helpful macros for the test class +#define TEST_F(cls, fn) void cls :: fn() + +// Do we expect the profiler to be enabled? +DEFINE_bool(test_profiler_enabled, true, + "expect profiler to be enabled during tests"); + +namespace { + +// TODO(csilvers): error-checking on the pthreads routines +class Thread { + public: + Thread() : joinable_(false) { } + virtual ~Thread() { } + void SetJoinable(bool value) { joinable_ = value; } + void Start() { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, joinable_ ? PTHREAD_CREATE_JOINABLE + : PTHREAD_CREATE_DETACHED); + pthread_create(&thread_, &attr, &DoRun, this); + pthread_attr_destroy(&attr); + } + void Join() { + assert(joinable_); + pthread_join(thread_, NULL); + } + virtual void Run() = 0; + private: + static void* DoRun(void* cls) { + ProfileHandlerRegisterThread(); + reinterpret_cast(cls)->Run(); + return NULL; + } + pthread_t thread_; + bool joinable_; +}; + +// Sleep interval in nano secs. ITIMER_PROF goes off only afer the specified CPU +// time is consumed. Under heavy load this process may no get scheduled in a +// timely fashion. Therefore, give enough time (20x of ProfileHandle timer +// interval 10ms (100Hz)) for this process to accumulate enought CPU time to get +// a profile tick. +int kSleepInterval = 200000000; + +// Sleep interval in nano secs. To ensure that if the timer has expired it is +// reset. +int kTimerResetInterval = 5000000; + +static bool linux_per_thread_timers_mode_ = false; +static int timer_type_ = ITIMER_PROF; + +// Delays processing by the specified number of nano seconds. 'delay_ns' +// must be less than the number of nano seconds in a second (1000000000). +void Delay(int delay_ns) { + static const int kNumNSecInSecond = 1000000000; + EXPECT_LT(delay_ns, kNumNSecInSecond); + struct timespec delay = { 0, delay_ns }; + nanosleep(&delay, 0); +} + +// Checks whether the profile timer is enabled for the current thread. +bool IsTimerEnabled() { + itimerval current_timer; + EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); + if ((current_timer.it_value.tv_sec == 0) && + (current_timer.it_value.tv_usec != 0)) { + // May be the timer has expired. Sleep for a bit and check again. + Delay(kTimerResetInterval); + EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); + } + return (current_timer.it_value.tv_sec != 0 || + current_timer.it_value.tv_usec != 0); +} + +// Dummy worker thread to accumulate cpu time. +class BusyThread : public Thread { + public: + BusyThread() : stop_work_(false) { + } + + // Setter/Getters + bool stop_work() { + MutexLock lock(&mu_); + return stop_work_; + } + void set_stop_work(bool stop_work) { + MutexLock lock(&mu_); + stop_work_ = stop_work; + } + + private: + // Protects stop_work_ below. + Mutex mu_; + // Whether to stop work? + bool stop_work_; + + // Do work until asked to stop. + void Run() { + while (!stop_work()) { + } + } +}; + +class NullThread : public Thread { + private: + void Run() { + } +}; + +// Signal handler which tracks the profile timer ticks. +static void TickCounter(int sig, siginfo_t* sig_info, void *vuc, + void* tick_counter) { + int* counter = static_cast(tick_counter); + ++(*counter); +} + +// This class tests the profile-handler.h interface. +class ProfileHandlerTest { + protected: + + // Determines the timer type. + static void SetUpTestCase() { + timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); + +#if HAVE_LINUX_SIGEV_THREAD_ID + linux_per_thread_timers_mode_ = (getenv("CPUPROFILE_PER_THREAD_TIMERS") != NULL); + const char *signal_number = getenv("CPUPROFILE_TIMER_SIGNAL"); + if (signal_number) { + //signal_number_ = strtol(signal_number, NULL, 0); + linux_per_thread_timers_mode_ = true; + Delay(kTimerResetInterval); + } +#endif + } + + // Sets up the profile timers and SIGPROF/SIGALRM handler in a known state. + // It does the following: + // 1. Unregisters all the callbacks, stops the timer and clears out + // timer_sharing state in the ProfileHandler. This clears out any state + // left behind by the previous test or during module initialization when + // the test program was started. + // 3. Starts a busy worker thread to accumulate CPU usage. + virtual void SetUp() { + // Reset the state of ProfileHandler between each test. This unregisters + // all callbacks and stops the timer. + ProfileHandlerReset(); + EXPECT_EQ(0, GetCallbackCount()); + VerifyDisabled(); + // Start worker to accumulate cpu usage. + StartWorker(); + } + + virtual void TearDown() { + ProfileHandlerReset(); + // Stops the worker thread. + StopWorker(); + } + + // Starts a busy worker thread to accumulate cpu time. There should be only + // one busy worker running. This is required for the case where there are + // separate timers for each thread. + void StartWorker() { + busy_worker_ = new BusyThread(); + busy_worker_->SetJoinable(true); + busy_worker_->Start(); + // Wait for worker to start up and register with the ProfileHandler. + // TODO(nabeelmian) This may not work under very heavy load. + Delay(kSleepInterval); + } + + // Stops the worker thread. + void StopWorker() { + busy_worker_->set_stop_work(true); + busy_worker_->Join(); + delete busy_worker_; + } + + // Gets the number of callbacks registered with the ProfileHandler. + uint32 GetCallbackCount() { + ProfileHandlerState state; + ProfileHandlerGetState(&state); + return state.callback_count; + } + + // Gets the current ProfileHandler interrupt count. + uint64 GetInterruptCount() { + ProfileHandlerState state; + ProfileHandlerGetState(&state); + return state.interrupts; + } + + // Verifies that a callback is correctly registered and receiving + // profile ticks. + void VerifyRegistration(const int& tick_counter) { + // Check the callback count. + EXPECT_GT(GetCallbackCount(), 0); + // Check that the profile timer is enabled. + EXPECT_EQ(FLAGS_test_profiler_enabled, linux_per_thread_timers_mode_ || IsTimerEnabled()); + uint64 interrupts_before = GetInterruptCount(); + // Sleep for a bit and check that tick counter is making progress. + int old_tick_count = tick_counter; + Delay(kSleepInterval); + int new_tick_count = tick_counter; + uint64 interrupts_after = GetInterruptCount(); + if (FLAGS_test_profiler_enabled) { + EXPECT_GT(new_tick_count, old_tick_count); + EXPECT_GT(interrupts_after, interrupts_before); + } else { + EXPECT_EQ(new_tick_count, old_tick_count); + EXPECT_EQ(interrupts_after, interrupts_before); + } + } + + // Verifies that a callback is not receiving profile ticks. + void VerifyUnregistration(const int& tick_counter) { + // Sleep for a bit and check that tick counter is not making progress. + int old_tick_count = tick_counter; + Delay(kSleepInterval); + int new_tick_count = tick_counter; + EXPECT_EQ(old_tick_count, new_tick_count); + // If no callbacks, timer should be disabled. + if (GetCallbackCount() == 0) { + EXPECT_FALSE(IsTimerEnabled()); + } + } + + // Verifies that the timer is disabled. Expects the worker to be running. + void VerifyDisabled() { + // Check that the callback count is 0. + EXPECT_EQ(0, GetCallbackCount()); + // Check that the timer is disabled. + EXPECT_FALSE(IsTimerEnabled()); + // Verify that the ProfileHandler is not accumulating profile ticks. + uint64 interrupts_before = GetInterruptCount(); + Delay(kSleepInterval); + uint64 interrupts_after = GetInterruptCount(); + EXPECT_EQ(interrupts_before, interrupts_after); + } + + // Registers a callback and waits for kTimerResetInterval for timers to get + // reset. + ProfileHandlerToken* RegisterCallback(void* callback_arg) { + ProfileHandlerToken* token = ProfileHandlerRegisterCallback( + TickCounter, callback_arg); + Delay(kTimerResetInterval); + return token; + } + + // Unregisters a callback and waits for kTimerResetInterval for timers to get + // reset. + void UnregisterCallback(ProfileHandlerToken* token) { + ProfileHandlerUnregisterCallback(token); + Delay(kTimerResetInterval); + } + + // Busy worker thread to accumulate cpu usage. + BusyThread* busy_worker_; + + private: + // The tests to run + void RegisterUnregisterCallback(); + void MultipleCallbacks(); + void Reset(); + void RegisterCallbackBeforeThread(); + + public: +#define RUN(test) do { \ + printf("Running %s\n", #test); \ + ProfileHandlerTest pht; \ + pht.SetUp(); \ + pht.test(); \ + pht.TearDown(); \ +} while (0) + + static int RUN_ALL_TESTS() { + SetUpTestCase(); + RUN(RegisterUnregisterCallback); + RUN(MultipleCallbacks); + RUN(Reset); + RUN(RegisterCallbackBeforeThread); + printf("Done\n"); + return 0; + } +}; + +// Verifies ProfileHandlerRegisterCallback and +// ProfileHandlerUnregisterCallback. +TEST_F(ProfileHandlerTest, RegisterUnregisterCallback) { + int tick_count = 0; + ProfileHandlerToken* token = RegisterCallback(&tick_count); + VerifyRegistration(tick_count); + UnregisterCallback(token); + VerifyUnregistration(tick_count); +} + +// Verifies that multiple callbacks can be registered. +TEST_F(ProfileHandlerTest, MultipleCallbacks) { + // Register first callback. + int first_tick_count = 0; + ProfileHandlerToken* token1 = RegisterCallback(&first_tick_count); + // Check that callback was registered correctly. + VerifyRegistration(first_tick_count); + EXPECT_EQ(1, GetCallbackCount()); + + // Register second callback. + int second_tick_count = 0; + ProfileHandlerToken* token2 = RegisterCallback(&second_tick_count); + // Check that callback was registered correctly. + VerifyRegistration(second_tick_count); + EXPECT_EQ(2, GetCallbackCount()); + + // Unregister first callback. + UnregisterCallback(token1); + VerifyUnregistration(first_tick_count); + EXPECT_EQ(1, GetCallbackCount()); + // Verify that second callback is still registered. + VerifyRegistration(second_tick_count); + + // Unregister second callback. + UnregisterCallback(token2); + VerifyUnregistration(second_tick_count); + EXPECT_EQ(0, GetCallbackCount()); + + // Verify that the timers is correctly disabled. + if (!linux_per_thread_timers_mode_) VerifyDisabled(); +} + +// Verifies ProfileHandlerReset +TEST_F(ProfileHandlerTest, Reset) { + // Verify that the profile timer interrupt is disabled. + if (!linux_per_thread_timers_mode_) VerifyDisabled(); + int first_tick_count = 0; + RegisterCallback(&first_tick_count); + VerifyRegistration(first_tick_count); + EXPECT_EQ(1, GetCallbackCount()); + + // Register second callback. + int second_tick_count = 0; + RegisterCallback(&second_tick_count); + VerifyRegistration(second_tick_count); + EXPECT_EQ(2, GetCallbackCount()); + + // Reset the profile handler and verify that callback were correctly + // unregistered and the timer is disabled. + ProfileHandlerReset(); + VerifyUnregistration(first_tick_count); + VerifyUnregistration(second_tick_count); + if (!linux_per_thread_timers_mode_) VerifyDisabled(); +} + +// Verifies that ProfileHandler correctly handles a case where a callback was +// registered before the second thread started. +TEST_F(ProfileHandlerTest, RegisterCallbackBeforeThread) { + // Stop the worker. + StopWorker(); + // Unregister all existing callbacks and stop the timer. + ProfileHandlerReset(); + EXPECT_EQ(0, GetCallbackCount()); + VerifyDisabled(); + + // Start the worker. + StartWorker(); + // Register a callback and check that profile ticks are being delivered and + // the timer is enabled. + int tick_count = 0; + RegisterCallback(&tick_count); + EXPECT_EQ(1, GetCallbackCount()); + VerifyRegistration(tick_count); + EXPECT_EQ(FLAGS_test_profiler_enabled, linux_per_thread_timers_mode_ || IsTimerEnabled()); +} + +} // namespace + +int main(int argc, char** argv) { + return ProfileHandlerTest::RUN_ALL_TESTS(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/profiledata_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/profiledata_unittest.cc new file mode 100644 index 000000000..3286b9c84 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/profiledata_unittest.cc @@ -0,0 +1,612 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Chris Demetriou +// +// This file contains the unit tests for the ProfileData class. + +#if defined HAVE_STDINT_H +#include // to get uintptr_t +#elif defined HAVE_INTTYPES_H +#include // another place uintptr_t might be defined +#endif +#include +#include +#include +#include +#include + +#include "profiledata.h" + +#include "base/commandlineflags.h" +#include "base/logging.h" + +using std::string; + +// Some helpful macros for the test class +#define TEST_F(cls, fn) void cls :: fn() + +namespace { + +template class scoped_array { + public: + scoped_array(T* data) : data_(data) { } + ~scoped_array() { delete[] data_; } + T* get() { return data_; } + T& operator[](int i) { return data_[i]; } + private: + T* const data_; +}; + +// Re-runs fn until it doesn't cause EINTR. +#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) + +// Read up to "count" bytes from file descriptor "fd" into the buffer +// starting at "buf" while handling short reads and EINTR. On +// success, return the number of bytes read. Otherwise, return -1. +static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) { + CHECK_GE(fd, 0); + char *buf0 = reinterpret_cast(buf); + ssize_t num_bytes = 0; + while (num_bytes < count) { + ssize_t len; + NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes)); + if (len < 0) { // There was an error other than EINTR. + return -1; + } + if (len == 0) { // Reached EOF. + break; + } + num_bytes += len; + } + CHECK(num_bytes <= count); + return num_bytes; +} + +// Thin wrapper around a file descriptor so that the file descriptor +// gets closed for sure. +struct FileDescriptor { + const int fd_; + explicit FileDescriptor(int fd) : fd_(fd) {} + ~FileDescriptor() { + if (fd_ >= 0) { + NO_INTR(close(fd_)); + } + } + int get() { return fd_; } +}; + +// must be the same as with ProfileData::Slot. +typedef uintptr_t ProfileDataSlot; + +// Quick and dirty function to make a number into a void* for use in a +// sample. +inline void* V(intptr_t x) { return reinterpret_cast(x); } + +// String returned by ProfileDataChecker helper functions to indicate success. +const char kNoError[] = ""; + +class ProfileDataChecker { + public: + ProfileDataChecker() { + const char* tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + mkdir(tmpdir, 0755); // if necessary + filename_ = string(tmpdir) + "/profiledata_unittest.tmp"; + } + + string filename() const { return filename_; } + + // Checks the first 'num_slots' profile data slots in the file + // against the data pointed to by 'slots'. Returns kNoError if the + // data matched, otherwise returns an indication of the cause of the + // mismatch. + string Check(const ProfileDataSlot* slots, int num_slots) { + return CheckWithSkips(slots, num_slots, NULL, 0); + } + + // Checks the first 'num_slots' profile data slots in the file + // against the data pointed to by 'slots', skipping over entries + // described by 'skips' and 'num_skips'. + // + // 'skips' must be a sorted list of (0-based) slot numbers to be + // skipped, of length 'num_skips'. Note that 'num_slots' includes + // any skipped slots, i.e., the first 'num_slots' profile data slots + // will be considered, but some may be skipped. + // + // Returns kNoError if the data matched, otherwise returns an + // indication of the cause of the mismatch. + string CheckWithSkips(const ProfileDataSlot* slots, int num_slots, + const int* skips, int num_skips); + + // Validate that a profile is correctly formed. The profile is + // assumed to have been created by the same kind of binary (e.g., + // same slot size, same endian, etc.) as is validating the profile. + // + // Returns kNoError if the profile appears valid, otherwise returns + // an indication of the problem with the profile. + string ValidateProfile(); + + private: + string filename_; +}; + +string ProfileDataChecker::CheckWithSkips(const ProfileDataSlot* slots, + int num_slots, const int* skips, + int num_skips) { + FileDescriptor fd(open(filename_.c_str(), O_RDONLY)); + if (fd.get() < 0) + return "file open error"; + + scoped_array filedata(new ProfileDataSlot[num_slots]); + size_t expected_bytes = num_slots * sizeof filedata[0]; + ssize_t bytes_read = ReadPersistent(fd.get(), filedata.get(), expected_bytes); + if (expected_bytes != bytes_read) + return "file too small"; + + for (int i = 0; i < num_slots; i++) { + if (num_skips > 0 && *skips == i) { + num_skips--; + skips++; + continue; + } + if (slots[i] != filedata[i]) + return "data mismatch"; + } + return kNoError; +} + +string ProfileDataChecker::ValidateProfile() { + FileDescriptor fd(open(filename_.c_str(), O_RDONLY)); + if (fd.get() < 0) + return "file open error"; + + struct stat statbuf; + if (fstat(fd.get(), &statbuf) != 0) + return "fstat error"; + if (statbuf.st_size != static_cast(statbuf.st_size)) + return "file impossibly large"; + ssize_t filesize = statbuf.st_size; + + scoped_array filedata(new char[filesize]); + if (ReadPersistent(fd.get(), filedata.get(), filesize) != filesize) + return "read of whole file failed"; + + // Must have enough data for the header and the trailer. + if (filesize < (5 + 3) * sizeof(ProfileDataSlot)) + return "not enough data in profile for header + trailer"; + + // Check the header + if (reinterpret_cast(filedata.get())[0] != 0) + return "error in header: non-zero count"; + if (reinterpret_cast(filedata.get())[1] != 3) + return "error in header: num_slots != 3"; + if (reinterpret_cast(filedata.get())[2] != 0) + return "error in header: non-zero format version"; + // Period (slot 3) can have any value. + if (reinterpret_cast(filedata.get())[4] != 0) + return "error in header: non-zero padding value"; + ssize_t cur_offset = 5 * sizeof(ProfileDataSlot); + + // While there are samples, skip them. Each sample consists of + // at least three slots. + bool seen_trailer = false; + while (!seen_trailer) { + if (cur_offset > filesize - 3 * sizeof(ProfileDataSlot)) + return "truncated sample header"; + ProfileDataSlot* sample = + reinterpret_cast(filedata.get() + cur_offset); + ProfileDataSlot slots_this_sample = 2 + sample[1]; + ssize_t size_this_sample = slots_this_sample * sizeof(ProfileDataSlot); + if (cur_offset > filesize - size_this_sample) + return "truncated sample"; + + if (sample[0] == 0 && sample[1] == 1 && sample[2] == 0) { + seen_trailer = true; + } else { + if (sample[0] < 1) + return "error in sample: sample count < 1"; + if (sample[1] < 1) + return "error in sample: num_pcs < 1"; + for (int i = 2; i < slots_this_sample; i++) { + if (sample[i] == 0) + return "error in sample: NULL PC"; + } + } + cur_offset += size_this_sample; + } + + // There must be at least one line in the (text) list of mapped objects, + // and it must be terminated by a newline. Note, the use of newline + // here and below Might not be reasonable on non-UNIX systems. + if (cur_offset >= filesize) + return "no list of mapped objects"; + if (filedata[filesize - 1] != '\n') + return "profile did not end with a complete line"; + + while (cur_offset < filesize) { + char* line_start = filedata.get() + cur_offset; + + // Find the end of the line, and replace it with a NUL for easier + // scanning. + char* line_end = strchr(line_start, '\n'); + *line_end = '\0'; + + // Advance past any leading space. It's allowed in some lines, + // but not in others. + bool has_leading_space = false; + char* line_cur = line_start; + while (*line_cur == ' ') { + has_leading_space = true; + line_cur++; + } + + bool found_match = false; + + // Check for build lines. + if (!found_match) { + found_match = (strncmp(line_cur, "build=", 6) == 0); + // Anything may follow "build=", and leading space is allowed. + } + + // A line from ProcMapsIterator::FormatLine, of the form: + // + // 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so + // + // Leading space is not allowed. The filename may be omitted or + // may consist of multiple words, so we scan only up to the + // space before the filename. + if (!found_match) { + int chars_scanned = -1; + sscanf(line_cur, "%*x-%*x %*c%*c%*c%*c %*x %*x:%*x %*d %n", + &chars_scanned); + found_match = (chars_scanned > 0 && !has_leading_space); + } + + // A line from DumpAddressMap, of the form: + // + // 40000000-40015000: /lib/ld-2.3.2.so + // + // Leading space is allowed. The filename may be omitted or may + // consist of multiple words, so we scan only up to the space + // before the filename. + if (!found_match) { + int chars_scanned = -1; + sscanf(line_cur, "%*x-%*x: %n", &chars_scanned); + found_match = (chars_scanned > 0); + } + + if (!found_match) + return "unrecognized line in text section"; + + cur_offset += (line_end - line_start) + 1; + } + + return kNoError; +} + +class ProfileDataTest { + protected: + void ExpectStopped() { + EXPECT_FALSE(collector_.enabled()); + } + + void ExpectRunningSamples(int samples) { + ProfileData::State state; + collector_.GetCurrentState(&state); + EXPECT_TRUE(state.enabled); + EXPECT_EQ(samples, state.samples_gathered); + } + + void ExpectSameState(const ProfileData::State& before, + const ProfileData::State& after) { + EXPECT_EQ(before.enabled, after.enabled); + EXPECT_EQ(before.samples_gathered, after.samples_gathered); + EXPECT_EQ(before.start_time, after.start_time); + EXPECT_STREQ(before.profile_name, after.profile_name); + } + + ProfileData collector_; + ProfileDataChecker checker_; + + private: + // The tests to run + void OpsWhenStopped(); + void StartStopEmpty(); + void StartStopNoOptionsEmpty(); + void StartWhenStarted(); + void StartStopEmpty2(); + void CollectOne(); + void CollectTwoMatching(); + void CollectTwoFlush(); + void StartResetRestart(); + + public: +#define RUN(test) do { \ + printf("Running %s\n", #test); \ + ProfileDataTest pdt; \ + pdt.test(); \ +} while (0) + + static int RUN_ALL_TESTS() { + RUN(OpsWhenStopped); + RUN(StartStopEmpty); + RUN(StartWhenStarted); + RUN(StartStopEmpty2); + RUN(CollectOne); + RUN(CollectTwoMatching); + RUN(CollectTwoFlush); + RUN(StartResetRestart); + RUN(StartStopNoOptionsEmpty); + return 0; + } +}; + +// Check that various operations are safe when stopped. +TEST_F(ProfileDataTest, OpsWhenStopped) { + ExpectStopped(); + EXPECT_FALSE(collector_.enabled()); + + // Verify that state is disabled, all-empty/all-0 + ProfileData::State state_before; + collector_.GetCurrentState(&state_before); + EXPECT_FALSE(state_before.enabled); + EXPECT_EQ(0, state_before.samples_gathered); + EXPECT_EQ(0, state_before.start_time); + EXPECT_STREQ("", state_before.profile_name); + + // Safe to call stop again. + collector_.Stop(); + + // Safe to call FlushTable. + collector_.FlushTable(); + + // Safe to call Add. + const void *trace[] = { V(100), V(101), V(102), V(103), V(104) }; + collector_.Add(arraysize(trace), trace); + + ProfileData::State state_after; + collector_.GetCurrentState(&state_after); + + ExpectSameState(state_before, state_after); +} + +// Start and Stop, collecting no samples. Verify output contents. +TEST_F(ProfileDataTest, StartStopEmpty) { + const int frequency = 1; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 0, 1, 0 // binary trailer + }; + + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +// Start and Stop with no options, collecting no samples. Verify +// output contents. +TEST_F(ProfileDataTest, StartStopNoOptionsEmpty) { + // We're not requesting a specific period, implementation can do + // whatever it likes. + ProfileDataSlot slots[] = { + 0, 3, 0, 0 /* skipped */, 0, // binary header + 0, 1, 0 // binary trailer + }; + int slots_to_skip[] = { 3 }; + + ExpectStopped(); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), + ProfileData::Options())); + ExpectRunningSamples(0); + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.CheckWithSkips(slots, arraysize(slots), + slots_to_skip, + arraysize(slots_to_skip))); +} + +// Start after already started. Should return false and not impact +// collected data or state. +TEST_F(ProfileDataTest, StartWhenStarted) { + const int frequency = 1; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 0, 1, 0 // binary trailer + }; + + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + + ProfileData::State state_before; + collector_.GetCurrentState(&state_before); + + options.set_frequency(frequency * 2); + CHECK(!collector_.Start("foobar", options)); + + ProfileData::State state_after; + collector_.GetCurrentState(&state_after); + ExpectSameState(state_before, state_after); + + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +// Like StartStopEmpty, but uses a different file name and frequency. +TEST_F(ProfileDataTest, StartStopEmpty2) { + const int frequency = 2; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 0, 1, 0 // binary trailer + }; + + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +TEST_F(ProfileDataTest, CollectOne) { + const int frequency = 2; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 1, 5, 100, 101, 102, 103, 104, // our sample + 0, 1, 0 // binary trailer + }; + + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + + const void *trace[] = { V(100), V(101), V(102), V(103), V(104) }; + collector_.Add(arraysize(trace), trace); + ExpectRunningSamples(1); + + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +TEST_F(ProfileDataTest, CollectTwoMatching) { + const int frequency = 2; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 2, 5, 100, 201, 302, 403, 504, // our two samples + 0, 1, 0 // binary trailer + }; + + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + + for (int i = 0; i < 2; ++i) { + const void *trace[] = { V(100), V(201), V(302), V(403), V(504) }; + collector_.Add(arraysize(trace), trace); + ExpectRunningSamples(i + 1); + } + + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +TEST_F(ProfileDataTest, CollectTwoFlush) { + const int frequency = 2; + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 1, 5, 100, 201, 302, 403, 504, // first sample (flushed) + 1, 5, 100, 201, 302, 403, 504, // second identical sample + 0, 1, 0 // binary trailer + }; + + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + + const void *trace[] = { V(100), V(201), V(302), V(403), V(504) }; + + collector_.Add(arraysize(trace), trace); + ExpectRunningSamples(1); + collector_.FlushTable(); + + collector_.Add(arraysize(trace), trace); + ExpectRunningSamples(2); + + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +// Start then reset, verify that the result is *not* a valid profile. +// Then start again and make sure the result is OK. +TEST_F(ProfileDataTest, StartResetRestart) { + ExpectStopped(); + ProfileData::Options options; + options.set_frequency(1); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + collector_.Reset(); + ExpectStopped(); + // We expect the resulting file to be empty. This is a minimal test + // of ValidateProfile. + EXPECT_NE(kNoError, checker_.ValidateProfile()); + + struct stat statbuf; + EXPECT_EQ(0, stat(checker_.filename().c_str(), &statbuf)); + EXPECT_EQ(0, statbuf.st_size); + + const int frequency = 2; // Different frequency than used above. + ProfileDataSlot slots[] = { + 0, 3, 0, 1000000 / frequency, 0, // binary header + 0, 1, 0 // binary trailer + }; + + options.set_frequency(frequency); + EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options)); + ExpectRunningSamples(0); + collector_.Stop(); + ExpectStopped(); + EXPECT_EQ(kNoError, checker_.ValidateProfile()); + EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots))); +} + +} // namespace + +int main(int argc, char** argv) { + int rc = ProfileDataTest::RUN_ALL_TESTS(); + printf("%s\n", rc == 0 ? "PASS" : "FAIL"); + return rc; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.cc new file mode 100644 index 000000000..4c814c09f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.cc @@ -0,0 +1,147 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 +// +// Does some simple arithmetic and a few libc routines, so we can profile it. +// Define WITH_THREADS to add pthread functionality as well (otherwise, btw, +// the num_threads argument to this program is ingored). + +#include "config_for_unittests.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include // for fork() +#endif +#include // for wait() +#include "gperftools/profiler.h" +#include "base/simple_mutex.h" +#include "tests/testutil.h" + +static volatile int result = 0; +static int g_iters = 0; // argv[1] + +Mutex mutex(Mutex::LINKER_INITIALIZED); + +static void test_other_thread() { +#ifndef NO_THREADS + ProfilerRegisterThread(); + + int i, m; + char b[128]; + MutexLock ml(&mutex); + for (m = 0; m < 1000000; ++m) { // run millions of times + for (i = 0; i < g_iters; ++i ) { + result ^= i; + } + snprintf(b, sizeof(b), "other: %d", result); // get some libc action + } +#endif +} + +static void test_main_thread() { + int i, m; + char b[128]; + MutexLock ml(&mutex); + for (m = 0; m < 1000000; ++m) { // run millions of times + for (i = 0; i < g_iters; ++i ) { + result ^= i; + } + snprintf(b, sizeof(b), "same: %d", result); // get some libc action + } +} + +int main(int argc, char** argv) { + if ( argc <= 1 ) { + fprintf(stderr, "USAGE: %s [num_threads] [filename]\n", argv[0]); + fprintf(stderr, " iters: How many million times to run the XOR test.\n"); + fprintf(stderr, " num_threads: how many concurrent threads.\n"); + fprintf(stderr, " 0 or 1 for single-threaded mode,\n"); + fprintf(stderr, " -# to fork instead of thread.\n"); + fprintf(stderr, " filename: The name of the output profile.\n"); + fprintf(stderr, (" If you don't specify, set CPUPROFILE " + "in the environment instead!\n")); + return 1; + } + + g_iters = atoi(argv[1]); + int num_threads = 1; + const char* filename = NULL; + if (argc > 2) { + num_threads = atoi(argv[2]); + } + if (argc > 3) { + filename = argv[3]; + } + + if (filename) { + ProfilerStart(filename); + } + + test_main_thread(); + + ProfilerFlush(); // just because we can + + // The other threads, if any, will run only half as long as the main thread + if(num_threads > 0) { + RunManyThreads(test_other_thread, num_threads); + } else { + // Or maybe they asked to fork. The fork test is only interesting + // when we use CPUPROFILE to name, so check for that +#ifdef HAVE_UNISTD_H + for (; num_threads < 0; ++num_threads) { // - to fork + if (filename) { + printf("FORK test only makes sense when no filename is specified.\n"); + return 2; + } + switch (fork()) { + case -1: + printf("FORK failed!\n"); + return 1; + case 0: // child + return execl(argv[0], argv[0], argv[1], NULL); + default: + wait(NULL); // we'll let the kids run one at a time + } + } +#else + fprintf(stderr, "%s was compiled without support for fork() and exec()\n", argv[0]); +#endif + } + + test_main_thread(); + + if (filename) { + ProfilerStop(); + } + + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.sh new file mode 100755 index 000000000..4085f2cd0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/profiler_unittest.sh @@ -0,0 +1,269 @@ +#!/bin/sh + +# 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 +# +# Runs the 4 profiler unittests and makes sure their profiles look +# appropriate. We expect two commandline args, as described below. +# +# We run under the assumption that if $PROFILER1 is run with no +# arguments, it prints a usage line of the form +# USAGE: [...] +# +# This is because libtool sometimes turns the 'executable' into a +# shell script which runs an actual binary somewhere else. + +# We expect BINDIR and PPROF_PATH to be set in the environment. +# If not, we set them to some reasonable values +BINDIR="${BINDIR:-.}" +PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir] [path to pprof]" + echo " By default, unittest_dir=$BINDIR, pprof_path=$PPROF_PATH" + exit 1 +fi + +TMPDIR=/tmp/profile_info + +UNITTEST_DIR=${1:-$BINDIR} +PPROF=${2:-$PPROF_PATH} + +# We test the sliding-window functionality of the cpu-profile reader +# by using a small stride, forcing lots of reads. +PPROF_FLAGS="--test_stride=128" + +PROFILER1="$UNITTEST_DIR/profiler1_unittest" +PROFILER2="$UNITTEST_DIR/profiler2_unittest" +PROFILER3="$UNITTEST_DIR/profiler3_unittest" +PROFILER4="$UNITTEST_DIR/profiler4_unittest" + +# Unfortunately, for us, libtool can replace executables with a shell +# script that does some work before calling the 'real' executable +# under a different name. We need the 'real' executable name to run +# pprof on it. We've constructed all the binaries used in this +# unittest so when they are called with no arguments, they report +# their argv[0], which is the real binary name. +Realname() { + "$1" 2>&1 | awk '{print $2; exit;}' +} + +PROFILER1_REALNAME=`Realname "$PROFILER1"` +PROFILER2_REALNAME=`Realname "$PROFILER2"` +PROFILER3_REALNAME=`Realname "$PROFILER3"` +PROFILER4_REALNAME=`Realname "$PROFILER4"` + +# It's meaningful to the profiler, so make sure we know its state +unset CPUPROFILE + +# Some output/logging in the profiler can cause issues when running the unit +# tests. For example, logging a warning when the profiler is detected as being +# present but no CPUPROFILE is specified in the environment. Especially when +# we are checking for a silent run or specific timing constraints are being +# checked. So set the env variable signifying that we are running in a unit +# test environment. +PERFTOOLS_UNITTEST=1 + +rm -rf "$TMPDIR" +mkdir "$TMPDIR" || exit 2 + +num_failures=0 + +RegisterFailure() { + num_failures=`expr $num_failures + 1` +} + +# Takes two filenames representing profiles, with their executable scripts, +# and a multiplier, and verifies that the 'contentful' functions in each +# profile take the same time (possibly scaled by the given multiplier). It +# used to be "same" meant within 50%, after adding an noise-reducing X units +# to each value. But even that would often spuriously fail, so now it's +# "both non-zero". We're pretty forgiving. +VerifySimilar() { + prof1="$TMPDIR/$1" + exec1="$2" + prof2="$TMPDIR/$3" + exec2="$4" + mult="$5" + + # We are careful not to put exec1 and exec2 in quotes, because if + # they are the empty string, it means we want to use the 1-arg + # version of pprof. + mthread1=`"$PPROF" $PPROF_FLAGS $exec1 "$prof1" | grep test_main_thread | awk '{print $1}'` + mthread2=`"$PPROF" $PPROF_FLAGS $exec2 "$prof2" | grep test_main_thread | awk '{print $1}'` + mthread1_plus=`expr $mthread1 + 5` + mthread2_plus=`expr $mthread2 + 5` + if [ -z "$mthread1" ] || [ -z "$mthread2" ] || \ + [ "$mthread1" -le 0 -o "$mthread2" -le 0 ] +# || [ `expr $mthread1_plus \* $mult` -gt `expr $mthread2_plus \* 2` -o \ +# `expr $mthread1_plus \* $mult \* 2` -lt `expr $mthread2_plus` ] + then + echo + echo ">>> profile on $exec1 vs $exec2 with multiplier $mult failed:" + echo "Actual times (in profiling units) were '$mthread1' vs. '$mthread2'" + echo + RegisterFailure + fi +} + +# Takes two filenames representing profiles, and optionally their +# executable scripts (these may be empty if the profiles include +# symbols), and verifies that the two profiles are identical. +VerifyIdentical() { + prof1="$TMPDIR/$1" + exec1="$2" + prof2="$TMPDIR/$3" + exec2="$4" + + # We are careful not to put exec1 and exec2 in quotes, because if + # they are the empty string, it means we want to use the 1-arg + # version of pprof. + "$PPROF" $PPROF_FLAGS $exec1 "$prof1" > "$TMPDIR/out1" + "$PPROF" $PPROF_FLAGS $exec2 "$prof2" > "$TMPDIR/out2" + diff=`diff "$TMPDIR/out1" "$TMPDIR/out2"` + + if [ ! -z "$diff" ]; then + echo + echo ">>> profile doesn't match, args: $exec1 $prof1 vs. $exec2 $prof2" + echo ">>> Diff:" + echo "$diff" + echo + RegisterFailure + fi +} + +# Takes a filename representing a profile, with its executable, +# and a multiplier, and verifies that the main-thread function takes +# the same amount of time as the other-threads function (possibly scaled +# by the given multiplier). Figuring out the multiplier can be tricky, +# since by design the main thread runs twice as long as each of the +# 'other' threads! It used to be "same" meant within 50%, after adding an +# noise-reducing X units to each value. But even that would often +# spuriously fail, so now it's "both non-zero". We're pretty forgiving. +VerifyAcrossThreads() { + prof1="$TMPDIR/$1" + # We need to run the script with no args to get the actual exe name + exec1="$2" + mult="$3" + + # We are careful not to put exec1 in quotes, because if it is the + # empty string, it means we want to use the 1-arg version of pprof. + mthread=`$PPROF $PPROF_FLAGS $exec1 "$prof1" | grep test_main_thread | awk '{print $1}'` + othread=`$PPROF $PPROF_FLAGS $exec1 "$prof1" | grep test_other_thread | awk '{print $1}'` + if [ -z "$mthread" ] || [ -z "$othread" ] || \ + [ "$mthread" -le 0 -o "$othread" -le 0 ] +# || [ `expr $mthread \* $mult \* 3` -gt `expr $othread \* 10` -o \ +# `expr $mthread \* $mult \* 10` -lt `expr $othread \* 3` ] + then + echo + echo ">>> profile on $exec1 (main vs thread) with multiplier $mult failed:" + echo "Actual times (in profiling units) were '$mthread' vs. '$othread'" + echo + RegisterFailure + fi +} + +echo +echo ">>> WARNING <<<" +echo "This test looks at timing information to determine correctness." +echo "If your system is loaded, the test may spuriously fail." +echo "If the test does fail with an 'Actual times' error, try running again." +echo + +# profiler1 is a non-threaded version +"$PROFILER1" 50 1 "$TMPDIR/p1" || RegisterFailure +"$PROFILER1" 100 1 "$TMPDIR/p2" || RegisterFailure +VerifySimilar p1 "$PROFILER1_REALNAME" p2 "$PROFILER1_REALNAME" 2 + +# Verify the same thing works if we statically link +"$PROFILER2" 50 1 "$TMPDIR/p3" || RegisterFailure +"$PROFILER2" 100 1 "$TMPDIR/p4" || RegisterFailure +VerifySimilar p3 "$PROFILER2_REALNAME" p4 "$PROFILER2_REALNAME" 2 + +# Verify the same thing works if we specify via CPUPROFILE +CPUPROFILE="$TMPDIR/p5" "$PROFILER2" 50 || RegisterFailure +CPUPROFILE="$TMPDIR/p6" "$PROFILER2" 100 || RegisterFailure +VerifySimilar p5 "$PROFILER2_REALNAME" p6 "$PROFILER2_REALNAME" 2 + +CPUPROFILE="$TMPDIR/p5b" "$PROFILER3" 30 || RegisterFailure +CPUPROFILE="$TMPDIR/p5c" "$PROFILER3" 60 || RegisterFailure +VerifySimilar p5b "$PROFILER3_REALNAME" p5c "$PROFILER3_REALNAME" 2 + +# Now try what happens when we use threads +"$PROFILER3" 30 2 "$TMPDIR/p7" || RegisterFailure +"$PROFILER3" 60 2 "$TMPDIR/p8" || RegisterFailure +VerifySimilar p7 "$PROFILER3_REALNAME" p8 "$PROFILER3_REALNAME" 2 + +"$PROFILER4" 30 2 "$TMPDIR/p9" || RegisterFailure +"$PROFILER4" 60 2 "$TMPDIR/p10" || RegisterFailure +VerifySimilar p9 "$PROFILER4_REALNAME" p10 "$PROFILER4_REALNAME" 2 + +# More threads! +"$PROFILER4" 25 3 "$TMPDIR/p9" || RegisterFailure +"$PROFILER4" 50 3 "$TMPDIR/p10" || RegisterFailure +VerifySimilar p9 "$PROFILER4_REALNAME" p10 "$PROFILER4_REALNAME" 2 + +# Compare how much time the main thread takes compared to the other threads +# Recall the main thread runs twice as long as the other threads, by design. +"$PROFILER4" 20 4 "$TMPDIR/p11" || RegisterFailure +VerifyAcrossThreads p11 "$PROFILER4_REALNAME" 2 + +# Test symbol save and restore +"$PROFILER1" 50 1 "$TMPDIR/p12" || RegisterFailure +"$PPROF" $PPROF_FLAGS "$PROFILER1_REALNAME" "$TMPDIR/p12" --raw \ + >"$TMPDIR/p13" 2>/dev/null || RegisterFailure +VerifyIdentical p12 "$PROFILER1_REALNAME" p13 "" || RegisterFailure + +"$PROFILER3" 30 2 "$TMPDIR/p14" || RegisterFailure +"$PPROF" $PPROF_FLAGS "$PROFILER3_REALNAME" "$TMPDIR/p14" --raw \ + >"$TMPDIR/p15" 2>/dev/null || RegisterFailure +VerifyIdentical p14 "$PROFILER3_REALNAME" p15 "" || RegisterFailure + +# Test using ITIMER_REAL instead of ITIMER_PROF. +env CPUPROFILE_REALTIME=1 "$PROFILER3" 30 2 "$TMPDIR/p16" || RegisterFailure +env CPUPROFILE_REALTIME=1 "$PROFILER3" 60 2 "$TMPDIR/p17" || RegisterFailure +VerifySimilar p16 "$PROFILER3_REALNAME" p17 "$PROFILER3_REALNAME" 2 + + +# Make sure that when we have a process with a fork, the profiles don't +# clobber each other +CPUPROFILE="$TMPDIR/pfork" "$PROFILER1" 1 -2 || RegisterFailure +n=`ls $TMPDIR/pfork* | wc -l` +if [ $n != 3 ]; then + echo "FORK test FAILED: expected 3 profiles (for main + 2 children), found $n" + num_failures=`expr $num_failures + 1` +fi + +rm -rf "$TMPDIR" # clean up + +echo "Tests finished with $num_failures failures" +exit $num_failures diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/raw_printer_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/raw_printer_test.cc new file mode 100644 index 000000000..2c7be6ac0 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/raw_printer_test.cc @@ -0,0 +1,64 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright 2009 Google Inc. All Rights Reserved. +// Author: sanjay@google.com (Sanjay Ghemawat) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + +#include "raw_printer.h" +#include +#include +#include "base/logging.h" + +using std::string; + +#define TEST(a, b) void TEST_##a##_##b() +#define RUN_TEST(a, b) TEST_##a##_##b() + +TEST(RawPrinter, Empty) { + char buffer[1]; + base::RawPrinter printer(buffer, arraysize(buffer)); + CHECK_EQ(0, printer.length()); + CHECK_EQ(string(""), buffer); + CHECK_EQ(0, printer.space_left()); + printer.Printf("foo"); + CHECK_EQ(string(""), string(buffer)); + CHECK_EQ(0, printer.length()); + CHECK_EQ(0, printer.space_left()); +} + +TEST(RawPrinter, PartiallyFilled) { + char buffer[100]; + base::RawPrinter printer(buffer, arraysize(buffer)); + printer.Printf("%s %s", "hello", "world"); + CHECK_EQ(string("hello world"), string(buffer)); + CHECK_EQ(11, printer.length()); + CHECK_LT(0, printer.space_left()); +} + +TEST(RawPrinter, Truncated) { + char buffer[3]; + base::RawPrinter printer(buffer, arraysize(buffer)); + printer.Printf("%d", 12345678); + CHECK_EQ(string("12"), string(buffer)); + CHECK_EQ(2, printer.length()); + CHECK_EQ(0, printer.space_left()); +} + +TEST(RawPrinter, ExactlyFilled) { + char buffer[12]; + base::RawPrinter printer(buffer, arraysize(buffer)); + printer.Printf("%s %s", "hello", "world"); + CHECK_EQ(string("hello world"), string(buffer)); + CHECK_EQ(11, printer.length()); + CHECK_EQ(0, printer.space_left()); +} + +int main(int argc, char **argv) { + RUN_TEST(RawPrinter, Empty); + RUN_TEST(RawPrinter, PartiallyFilled); + RUN_TEST(RawPrinter, Truncated); + RUN_TEST(RawPrinter, ExactlyFilled); + printf("PASS\n"); + return 0; // 0 means success +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/realloc_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/realloc_unittest.cc new file mode 100644 index 000000000..a4ea17ca4 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/realloc_unittest.cc @@ -0,0 +1,125 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2004, 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: Sanjay Ghemawat +// +// Test realloc() functionality + +#include "config_for_unittests.h" +#include // for assert +#include +#include // for size_t, NULL +#include // for free, malloc, realloc +#include // for min +#include "base/logging.h" + +using std::min; + + +// Fill a buffer of the specified size with a predetermined pattern +static void Fill(unsigned char* buffer, int n) { + for (int i = 0; i < n; i++) { + buffer[i] = (i & 0xff); + } +} + +// Check that the specified buffer has the predetermined pattern +// generated by Fill() +static bool Valid(unsigned char* buffer, int n) { + for (int i = 0; i < n; i++) { + if (buffer[i] != (i & 0xff)) { + return false; + } + } + return true; +} + +// Return the next interesting size/delta to check. Returns -1 if no more. +static int NextSize(int size) { + if (size < 100) { + return size+1; + } else if (size < 100000) { + // Find next power of two + int power = 1; + while (power < size) { + power <<= 1; + } + + // Yield (power-1, power, power+1) + if (size < power-1) { + return power-1; + } else if (size == power-1) { + return power; + } else { + assert(size == power); + return power+1; + } + } else { + return -1; + } +} + +int main(int argc, char** argv) { + for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) { + for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) { + unsigned char* src = (unsigned char*) malloc(src_size); + Fill(src, src_size); + unsigned char* dst = (unsigned char*) realloc(src, dst_size); + CHECK(Valid(dst, min(src_size, dst_size))); + Fill(dst, dst_size); + CHECK(Valid(dst, dst_size)); + if (dst != NULL) free(dst); + } + } + + // Now make sure realloc works correctly even when we overflow the + // packed cache, so some entries are evicted from the cache. + // The cache has 2^12 entries, keyed by page number. + const int kNumEntries = 1 << 14; + int** p = (int**)malloc(sizeof(*p) * kNumEntries); + int sum = 0; + for (int i = 0; i < kNumEntries; i++) { + p[i] = (int*)malloc(8192); // no page size is likely to be bigger + p[i][1000] = i; // use memory deep in the heart of p + } + for (int i = 0; i < kNumEntries; i++) { + p[i] = (int*)realloc(p[i], 9000); + } + for (int i = 0; i < kNumEntries; i++) { + sum += p[i][1000]; + free(p[i]); + } + CHECK_EQ(kNumEntries/2 * (kNumEntries - 1), sum); // assume kNE is even + free(p); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/sampler_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/sampler_test.cc new file mode 100644 index 000000000..4095d6af4 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/sampler_test.cc @@ -0,0 +1,631 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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. + +// --- +// All Rights Reserved. +// +// Author: Daniel Ford +// +// Checks basic properties of the sampler + +#include "config_for_unittests.h" +#include // defines posix_memalign +#include // for the printf at the end +#if defined HAVE_STDINT_H +#include // to get uintptr_t +#elif defined HAVE_INTTYPES_H +#include // another place uintptr_t might be defined +#endif +#include +#include +#include +#include +#include +#include +#include "base/logging.h" +#include "base/commandlineflags.h" +#include "sampler.h" // The Sampler class being tested + +using std::sort; +using std::min; +using std::max; +using std::vector; +using std::abs; + +vector g_testlist; // the tests to run + +#define TEST(a, b) \ + struct Test_##a##_##b { \ + Test_##a##_##b() { g_testlist.push_back(&Run); } \ + static void Run(); \ + }; \ + static Test_##a##_##b g_test_##a##_##b; \ + void Test_##a##_##b::Run() + + +static int RUN_ALL_TESTS() { + vector::const_iterator it; + for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { + (*it)(); // The test will error-exit if there's a problem. + } + fprintf(stderr, "\nPassed %d tests\n\nPASS\n", (int)g_testlist.size()); + return 0; +} + +#undef LOG // defined in base/logging.h +// Ideally, we'd put the newline at the end, but this hack puts the +// newline at the end of the previous log message, which is good enough :-) +#define LOG(level) std::cerr << "\n" + +static std::string StringPrintf(const char* format, ...) { + char buf[256]; // should be big enough for all logging + va_list ap; + va_start(ap, format); + perftools_vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + return buf; +} + +namespace { +template class scoped_array { + public: + scoped_array(T* p) : p_(p) { } + ~scoped_array() { delete[] p_; } + const T* get() const { return p_; } + T* get() { return p_; } + T& operator[](int i) { return p_[i]; } + private: + T* p_; +}; +} + +// Note that these tests are stochastic. +// This mean that the chance of correct code passing the test is, +// in the case of 5 standard deviations: +// kSigmas=5: ~99.99994267% +// in the case of 4 standard deviations: +// kSigmas=4: ~99.993666% +static const double kSigmas = 4; +static const size_t kSamplingInterval = 512*1024; + +// Tests that GetSamplePeriod returns the expected value +// which is 1<<19 +TEST(Sampler, TestGetSamplePeriod) { + tcmalloc::Sampler sampler; + sampler.Init(1); + uint64_t sample_period; + sample_period = sampler.GetSamplePeriod(); + CHECK_GT(sample_period, 0); +} + +// Tests of the quality of the random numbers generated +// This uses the Anderson Darling test for uniformity. +// See "Evaluating the Anderson-Darling Distribution" by Marsaglia +// for details. + +// Short cut version of ADinf(z), z>0 (from Marsaglia) +// This returns the p-value for Anderson Darling statistic in +// the limit as n-> infinity. For finite n, apply the error fix below. +double AndersonDarlingInf(double z) { + if (z < 2) { + return exp(-1.2337141 / z) / sqrt(z) * (2.00012 + (0.247105 - + (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 + * z) * z) * z) * z) * z); + } + return exp( - exp(1.0776 - (2.30695 - (0.43424 - (0.082433 - + (0.008056 - 0.0003146 * z) * z) * z) * z) * z)); +} + +// Corrects the approximation error in AndersonDarlingInf for small values of n +// Add this to AndersonDarlingInf to get a better approximation +// (from Marsaglia) +double AndersonDarlingErrFix(int n, double x) { + if (x > 0.8) { + return (-130.2137 + (745.2337 - (1705.091 - (1950.646 - + (1116.360 - 255.7844 * x) * x) * x) * x) * x) / n; + } + double cutoff = 0.01265 + 0.1757 / n; + double t; + if (x < cutoff) { + t = x / cutoff; + t = sqrt(t) * (1 - t) * (49 * t - 102); + return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n; + } else { + t = (x - cutoff) / (0.8 - cutoff); + t = -0.00022633 + (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 + * t) * t) * t) * t) * t; + return t * (0.04213 + 0.01365 / n) / n; + } +} + +// Returns the AndersonDarling p-value given n and the value of the statistic +double AndersonDarlingPValue(int n, double z) { + double ad = AndersonDarlingInf(z); + double errfix = AndersonDarlingErrFix(n, ad); + return ad + errfix; +} + +double AndersonDarlingStatistic(int n, double* random_sample) { + double ad_sum = 0; + for (int i = 0; i < n; i++) { + ad_sum += (2*i + 1) * log(random_sample[i] * (1 - random_sample[n-1-i])); + } + double ad_statistic = - n - 1/static_cast(n) * ad_sum; + return ad_statistic; +} + +// Tests if the array of doubles is uniformly distributed. +// Returns the p-value of the Anderson Darling Statistic +// for the given set of sorted random doubles +// See "Evaluating the Anderson-Darling Distribution" by +// Marsaglia and Marsaglia for details. +double AndersonDarlingTest(int n, double* random_sample) { + double ad_statistic = AndersonDarlingStatistic(n, random_sample); + LOG(INFO) << StringPrintf("AD stat = %f, n=%d\n", ad_statistic, n); + double p = AndersonDarlingPValue(n, ad_statistic); + return p; +} + +// Test the AD Test. The value of the statistic should go to zero as n->infty +// Not run as part of regular tests +void ADTestTest(int n) { + scoped_array random_sample(new double[n]); + for (int i = 0; i < n; i++) { + random_sample[i] = (i+0.01)/n; + } + sort(random_sample.get(), random_sample.get() + n); + double ad_stat = AndersonDarlingStatistic(n, random_sample.get()); + LOG(INFO) << StringPrintf("Testing the AD test. n=%d, ad_stat = %f", + n, ad_stat); +} + +// Print the CDF of the distribution of the Anderson-Darling Statistic +// Used for checking the Anderson-Darling Test +// Not run as part of regular tests +void ADCDF() { + for (int i = 1; i < 40; i++) { + double x = i/10.0; + LOG(INFO) << "x= " << x << " adpv= " + << AndersonDarlingPValue(100, x) << ", " + << AndersonDarlingPValue(1000, x); + } +} + +// Testing that NextRandom generates uniform +// random numbers. +// Applies the Anderson-Darling test for uniformity +void TestNextRandom(int n) { + tcmalloc::Sampler sampler; + sampler.Init(1); + uint64_t x = 1; + // This assumes that the prng returns 48 bit numbers + uint64_t max_prng_value = static_cast(1)<<48; + // Initialize + for (int i = 1; i <= 20; i++) { // 20 mimics sampler.Init() + x = sampler.NextRandom(x); + } + scoped_array int_random_sample(new uint64_t[n]); + // Collect samples + for (int i = 0; i < n; i++) { + int_random_sample[i] = x; + x = sampler.NextRandom(x); + } + // First sort them... + sort(int_random_sample.get(), int_random_sample.get() + n); + scoped_array random_sample(new double[n]); + // Convert them to uniform randoms (in the range [0,1]) + for (int i = 0; i < n; i++) { + random_sample[i] = static_cast(int_random_sample[i])/max_prng_value; + } + // Now compute the Anderson-Darling statistic + double ad_pvalue = AndersonDarlingTest(n, random_sample.get()); + LOG(INFO) << StringPrintf("pvalue for AndersonDarlingTest " + "with n= %d is p= %f\n", n, ad_pvalue); + CHECK_GT(min(ad_pvalue, 1 - ad_pvalue), 0.0001); + // << StringPrintf("prng is not uniform, %d\n", n); +} + + +TEST(Sampler, TestNextRandom_MultipleValues) { + TestNextRandom(10); // Check short-range correlation + TestNextRandom(100); + TestNextRandom(1000); + TestNextRandom(10000); // Make sure there's no systematic error +} + +// Tests that PickNextSamplePeriod generates +// geometrically distributed random numbers. +// First converts to uniforms then applied the +// Anderson-Darling test for uniformity. +void TestPickNextSample(int n) { + tcmalloc::Sampler sampler; + sampler.Init(1); + scoped_array int_random_sample(new uint64_t[n]); + int sample_period = sampler.GetSamplePeriod(); + int ones_count = 0; + for (int i = 0; i < n; i++) { + int_random_sample[i] = sampler.PickNextSamplingPoint(); + CHECK_GE(int_random_sample[i], 1); + if (int_random_sample[i] == 1) { + ones_count += 1; + } + CHECK_LT(ones_count, 4); // << " out of " << i << " samples."; + } + // First sort them... + sort(int_random_sample.get(), int_random_sample.get() + n); + scoped_array random_sample(new double[n]); + // Convert them to uniform random numbers + // by applying the geometric CDF + for (int i = 0; i < n; i++) { + random_sample[i] = 1 - exp(-static_cast(int_random_sample[i]) + / sample_period); + } + // Now compute the Anderson-Darling statistic + double geom_ad_pvalue = AndersonDarlingTest(n, random_sample.get()); + LOG(INFO) << StringPrintf("pvalue for geometric AndersonDarlingTest " + "with n= %d is p= %f\n", n, geom_ad_pvalue); + CHECK_GT(min(geom_ad_pvalue, 1 - geom_ad_pvalue), 0.0001); + // << "PickNextSamplingPoint does not produce good " + // "geometric/exponential random numbers\n"; +} + +TEST(Sampler, TestPickNextSample_MultipleValues) { + TestPickNextSample(10); // Make sure the first few are good (enough) + TestPickNextSample(100); + TestPickNextSample(1000); + TestPickNextSample(10000); // Make sure there's no systematic error +} + + +// This is superceeded by the Anderson-Darling Test +// and it not run now. +// Tests how fast nearby values are spread out with LRand64 +// The purpose of this code is to determine how many +// steps to apply to the seed during initialization +void TestLRand64Spread() { + tcmalloc::Sampler sampler; + sampler.Init(1); + uint64_t current_value; + printf("Testing LRand64 Spread\n"); + for (int i = 1; i < 10; i++) { + printf("%d ", i); + current_value = i; + for (int j = 1; j < 100; j++) { + current_value = sampler.NextRandom(current_value); + } + LOG(INFO) << current_value; + } +} + + +// Futher tests + +bool CheckMean(size_t mean, int num_samples) { + tcmalloc::Sampler sampler; + sampler.Init(1); + size_t total = 0; + for (int i = 0; i < num_samples; i++) { + total += sampler.PickNextSamplingPoint(); + } + double empirical_mean = total / static_cast(num_samples); + double expected_sd = mean / pow(num_samples * 1.0, 0.5); + return(fabs(mean-empirical_mean) < expected_sd * kSigmas); +} + +// Prints a sequence so you can look at the distribution +void OutputSequence(int sequence_length) { + tcmalloc::Sampler sampler; + sampler.Init(1); + size_t next_step; + for (int i = 0; i< sequence_length; i++) { + next_step = sampler.PickNextSamplingPoint(); + LOG(INFO) << next_step; + } +} + + +double StandardDeviationsErrorInSample( + int total_samples, int picked_samples, + int alloc_size, int sampling_interval) { + double p = 1 - exp(-(static_cast(alloc_size) / sampling_interval)); + double expected_samples = total_samples * p; + double sd = pow(p*(1-p)*total_samples, 0.5); + return((picked_samples - expected_samples) / sd); +} + +TEST(Sampler, LargeAndSmallAllocs_CombinedTest) { + tcmalloc::Sampler sampler; + sampler.Init(1); + int counter_big = 0; + int counter_small = 0; + int size_big = 129*8*1024+1; + int size_small = 1024*8; + int num_iters = 128*4*8; + // Allocate in mixed chunks + for (int i = 0; i < num_iters; i++) { + if (!sampler.RecordAllocation(size_big)) { + counter_big += 1; + } + for (int i = 0; i < 129; i++) { + if (!sampler.RecordAllocation(size_small)) { + counter_small += 1; + } + } + } + // Now test that there are the right number of each + double large_allocs_sds = + StandardDeviationsErrorInSample(num_iters, counter_big, + size_big, kSamplingInterval); + double small_allocs_sds = + StandardDeviationsErrorInSample(num_iters*129, counter_small, + size_small, kSamplingInterval); + LOG(INFO) << StringPrintf("large_allocs_sds = %f\n", large_allocs_sds); + LOG(INFO) << StringPrintf("small_allocs_sds = %f\n", small_allocs_sds); + CHECK_LE(fabs(large_allocs_sds), kSigmas); + CHECK_LE(fabs(small_allocs_sds), kSigmas); +} + +// Tests whether the mean is about right over 1000 samples +TEST(Sampler, IsMeanRight) { + CHECK(CheckMean(kSamplingInterval, 1000)); +} + +// This flag is for the OldSampler class to use +const int64 FLAGS_mock_tcmalloc_sample_parameter = 1<<19; + +// A cut down and slightly refactored version of the old Sampler +class OldSampler { + public: + void Init(uint32_t seed); + void Cleanup() {} + + // Record allocation of "k" bytes. Return true iff allocation + // should be sampled + bool SampleAllocation(size_t k); + + // Generate a geometric with mean 1M (or FLAG value) + void PickNextSample(size_t k); + + // Initialize the statics for the Sample class + static void InitStatics() { + sample_period = 1048583; + } + size_t bytes_until_sample_; + + private: + uint32_t rnd_; // Cheap random number generator + static uint64_t sample_period; + // Should be a prime just above a power of 2: + // 2, 5, 11, 17, 37, 67, 131, 257, + // 521, 1031, 2053, 4099, 8209, 16411, + // 32771, 65537, 131101, 262147, 524309, 1048583, + // 2097169, 4194319, 8388617, 16777259, 33554467 +}; + +// Statics for OldSampler +uint64_t OldSampler::sample_period; + +void OldSampler::Init(uint32_t seed) { + // Initialize PRNG -- run it for a bit to get to good values + if (seed != 0) { + rnd_ = seed; + } else { + rnd_ = 12345; + } + bytes_until_sample_ = 0; + for (int i = 0; i < 100; i++) { + PickNextSample(sample_period * 2); + } +}; + +// A cut-down version of the old PickNextSampleRoutine +void OldSampler::PickNextSample(size_t k) { + // Make next "random" number + // x^32+x^22+x^2+x^1+1 is a primitive polynomial for random numbers + static const uint32_t kPoly = (1 << 22) | (1 << 2) | (1 << 1) | (1 << 0); + uint32_t r = rnd_; + rnd_ = (r << 1) ^ ((static_cast(r) >> 31) & kPoly); + + // Next point is "rnd_ % (sample_period)". I.e., average + // increment is "sample_period/2". + const int flag_value = FLAGS_mock_tcmalloc_sample_parameter; + static int last_flag_value = -1; + + if (flag_value != last_flag_value) { + // There should be a spinlock here, but this code is + // for benchmarking only. + sample_period = 1048583; + last_flag_value = flag_value; + } + + bytes_until_sample_ += rnd_ % sample_period; + + if (k > (static_cast(-1) >> 2)) { + // If the user has asked for a huge allocation then it is possible + // for the code below to loop infinitely. Just return (note that + // this throws off the sampling accuracy somewhat, but a user who + // is allocating more than 1G of memory at a time can live with a + // minor inaccuracy in profiling of small allocations, and also + // would rather not wait for the loop below to terminate). + return; + } + + while (bytes_until_sample_ < k) { + // Increase bytes_until_sample_ by enough average sampling periods + // (sample_period >> 1) to allow us to sample past the current + // allocation. + bytes_until_sample_ += (sample_period >> 1); + } + + bytes_until_sample_ -= k; +} + +inline bool OldSampler::SampleAllocation(size_t k) { + if (bytes_until_sample_ < k) { + PickNextSample(k); + return true; + } else { + bytes_until_sample_ -= k; + return false; + } +} + +// This checks that the stated maximum value for the +// tcmalloc_sample_parameter flag never overflows bytes_until_sample_ +TEST(Sampler, bytes_until_sample_Overflow_Underflow) { + tcmalloc::Sampler sampler; + sampler.Init(1); + uint64_t one = 1; + // sample_parameter = 0; // To test the edge case + uint64_t sample_parameter_array[4] = {0, 1, one<<19, one<<58}; + for (int i = 0; i < 4; i++) { + uint64_t sample_parameter = sample_parameter_array[i]; + LOG(INFO) << "sample_parameter = " << sample_parameter; + double sample_scaling = - log(2.0) * sample_parameter; + // Take the top 26 bits as the random number + // (This plus the 1<<26 sampling bound give a max step possible of + // 1209424308 bytes.) + const uint64_t prng_mod_power = 48; // Number of bits in prng + + // First, check the largest_prng value + uint64_t largest_prng_value = (static_cast(1)<<48) - 1; + double q = (largest_prng_value >> (prng_mod_power - 26)) + 1.0; + LOG(INFO) << StringPrintf("q = %f\n", q); + LOG(INFO) << StringPrintf("log2(q) = %f\n", log(q)/log(2.0)); + uint64_t smallest_sample_step + = static_cast(min(log2(q) - 26, 0.0) + * sample_scaling + 1); + LOG(INFO) << "Smallest sample step is " << smallest_sample_step; + uint64_t cutoff = static_cast(10) + * (sample_parameter/(one<<24) + 1); + LOG(INFO) << "Acceptable value is < " << cutoff; + // This checks that the answer is "small" and positive + CHECK_LE(smallest_sample_step, cutoff); + + // Next, check with the smallest prng value + uint64_t smallest_prng_value = 0; + q = (smallest_prng_value >> (prng_mod_power - 26)) + 1.0; + LOG(INFO) << StringPrintf("q = %f\n", q); + uint64_t largest_sample_step + = static_cast(min(log2(q) - 26, 0.0) + * sample_scaling + 1); + LOG(INFO) << "Largest sample step is " << largest_sample_step; + CHECK_LE(largest_sample_step, one<<63); + CHECK_GE(largest_sample_step, smallest_sample_step); + } +} + + +// Test that NextRand is in the right range. Unfortunately, this is a +// stochastic test which could miss problems. +TEST(Sampler, NextRand_range) { + tcmalloc::Sampler sampler; + sampler.Init(1); + uint64_t one = 1; + // The next number should be (one << 48) - 1 + uint64_t max_value = (one << 48) - 1; + uint64_t x = (one << 55); + int n = 22; // 27; + LOG(INFO) << "Running sampler.NextRandom 1<<" << n << " times"; + for (int i = 1; i <= (1<>27); i++) { // 20 mimics sampler.Init() + rnd = sampler.NextRandom(rnd); + CHECK_LE(rnd, max_value); + double q = (rnd >> (prng_mod_power - 26)) + 1.0; + CHECK_GE(q, 0); // << rnd << " " << prng_mod_power; + } + // Test some potentially out of bounds value for rnd + for (int i = 1; i <= 63; i++) { + rnd = one << i; + double q = (rnd >> (prng_mod_power - 26)) + 1.0; + LOG(INFO) << "rnd = " << rnd << " i=" << i << " q=" << q; + CHECK_GE(q, 0); + // << " rnd=" << rnd << " i=" << i << " prng_mod_power" << prng_mod_power; + } +} + +void test_arithmetic(uint64_t rnd) { + const uint64_t prng_mod_power = 48; // Number of bits in prng + uint64_t shifted_rnd = rnd >> (prng_mod_power - 26); + CHECK_GE(shifted_rnd, 0); + CHECK_LT(shifted_rnd, (1<<26)); + LOG(INFO) << shifted_rnd; + LOG(INFO) << static_cast(shifted_rnd); + CHECK_GE(static_cast(static_cast(shifted_rnd)), 0); + // << " rnd=" << rnd << " srnd=" << shifted_rnd; + CHECK_GE(static_cast(shifted_rnd), 0); + // << " rnd=" << rnd << " srnd=" << shifted_rnd; + double q = static_cast(shifted_rnd) + 1.0; + CHECK_GT(q, 0); +} + +// Tests certain arithmetic operations to make sure they compute what we +// expect them too (for testing across different platforms) +// know bad values under with -c dbg --cpu piii for _some_ binaries: +// rnd=227453640600554 +// shifted_rnd=54229173 +// (hard to reproduce) +TEST(Sampler, arithmetic_2) { + uint64_t rnd = 227453640600554LL; + test_arithmetic(rnd); +} + + +// It's not really a test, but it's good to know +TEST(Sample, size_of_class) { + tcmalloc::Sampler sampler; + sampler.Init(1); + LOG(INFO) << "Size of Sampler class is: " << sizeof(tcmalloc::Sampler); + LOG(INFO) << "Size of Sampler object is: " << sizeof(sampler); +} + +// Make sure sampling is enabled, or the tests won't work right. +DECLARE_int64(tcmalloc_sample_parameter); + +int main(int argc, char **argv) { + if (FLAGS_tcmalloc_sample_parameter == 0) + FLAGS_tcmalloc_sample_parameter = 524288; + return RUN_ALL_TESTS(); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.cc new file mode 100644 index 000000000..729aba8a7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.cc @@ -0,0 +1,83 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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 tests ReadStackTraces and ReadGrowthStackTraces. It does this +// by doing a bunch of allocations and then calling those functions. +// A driver shell-script can call this, and then call pprof, and +// verify the expected output. The output is written to +// argv[1].heap and argv[1].growth + +#include "config_for_unittests.h" +#include +#include +#include +#include "base/logging.h" +#include + +using std::string; + +extern "C" void* AllocateAllocate() ATTRIBUTE_NOINLINE; + +extern "C" void* AllocateAllocate() { + // The VLOG's are mostly to discourage inlining + VLOG(1, "Allocating some more"); + void* p = malloc(10000); + VLOG(1, "Done allocating"); + return p; +} + +static void WriteStringToFile(const string& s, const string& filename) { + FILE* fp = fopen(filename.c_str(), "w"); + fwrite(s.data(), 1, s.length(), fp); + fclose(fp); +} + +int main(int argc, char** argv) { + if (argc < 2) { + fprintf(stderr, "USAGE: %s \n", argv[0]); + exit(1); + } + for (int i = 0; i < 8000; i++) { + AllocateAllocate(); + } + + string s; + MallocExtension::instance()->GetHeapSample(&s); + WriteStringToFile(s, string(argv[1]) + ".heap"); + + s.clear(); + MallocExtension::instance()->GetHeapGrowthStacks(&s); + WriteStringToFile(s, string(argv[1]) + ".growth"); + + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.sh new file mode 100755 index 000000000..2a5842681 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/sampling_test.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +# Copyright (c) 2008, 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 a test that tcmalloc creates, and pprof reads, sampling data +# correctly: both for the heap profile (ReadStackTraces) and for +# growth in the heap sized (ReadGrowthStackTraces). + +BINDIR="${BINDIR:-.}" +PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}" + +if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then + echo "USAGE: $0 [unittest dir] [path to pprof]" + echo " By default, unittest_dir=$BINDIR, pprof_path=$PPROF_PATH" + exit 1 +fi + +SAMPLING_TEST="${1:-$BINDIR/sampling_test}" +PPROF="${2:-$PPROF_PATH}" +OUTDIR="/tmp/sampling_test_dir" + +# libtool is annoying, and puts the actual executable in a different +# directory, replacing the seeming-executable with a shell script. +# We use the error output of sampling_test to indicate its real location +SAMPLING_TEST_BINARY=`"$SAMPLING_TEST" 2>&1 | awk '/USAGE/ {print $2; exit;}'` + +# A kludge for cygwin. Unfortunately, 'test -f' says that 'foo' exists +# even when it doesn't, and only foo.exe exists. Other unix utilities +# (like nm) need you to say 'foo.exe'. We use one such utility, cat, to +# see what the *real* binary name is. +if ! cat "$SAMPLING_TEST_BINARY" >/dev/null 2>&1; then + SAMPLING_TEST_BINARY="$SAMPLING_TEST_BINARY".exe +fi + +die() { # runs the command given as arguments, and then dies. + echo "FAILED. Output from $@" + echo "----" + "$@" + echo "----" + exit 1 +} + +rm -rf "$OUTDIR" || die "Unable to delete $OUTDIR" +mkdir "$OUTDIR" || die "Unable to create $OUTDIR" + +# This puts the output into out.heap and out.growth. It allocates +# 8*10^7 bytes of memory, which is 76M. Because we sample, the +# estimate may be a bit high or a bit low: we accept anything from +# 50M to 99M. +"$SAMPLING_TEST" "$OUTDIR/out" + +echo "Testing heap output..." +"$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.heap" \ + | grep '[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \ + || die "$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.heap" +echo "OK" + +echo "Testing growth output..." +"$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.growth" \ + | grep '[5-9][0-9]\.[0-9][ 0-9.%]*_*AllocateAllocate' >/dev/null \ + || die "$PPROF" --text "$SAMPLING_TEST_BINARY" "$OUTDIR/out.growth" +echo "OK" + +echo "PASS" diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/simple_compat_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/simple_compat_test.cc new file mode 100644 index 000000000..24583a04b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/simple_compat_test.cc @@ -0,0 +1,71 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2012, 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 just verifies that we can compile code that #includes stuff +// via the backwards-compatibility 'google/' #include-dir. It does +// not include config.h on purpose, to better simulate a perftools +// client. + +#include +#include + +#define GPERFTOOLS_SUPPRESS_LEGACY_WARNING + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// We don't link in -lprofiler for this test, so be sure not to make +// any function calls that require the cpu-profiler code. The +// heap-profiler is ok. + +HeapLeakChecker::Disabler* heap_checker_h; +void (*heap_profiler_h)(const char*) = &HeapProfilerStart; +MallocExtension::Ownership malloc_extension_h; +MallocExtension_Ownership malloc_extension_c_h; +MallocHook::NewHook* malloc_hook_h; +MallocHook_NewHook* malloc_hook_c_h; +ProfilerOptions* profiler_h; +int (*stacktrace_h)(void**, int, int) = &GetStackTrace; +void* (*tcmalloc_h)(size_t) = &tc_new; + +int main(int argc, char** argv) { + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/stack_trace_table_test.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/stack_trace_table_test.cc new file mode 100644 index 000000000..393ebbe12 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/stack_trace_table_test.cc @@ -0,0 +1,93 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright 2009 Google Inc. All Rights Reserved. +// Author: fikes@google.com (Andrew Fikes) +// +// Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + + +#include "config_for_unittests.h" +#include // for puts() +#include "stack_trace_table.h" +#include "base/logging.h" +#include "base/spinlock.h" +#include "static_vars.h" + +#undef ARRAYSIZE // may be defined on, eg, windows +#define ARRAYSIZE(a) ( sizeof(a) / sizeof(*(a)) ) + +static void CheckTracesAndReset(tcmalloc::StackTraceTable* table, + const uintptr_t* expected, int len) { + void** entries = table->ReadStackTracesAndClear(); + for (int i = 0; i < len; ++i) { + CHECK_EQ(reinterpret_cast(entries[i]), expected[i]); + } + delete[] entries; +} + +static void AddTrace(tcmalloc::StackTraceTable* table, + const tcmalloc::StackTrace& t) { + // Normally we'd need this lock, but since the test is single-threaded + // we don't. I comment it out on windows because the DLL-decl thing + // is really annoying in this case. +#ifndef _MSC_VER + SpinLockHolder h(tcmalloc::Static::pageheap_lock()); +#endif + table->AddTrace(t); +} + +int main(int argc, char **argv) { + tcmalloc::StackTraceTable table; + + // Empty table + CHECK_EQ(table.depth_total(), 0); + CHECK_EQ(table.bucket_total(), 0); + static const uintptr_t k1[] = {0}; + CheckTracesAndReset(&table, k1, ARRAYSIZE(k1)); + + tcmalloc::StackTrace t1; + t1.size = static_cast(1024); + t1.depth = static_cast(2); + t1.stack[0] = reinterpret_cast(1); + t1.stack[1] = reinterpret_cast(2); + + + tcmalloc::StackTrace t2; + t2.size = static_cast(512); + t2.depth = static_cast(2); + t2.stack[0] = reinterpret_cast(2); + t2.stack[1] = reinterpret_cast(1); + + // Table w/ just t1 + AddTrace(&table, t1); + CHECK_EQ(table.depth_total(), 2); + CHECK_EQ(table.bucket_total(), 1); + static const uintptr_t k2[] = {1, 1024, 2, 1, 2, 0}; + CheckTracesAndReset(&table, k2, ARRAYSIZE(k2)); + + // Table w/ t1, t2 + AddTrace(&table, t1); + AddTrace(&table, t2); + CHECK_EQ(table.depth_total(), 4); + CHECK_EQ(table.bucket_total(), 2); + static const uintptr_t k3[] = {1, 512, 2, 2, 1, 1, 1024, 2, 1, 2, 0}; + CheckTracesAndReset(&table, k3, ARRAYSIZE(k3)); + + // Table w/ t1, t3 + // Same stack as t1, but w/ different size + tcmalloc::StackTrace t3; + t3.size = static_cast(2); + t3.depth = static_cast(2); + t3.stack[0] = reinterpret_cast(1); + t3.stack[1] = reinterpret_cast(2); + + AddTrace(&table, t1); + AddTrace(&table, t3); + CHECK_EQ(table.depth_total(), 4); + CHECK_EQ(table.bucket_total(), 2); + static const uintptr_t k5[] = {1, 2, 2, 1, 2, 1, 1024, 2, 1, 2, 0}; + CheckTracesAndReset(&table, k5, ARRAYSIZE(k5)); + + puts("PASS"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/stacktrace_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/stacktrace_unittest.cc new file mode 100644 index 000000000..e55a6322e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/stacktrace_unittest.cc @@ -0,0 +1,298 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +#include "config_for_unittests.h" +#ifdef HAVE_EXECINFO_H +#include +#endif +#include +#include + +// On those architectures we can and should test if backtracing with +// ucontext and from signal handler works +#if __GNUC__ && __linux__ && (__x86_64__ || __aarch64__ || __riscv) +#include +#define TEST_UCONTEXT_BITS 1 +#endif + +#include "base/commandlineflags.h" +#include "base/logging.h" +#include +#include "tests/testutil.h" + +namespace { + +// Obtain a backtrace, verify that the expected callers are present in the +// backtrace, and maybe print the backtrace to stdout. + +// The sequence of functions whose return addresses we expect to see in the +// backtrace. +const int BACKTRACE_STEPS = 6; + +struct AddressRange { + const void *start, *end; +}; + +// Expected function [start,end] range. +AddressRange expected_range[BACKTRACE_STEPS]; + +#if __GNUC__ +// Using GCC extension: address of a label can be taken with '&&label'. +// Start should be a label somewhere before recursive call, end somewhere +// after it. +#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ + do { \ + (prange)->start = &&start_label; \ + (prange)->end = &&end_label; \ + CHECK_LT((prange)->start, (prange)->end); \ + } while (0) +// This macro expands into "unmovable" code (opaque to GCC), and that +// prevents GCC from moving a_label up or down in the code. +// Without it, there is no code following the 'end' label, and GCC +// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before +// the recursive call. +#define DECLARE_ADDRESS_LABEL(a_label) \ + a_label: do { __asm__ __volatile__(""); } while (0) +// Gcc 4.4.0 may split function into multiple chunks, and the chunk +// performing recursive call may end up later in the code then the return +// instruction (this actually happens with FDO). +// Adjust function range from __builtin_return_address. +#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \ + do { \ + void *ra = __builtin_return_address(0); \ + CHECK_LT((prange)->start, ra); \ + if (ra > (prange)->end) { \ + printf("Adjusting range from %p..%p to %p..%p\n", \ + (prange)->start, (prange)->end, \ + (prange)->start, ra); \ + (prange)->end = ra; \ + } \ + } while (0) +#else +// Assume the Check* functions below are not longer than 256 bytes. +#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ + do { \ + (prange)->start = reinterpret_cast(&fn); \ + (prange)->end = reinterpret_cast(&fn) + 256; \ + } while (0) +#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0) +#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0) +#endif // __GNUC__ + + +//-----------------------------------------------------------------------// + +void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range) +{ + CHECK_GE(ret_addr, range.start); + CHECK_LE(ret_addr, range.end); +} + +//-----------------------------------------------------------------------// + +#if TEST_UCONTEXT_BITS + +struct get_stack_trace_args { + int *size_ptr; + void **result; + int max_depth; + uintptr_t where; +} gst_args; + +static +void SignalHandler(int dummy, siginfo_t *si, void* ucv) { + auto uc = static_cast(ucv); + +#ifdef __riscv + uc->uc_mcontext.__gregs[REG_PC] = gst_args.where; +#elif __aarch64__ + uc->uc_mcontext.pc = gst_args.where; +#else + uc->uc_mcontext.gregs[REG_RIP] = gst_args.where; +#endif + + *gst_args.size_ptr = GetStackTraceWithContext( + gst_args.result, + gst_args.max_depth, + 2, + uc); +} + +int ATTRIBUTE_NOINLINE CaptureLeafUContext(void **stack, int stack_len) { + INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]); + DECLARE_ADDRESS_LABEL(start); + + int size; + + printf("Capturing stack trace from signal's ucontext\n"); + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = SignalHandler; + sa.sa_flags = SA_SIGINFO | SA_RESETHAND; + int rv = sigaction(SIGSEGV, &sa, nullptr); + CHECK(rv == 0); + + gst_args.size_ptr = &size; + gst_args.result = stack; + gst_args.max_depth = stack_len; + gst_args.where = reinterpret_cast(noopt(&&after)); + + // now, "write" to null pointer and trigger sigsegv to run signal + // handler. It'll then change PC to after, as if we jumped one line + // below. + *noopt(reinterpret_cast(0)) = 0; + // this is not reached, but gcc gets really odd if we don't actually + // use computed goto. + static void* jump_target = &&after; + goto *noopt(&jump_target); + +after: + printf("Obtained %d stack frames.\n", size); + CHECK_GE(size, 1); + CHECK_LE(size, stack_len); + + DECLARE_ADDRESS_LABEL(end); + + return size; +} + +#endif // TEST_UCONTEXT_BITS + +int ATTRIBUTE_NOINLINE CaptureLeafPlain(void **stack, int stack_len) { + INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]); + DECLARE_ADDRESS_LABEL(start); + + int size = GetStackTrace(stack, stack_len, 0); + + printf("Obtained %d stack frames.\n", size); + CHECK_GE(size, 1); + CHECK_LE(size, stack_len); + + DECLARE_ADDRESS_LABEL(end); + + return size; +} + +void ATTRIBUTE_NOINLINE CheckStackTrace(int); + +int (*leaf_capture_fn)(void**, int) = CaptureLeafPlain; + +void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(int i) { + const int STACK_LEN = 20; + void *stack[STACK_LEN]; + int size; + + ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]); + + size = leaf_capture_fn(stack, STACK_LEN); + +#ifdef HAVE_EXECINFO_H + { + char **strings = backtrace_symbols(stack, size); + for (int i = 0; i < size; i++) + printf("%s %p\n", strings[i], stack[i]); + printf("CheckStackTrace() addr: %p\n", &CheckStackTrace); + free(strings); + } +#endif + + for (int i = 0, j = 0; i < BACKTRACE_STEPS; i++, j++) { + if (i == 1 && j == 1) { + // this is expected to be our function for which we don't + // establish bounds. So skip. + j++; + } + printf("Backtrace %d: expected: %p..%p actual: %p ... ", + i, expected_range[i].start, expected_range[i].end, stack[j]); + fflush(stdout); + CheckRetAddrIsInFunction(stack[j], expected_range[i]); + printf("OK\n"); + } +} + +//-----------------------------------------------------------------------// + +/* Dummy functions to make the backtrace more interesting. */ +void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) { + ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]); + INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]); + DECLARE_ADDRESS_LABEL(start); + for (int j = i; j >= 0; j--) + CheckStackTraceLeaf(j); + DECLARE_ADDRESS_LABEL(end); +} +void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) { + ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]); + INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]); + DECLARE_ADDRESS_LABEL(start); + for (int j = i; j >= 0; j--) + CheckStackTrace4(j); + DECLARE_ADDRESS_LABEL(end); +} +void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) { + ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]); + INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]); + DECLARE_ADDRESS_LABEL(start); + for (int j = i; j >= 0; j--) + CheckStackTrace3(j); + DECLARE_ADDRESS_LABEL(end); +} +void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) { + ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]); + INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]); + DECLARE_ADDRESS_LABEL(start); + for (int j = i; j >= 0; j--) + CheckStackTrace2(j); + DECLARE_ADDRESS_LABEL(end); +} +void ATTRIBUTE_NOINLINE CheckStackTrace(int i) { + INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]); + DECLARE_ADDRESS_LABEL(start); + for (int j = i; j >= 0; j--) { + CheckStackTrace1(j); + } + DECLARE_ADDRESS_LABEL(end); +} + +} // namespace +//-----------------------------------------------------------------------// + +int main(int argc, char ** argv) { + CheckStackTrace(0); + printf("PASS\n"); + +#if TEST_UCONTEXT_BITS + leaf_capture_fn = CaptureLeafUContext; + CheckStackTrace(0); + printf("PASS\n"); +#endif // TEST_UCONTEXT_BITS + + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/system-alloc_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/system-alloc_unittest.cc new file mode 100644 index 000000000..fd199e2ca --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/system-alloc_unittest.cc @@ -0,0 +1,161 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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 + +#include "config_for_unittests.h" + +#include "system-alloc.h" + +#include +#if defined HAVE_STDINT_H +#include // to get uintptr_t +#elif defined HAVE_INTTYPES_H +#include // another place uintptr_t might be defined +#endif +#include + +#include +#include + +#include "base/logging.h" // for Check_GEImpl, Check_LTImpl, etc +#include "common.h" // for kAddressBits +#include "gperftools/malloc_extension.h" // for MallocExtension::instance +#include "gperftools/tcmalloc.h" +#include "tests/testutil.h" + +class ArraySysAllocator : public SysAllocator { +public: + // Was this allocator invoked at least once? + bool invoked_; + + ArraySysAllocator() : SysAllocator() { + ptr_ = 0; + invoked_ = false; + } + + void* Alloc(size_t size, size_t *actual_size, size_t alignment) { + invoked_ = true; + + if (size > kArraySize) { + return NULL; + } + + void *result = &array_[ptr_]; + uintptr_t ptr = reinterpret_cast(result); + + if (actual_size) { + *actual_size = size; + } + + // Try to get more memory for alignment + size_t extra = alignment - (ptr & (alignment-1)); + size += extra; + CHECK_LT(ptr_ + size, kArraySize); + + if ((ptr & (alignment-1)) != 0) { + ptr += alignment - (ptr & (alignment-1)); + } + + ptr_ += size; + return reinterpret_cast(ptr); + } + + void DumpStats() { + } + +private: + static const int kArraySize = 8 * 1024 * 1024; + char array_[kArraySize]; + // We allocate the next chunk from here + int ptr_; + +}; +const int ArraySysAllocator::kArraySize; +ArraySysAllocator a; + +static void TestBasicInvoked() { + MallocExtension::instance()->SetSystemAllocator(&a); + + // An allocation size that is likely to trigger the system allocator. + // XXX: this is implementation specific. + char *p = noopt(new char[1024 * 1024]); + delete [] p; + + // Make sure that our allocator was invoked. + CHECK(a.invoked_); +} + +#if 0 // could port this to various OSs, but won't bother for now +TEST(AddressBits, CpuVirtualBits) { + // Check that kAddressBits is as least as large as either the number of bits + // in a pointer or as the number of virtual bits handled by the processor. + // To be effective this test must be run on each processor model. + const int kPointerBits = 8 * sizeof(void*); + const int kImplementedVirtualBits = NumImplementedVirtualBits(); + + CHECK_GE(kAddressBits, std::min(kImplementedVirtualBits, kPointerBits)); +} +#endif + +static void TestBasicRetryFailTest() { + // Check with the allocator still works after a failed allocation. + // + // There is no way to call malloc and guarantee it will fail. malloc takes a + // size_t parameter and the C++ standard does not constrain the size of + // size_t. For example, consider an implementation where size_t is 32 bits + // and pointers are 64 bits. + // + // It is likely, though, that sizeof(size_t) == sizeof(void*). In that case, + // the first allocation here might succeed but the second allocation must + // fail. + // + // If the second allocation succeeds, you will have to rewrite or + // disable this test. + // The weird parens are to avoid macro-expansion of 'max' on windows. + const size_t kHugeSize = (std::numeric_limits::max)() / 2; + void* p1 = noopt(malloc(kHugeSize)); + void* p2 = noopt(malloc(kHugeSize)); + CHECK(p2 == NULL); + if (p1 != NULL) free(p1); + + char* q = noopt(new char[1024]); + CHECK(q != NULL); + delete [] q; +} + +int main(int argc, char** argv) { + TestBasicInvoked(); + TestBasicRetryFailTest(); + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_large_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_large_unittest.cc new file mode 100644 index 000000000..02b8569e2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_large_unittest.cc @@ -0,0 +1,139 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Michael Chastain +// +// This is a unit test for large allocations in malloc and friends. +// "Large" means "so large that they overflow the address space". +// For 32 bits, this means allocations near 2^32 bytes and 2^31 bytes. +// For 64 bits, this means allocations near 2^64 bytes and 2^63 bytes. + +#include // for size_t, NULL +#include // for malloc, free, realloc +#include +#include // for set, etc + +#include "base/logging.h" // for operator<<, CHECK, etc +#include "gperftools/tcmalloc.h" +#include "tests/testutil.h" + +using std::set; + +// Alloc a size that should always fail. + +void TryAllocExpectFail(size_t size) { + void* p1 = noopt(malloc(size)); + CHECK(p1 == NULL); + + void* p2 = noopt(malloc(1)); + CHECK(p2 != NULL); + + void* p3 = noopt(realloc(p2, size)); + CHECK(p3 == NULL); + + free(p2); +} + +// Alloc a size that might work and might fail. +// If it does work, touch some pages. + +void TryAllocMightFail(size_t size) { + unsigned char* p = static_cast(noopt(malloc(size))); + if (p != NULL) { + static const size_t kPoints = 1024; + + for ( size_t i = 0; i < kPoints; ++i ) { + p[i * (size / kPoints)] = static_cast(i); + } + + for ( size_t i = 0; i < kPoints; ++i ) { + CHECK(p[i * (size / kPoints)] == static_cast(i)); + } + + p[size-1] = 'M'; + CHECK(p[size-1] == 'M'); + } + + free(noopt(p)); +} + +int main (int argc, char** argv) { + // Allocate some 0-byte objects. They better be unique. + // 0 bytes is not large but it exercises some paths related to + // large-allocation code. + { + static const int kZeroTimes = 1024; + printf("Test malloc(0) x %d\n", kZeroTimes); + set p_set; + for ( int i = 0; i < kZeroTimes; ++i ) { + char* p = new char; + CHECK(p != NULL); + CHECK(p_set.find(p) == p_set.end()); + p_set.insert(p_set.end(), p); + } + // Just leak the memory. + } + + // Grab some memory so that some later allocations are guaranteed to fail. + printf("Test small malloc\n"); + void* p_small = noopt(malloc(4*1048576)); + CHECK(p_small != NULL); + + // Test sizes up near the maximum size_t. + // These allocations test the wrap-around code. + printf("Test malloc(0 - N)\n"); + const size_t zero = 0; + static const size_t kMinusNTimes = 16384; + for ( size_t i = 1; i < kMinusNTimes; ++i ) { + TryAllocExpectFail(zero - i); + } + + // Test sizes a bit smaller. + // The small malloc above guarantees that all these return NULL. + printf("Test malloc(0 - 1048576 - N)\n"); + static const size_t kMinusMBMinusNTimes = 16384; + for ( size_t i = 0; i < kMinusMBMinusNTimes; ++i) { + TryAllocExpectFail(zero - 1048576 - i); + } + + // Test sizes at half of size_t. + // These might or might not fail to allocate. + printf("Test malloc(max/2 +- N)\n"); + static const size_t kHalfPlusMinusTimes = 64; + const size_t half = (zero - 2) / 2 + 1; + for ( size_t i = 0; i < kHalfPlusMinusTimes; ++i) { + TryAllocMightFail(half - i); + TryAllocMightFail(half + i); + } + + printf("PASS\n"); + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.cc new file mode 100644 index 000000000..658772f9f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.cc @@ -0,0 +1,1669 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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. + +// --- +// Unittest for the TCMalloc implementation. +// +// * The test consists of a set of threads. +// * Each thread maintains a set of allocated objects, with +// a bound on the total amount of data in the set. +// * Each allocated object's contents are generated by +// hashing the object pointer, and a generation count +// in the object. This allows us to easily check for +// data corruption. +// * At any given step, the thread can do any of the following: +// a. Allocate an object +// b. Increment an object's generation count and update +// its contents. +// c. Pass the object to another thread +// d. Free an object +// Also, at the end of every step, object(s) are freed to maintain +// the memory upper-bound. +// +// If this test is compiled with -DDEBUGALLOCATION, then we don't +// run some tests that test the inner workings of tcmalloc and +// break on debugallocation: that certain allocations are aligned +// in a certain way (even though no standard requires it), and that +// realloc() tries to minimize copying (which debug allocators don't +// care about). + +#include "config_for_unittests.h" +// 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 // for testing sbrk hooks +#endif +#include "tcmalloc.h" // must come early, to pick up posix_memalign +#include +#include +#include +#ifdef HAVE_STDINT_H +#include // for intptr_t +#endif +#include // for size_t +#ifdef HAVE_FCNTL_H +#include // for open; used with mmap-hook test +#endif +#ifdef HAVE_MMAP +#include // for testing mmap hooks +#endif +#ifdef HAVE_MALLOC_H +#include // defines pvalloc/etc on cygwin +#endif +#include +#include +#include +#include +#include +#include "base/logging.h" +#include "base/simple_mutex.h" +#include "gperftools/malloc_hook.h" +#include "gperftools/malloc_extension.h" +#include "gperftools/nallocx.h" +#include "gperftools/tcmalloc.h" +#include "thread_cache.h" +#include "system-alloc.h" +#include "tests/testutil.h" + +// Windows doesn't define pvalloc and a few other obsolete unix +// functions; nor does it define posix_memalign (which is not obsolete). +#if defined(_WIN32) +# define cfree free // don't bother to try to test these obsolete fns +# define valloc malloc +# define pvalloc malloc +// I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc +// must be paired with _aligned_free (not normal free), which is too +// invasive a change to how we allocate memory here. So just bail +static bool kOSSupportsMemalign = false; +static inline void* Memalign(size_t align, size_t size) { + //LOG(FATAL) << "memalign not supported on windows"; + exit(1); + return NULL; +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + //LOG(FATAL) << "posix_memalign not supported on windows"; + exit(1); + return -1; +} + +// OS X defines posix_memalign in some OS versions but not others; +// it's confusing enough to check that it's easiest to just not to test. +#elif defined(__APPLE__) +static bool kOSSupportsMemalign = false; +static inline void* Memalign(size_t align, size_t size) { + //LOG(FATAL) << "memalign not supported on OS X"; + exit(1); + return NULL; +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + //LOG(FATAL) << "posix_memalign not supported on OS X"; + exit(1); + return -1; +} + +#else +static bool kOSSupportsMemalign = true; +static inline void* Memalign(size_t align, size_t size) { + return noopt(memalign(align, noopt(size))); +} +static inline int PosixMemalign(void** ptr, size_t align, size_t size) { + return noopt(posix_memalign(ptr, align, noopt(size))); +} + +#endif + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + +#define OVERALIGNMENT 64 + +struct overaligned_type +{ +#if defined(__GNUC__) + __attribute__((__aligned__(OVERALIGNMENT))) +#elif defined(_MSC_VER) + __declspec(align(OVERALIGNMENT)) +#else + alignas(OVERALIGNMENT) +#endif + unsigned char data[OVERALIGNMENT * 2]; // make the object size different from + // alignment to make sure the correct + // values are passed to the new/delete + // implementation functions +}; + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + +// 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; +using std::string; + +DECLARE_double(tcmalloc_release_rate); +DECLARE_int32(max_free_queue_size); // in debugallocation.cc +DECLARE_int64(tcmalloc_sample_parameter); + +struct OOMAbleSysAlloc : public SysAllocator { + SysAllocator *child; + int simulate_oom; + + void* Alloc(size_t size, size_t* actual_size, size_t alignment) { + if (simulate_oom) { + return NULL; + } + return child->Alloc(size, actual_size, alignment); + } +}; + +static union { + char buf[sizeof(OOMAbleSysAlloc)]; + void *ptr; +} test_sys_alloc_space; + +static OOMAbleSysAlloc* get_test_sys_alloc() { + return reinterpret_cast(&test_sys_alloc_space); +} + +void setup_oomable_sys_alloc() { + SysAllocator *def = MallocExtension::instance()->GetSystemAllocator(); + + OOMAbleSysAlloc *alloc = get_test_sys_alloc(); + new (alloc) OOMAbleSysAlloc; + alloc->child = def; + + MallocExtension::instance()->SetSystemAllocator(alloc); +} + +namespace testing { + +static const int FLAGS_numtests = 50000; +static const int FLAGS_log_every_n_tests = 50000; // log exactly once + +// Testing parameters +static const int FLAGS_lgmaxsize = 16; // lg() of the max size object to alloc +static const int FLAGS_numthreads = 10; // Number of threads +static const int FLAGS_threadmb = 4; // Max memory size allocated by thread +static const int FLAGS_lg_max_memalign = 18; // lg of max alignment for memalign + +static const double FLAGS_memalign_min_fraction = 0; // min expected% +static const double FLAGS_memalign_max_fraction = 0.4; // max expected% +static const double FLAGS_memalign_max_alignment_ratio = 6; // alignment/size + +// Weights of different operations +static const int FLAGS_allocweight = 50; // Weight for picking allocation +static const int FLAGS_freeweight = 50; // Weight for picking free +static const int FLAGS_updateweight = 10; // Weight for picking update +static const int FLAGS_passweight = 1; // Weight for passing object + +static const int kSizeBits = 8 * sizeof(size_t); +static const size_t kMaxSize = ~static_cast(0); +static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1); + +static const size_t kNotTooBig = 100000; +// We want an allocation that is definitely more than main memory. OS +// X has special logic to discard very big allocs before even passing +// the request along to the user-defined memory allocator; we're not +// interested in testing their logic, so we have to make sure we're +// not *too* big. +static const size_t kTooBig = kMaxSize - 100000; + +static int news_handled = 0; + +// Global array of threads +class TesterThread; +static TesterThread** threads; + +// To help with generating random numbers +class TestHarness { + private: + // Information kept per type + struct Type { + string name; + int type; + int weight; + }; + + public: + TestHarness(int seed) + : types_(new vector), total_weight_(0), num_tests_(0) { + srandom(seed); + } + ~TestHarness() { + delete types_; + } + + // Add operation type with specified weight. When starting a new + // iteration, an operation type is picked with probability + // proportional to its weight. + // + // "type" must be non-negative. + // "weight" must be non-negative. + void AddType(int type, int weight, const char* name); + + // Call this to get the type of operation for the next iteration. + // It returns a random operation type from the set of registered + // operations. Returns -1 if tests should finish. + int PickType(); + + // If n == 0, returns the next pseudo-random number in the range [0 .. 0] + // If n != 0, returns the next pseudo-random number in the range [0 .. n) + int Uniform(int n) { + if (n == 0) { + return random() * 0; + } else { + return random() % n; + } + } + // Pick "base" uniformly from range [0,max_log] and then return + // "base" random bits. The effect is to pick a number in the range + // [0,2^max_log-1] with bias towards smaller numbers. + int Skewed(int max_log) { + const int base = random() % (max_log+1); + return random() % (1 << base); + } + + private: + vector* types_; // Registered types + int total_weight_; // Total weight of all types + int num_tests_; // Num tests run so far +}; + +void TestHarness::AddType(int type, int weight, const char* name) { + Type t; + t.name = name; + t.type = type; + t.weight = weight; + types_->push_back(t); + total_weight_ += weight; +} + +int TestHarness::PickType() { + if (num_tests_ >= FLAGS_numtests) return -1; + num_tests_++; + + assert(total_weight_ > 0); + // This is a little skewed if total_weight_ doesn't divide 2^31, but it's close + int v = Uniform(total_weight_); + int i; + for (i = 0; i < types_->size(); i++) { + v -= (*types_)[i].weight; + if (v < 0) { + break; + } + } + + assert(i < types_->size()); + if ((num_tests_ % FLAGS_log_every_n_tests) == 0) { + fprintf(LOGSTREAM, " Test %d out of %d: %s\n", + num_tests_, FLAGS_numtests, (*types_)[i].name.c_str()); + } + return (*types_)[i].type; +} + +class AllocatorState : public TestHarness { + public: + explicit AllocatorState(int seed) : TestHarness(seed), memalign_fraction_(0) { + if (kOSSupportsMemalign) { + CHECK_GE(FLAGS_memalign_max_fraction, 0); + CHECK_LE(FLAGS_memalign_max_fraction, 1); + CHECK_GE(FLAGS_memalign_min_fraction, 0); + CHECK_LE(FLAGS_memalign_min_fraction, 1); + double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; + CHECK_GE(delta, 0); + memalign_fraction_ = (Uniform(10000)/10000.0 * delta + + FLAGS_memalign_min_fraction); + //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); + } + } + virtual ~AllocatorState() {} + + // Allocate memory. Randomly choose between malloc() or posix_memalign(). + void* alloc(size_t size) { + if (Uniform(100) < memalign_fraction_ * 100) { + // Try a few times to find a reasonable alignment, or fall back on malloc. + for (int i = 0; i < 5; i++) { + size_t alignment = 1 << Uniform(FLAGS_lg_max_memalign); + if (alignment >= sizeof(intptr_t) && + (size < sizeof(intptr_t) || + alignment < FLAGS_memalign_max_alignment_ratio * size)) { + void *result = reinterpret_cast(static_cast(0x1234)); + int err = PosixMemalign(&result, alignment, size); + if (err != 0) { + CHECK_EQ(err, ENOMEM); + } + return err == 0 ? result : NULL; + } + } + } + return noopt(malloc(size)); + } + + private: + double memalign_fraction_; +}; + + +// Info kept per thread +class TesterThread { + private: + // Info kept per allocated object + struct Object { + char* ptr; // Allocated pointer + int size; // Allocated size + int generation; // Generation counter of object contents + }; + + Mutex lock_; // For passing in another thread's obj + int id_; // My thread id + AllocatorState rnd_; // For generating random numbers + vector heap_; // This thread's heap + vector passed_; // Pending objects passed from others + size_t heap_size_; // Current heap size + int locks_ok_; // Number of OK TryLock() ops + int locks_failed_; // Number of failed TryLock() ops + + // Type of operations + enum Type { ALLOC, FREE, UPDATE, PASS }; + + // ACM minimal standard random number generator. (re-entrant.) + class ACMRandom { + int32 seed_; + public: + explicit ACMRandom(int32 seed) { seed_ = seed; } + int32 Next() { + const int32 M = 2147483647L; // 2^31-1 + const int32 A = 16807; + // In effect, we are computing seed_ = (seed_ * A) % M, where M = 2^31-1 + uint32 lo = A * (int32)(seed_ & 0xFFFF); + uint32 hi = A * (int32)((uint32)seed_ >> 16); + lo += (hi & 0x7FFF) << 16; + if (lo > M) { + lo &= M; + ++lo; + } + lo += hi >> 15; + if (lo > M) { + lo &= M; + ++lo; + } + return (seed_ = (int32) lo); + } + }; + + public: + TesterThread(int id) + : id_(id), + rnd_(id+1), + heap_size_(0), + locks_ok_(0), + locks_failed_(0) { + } + + virtual ~TesterThread() { + if (FLAGS_verbose) + fprintf(LOGSTREAM, "Thread %2d: locks %6d ok; %6d trylocks failed\n", + id_, locks_ok_, locks_failed_); + if (locks_ok_ + locks_failed_ >= 1000) { + CHECK_LE(locks_failed_, locks_ok_ / 2); + } + } + + virtual void Run() { + rnd_.AddType(ALLOC, FLAGS_allocweight, "allocate"); + rnd_.AddType(FREE, FLAGS_freeweight, "free"); + rnd_.AddType(UPDATE, FLAGS_updateweight, "update"); + rnd_.AddType(PASS, FLAGS_passweight, "pass"); + + while (true) { + AcquirePassedObjects(); + + switch (rnd_.PickType()) { + case ALLOC: AllocateObject(); break; + case FREE: FreeObject(); break; + case UPDATE: UpdateObject(); break; + case PASS: PassObject(); break; + case -1: goto done; + default: assert(NULL == "Unknown type"); + } + + ShrinkHeap(); + } + + done: + DeleteHeap(); + } + + // Allocate a new object + void AllocateObject() { + Object object; + object.size = rnd_.Skewed(FLAGS_lgmaxsize); + object.ptr = static_cast(rnd_.alloc(object.size)); + CHECK(object.ptr); + object.generation = 0; + FillContents(&object); + heap_.push_back(object); + heap_size_ += object.size; + } + + // Mutate a random object + void UpdateObject() { + if (heap_.empty()) return; + const int index = rnd_.Uniform(heap_.size()); + CheckContents(heap_[index]); + heap_[index].generation++; + FillContents(&heap_[index]); + } + + // Free a random object + void FreeObject() { + if (heap_.empty()) return; + const int index = rnd_.Uniform(heap_.size()); + Object object = heap_[index]; + CheckContents(object); + free(object.ptr); + heap_size_ -= object.size; + heap_[index] = heap_[heap_.size()-1]; + heap_.pop_back(); + } + + // Delete all objects in the heap + void DeleteHeap() { + while (!heap_.empty()) { + FreeObject(); + } + } + + // Free objects until our heap is small enough + void ShrinkHeap() { + while (heap_size_ > FLAGS_threadmb << 20) { + assert(!heap_.empty()); + FreeObject(); + } + } + + // Pass a random object to another thread + void PassObject() { + // Pick object to pass + if (heap_.empty()) return; + const int index = rnd_.Uniform(heap_.size()); + Object object = heap_[index]; + CheckContents(object); + + // Pick thread to pass + const int tid = rnd_.Uniform(FLAGS_numthreads); + TesterThread* thread = threads[tid]; + + if (thread->lock_.TryLock()) { + // Pass the object + locks_ok_++; + thread->passed_.push_back(object); + thread->lock_.Unlock(); + heap_size_ -= object.size; + heap_[index] = heap_[heap_.size()-1]; + heap_.pop_back(); + } else { + locks_failed_++; + } + } + + // Grab any objects passed to this thread by another thread + void AcquirePassedObjects() { + // We do not create unnecessary contention by always using + // TryLock(). Plus we unlock immediately after swapping passed + // objects into a local vector. + vector copy; + { // Locking scope + if (!lock_.TryLock()) { + locks_failed_++; + return; + } + locks_ok_++; + swap(copy, passed_); + lock_.Unlock(); + } + + for (int i = 0; i < copy.size(); ++i) { + const Object& object = copy[i]; + CheckContents(object); + heap_.push_back(object); + heap_size_ += object.size; + } + } + + // Fill object contents according to ptr/generation + void FillContents(Object* object) { + ACMRandom r(reinterpret_cast(object->ptr) & 0x7fffffff); + for (int i = 0; i < object->generation; ++i) { + r.Next(); + } + const char c = static_cast(r.Next()); + memset(object->ptr, c, object->size); + } + + // Check object contents + void CheckContents(const Object& object) { + ACMRandom r(reinterpret_cast(object.ptr) & 0x7fffffff); + for (int i = 0; i < object.generation; ++i) { + r.Next(); + } + + // For large objects, we just check a prefix/suffix + const char expected = static_cast(r.Next()); + const int limit1 = object.size < 32 ? object.size : 32; + const int start2 = limit1 > object.size - 32 ? limit1 : object.size - 32; + for (int i = 0; i < limit1; ++i) { + CHECK_EQ(object.ptr[i], expected); + } + for (int i = start2; i < object.size; ++i) { + CHECK_EQ(object.ptr[i], expected); + } + } +}; + +static void RunThread(int thread_id) { + threads[thread_id]->Run(); +} + +static void TryHugeAllocation(size_t s, AllocatorState* rnd) { + void* p = rnd->alloc(noopt(s)); + CHECK(p == NULL); // huge allocation s should fail! +} + +static void TestHugeAllocations(AllocatorState* rnd) { + // Check that asking for stuff tiny bit smaller than largest possible + // size returns NULL. + for (size_t i = 0; i < 70000; i += rnd->Uniform(20)) { + TryHugeAllocation(kMaxSize - i, rnd); + } + // Asking for memory sizes near signed/unsigned boundary (kMaxSignedSize) + // might work or not, depending on the amount of virtual memory. +#ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs + for (size_t i = 0; i < 100; i++) { + void* p = NULL; + p = rnd->alloc(kMaxSignedSize + i); + if (p) free(p); // if: free(NULL) is not necessarily defined + p = rnd->alloc(kMaxSignedSize - i); + if (p) free(p); + } +#endif + + // Check that ReleaseFreeMemory has no visible effect (aka, does not + // crash the test): + MallocExtension* inst = MallocExtension::instance(); + CHECK(inst); + inst->ReleaseFreeMemory(); +} + +static void TestCalloc(size_t n, size_t s, bool ok) { + char* p = reinterpret_cast(calloc(n, s)); + if (FLAGS_verbose) + fprintf(LOGSTREAM, "calloc(%zx, %zx): %p\n", n, s, p); + if (!ok) { + CHECK(p == NULL); // calloc(n, s) should not succeed + } else { + CHECK(p != NULL); // calloc(n, s) should succeed + for (int i = 0; i < n*s; i++) { + CHECK(p[i] == '\0'); + } + free(p); + } +} + +// This makes sure that reallocing a small number of bytes in either +// direction doesn't cause us to allocate new memory. +static void TestRealloc() { +#ifndef DEBUGALLOCATION // debug alloc doesn't try to minimize reallocs + // When sampling, we always allocate in units of page-size, which + // makes reallocs of small sizes do extra work (thus, failing these + // checks). Since sampling is random, we turn off sampling to make + // sure that doesn't happen to us here. + const int64 old_sample_parameter = FLAGS_tcmalloc_sample_parameter; + FLAGS_tcmalloc_sample_parameter = 0; // turn off sampling + + int start_sizes[] = { 100, 1000, 10000, 100000 }; + int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 }; + + for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) { + void* p = noopt(malloc(start_sizes[s])); + CHECK(p); + // The larger the start-size, the larger the non-reallocing delta. + for (int d = 0; d < (s+1) * 2; ++d) { + void* new_p = noopt(realloc(p, start_sizes[s] + deltas[d])); + CHECK(p == new_p); // realloc should not allocate new memory + } + // Test again, but this time reallocing smaller first. + for (int d = 0; d < s*2; ++d) { + void* new_p = noopt(realloc(p, start_sizes[s] - deltas[d])); + CHECK(p == new_p); // realloc should not allocate new memory + } + free(p); + } + FLAGS_tcmalloc_sample_parameter = old_sample_parameter; +#endif +} + +static void TestNewHandler() { + ++news_handled; + throw std::bad_alloc(); +} + +static void TestOneNew(void* (*func)(size_t)) { + func = noopt(func); + // success test + try { + void* ptr = (*func)(kNotTooBig); + if (0 == ptr) { + fprintf(LOGSTREAM, "allocation should not have failed.\n"); + abort(); + } + } catch (...) { + fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); + abort(); + } + + // failure test + // we should always receive a bad_alloc exception + try { + (*func)(kTooBig); + fprintf(LOGSTREAM, "allocation should have failed.\n"); + abort(); + } catch (const std::bad_alloc&) { + // correct + } catch (...) { + fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); + abort(); + } +} + +static void TestNew(void* (*func)(size_t)) { + news_handled = 0; + + // test without new_handler: + std::new_handler saved_handler = std::set_new_handler(0); + TestOneNew(func); + + // test with new_handler: + std::set_new_handler(TestNewHandler); + TestOneNew(func); + if (news_handled != 1) { + fprintf(LOGSTREAM, "new_handler was not called.\n"); + abort(); + } + std::set_new_handler(saved_handler); +} + +static void TestOneNothrowNew(void* (*func)(size_t, const std::nothrow_t&)) { + func = noopt(func); + // success test + try { + void* ptr = (*func)(kNotTooBig, std::nothrow); + if (0 == ptr) { + fprintf(LOGSTREAM, "allocation should not have failed.\n"); + abort(); + } + } catch (...) { + fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); + abort(); + } + + // failure test + // we should always receive a bad_alloc exception + try { + if ((*func)(kTooBig, std::nothrow) != 0) { + fprintf(LOGSTREAM, "allocation should have failed.\n"); + abort(); + } + } catch (...) { + fprintf(LOGSTREAM, "nothrow allocation threw unexpected exception.\n"); + abort(); + } +} + +static void TestNothrowNew(void* (*func)(size_t, const std::nothrow_t&)) { + news_handled = 0; + + // test without new_handler: + std::new_handler saved_handler = std::set_new_handler(0); + TestOneNothrowNew(func); + + // test with new_handler: + std::set_new_handler(TestNewHandler); + TestOneNothrowNew(func); + if (news_handled != 1) { + fprintf(LOGSTREAM, "nothrow new_handler was not called.\n"); + abort(); + } + std::set_new_handler(saved_handler); +} + + +// 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 volatile int g_##hook_type##_calls = 0; \ + static void IncrementCallsTo##hook_type(__VA_ARGS__) { \ + 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 void Set##hook_type() { \ + CHECK(MallocHook::Add##hook_type( \ + (MallocHook::hook_type)&IncrementCallsTo##hook_type)); \ + } \ + static void Reset##hook_type() { \ + CHECK(MallocHook::Remove##hook_type( \ + (MallocHook::hook_type)&IncrementCallsTo##hook_type)); \ + } + +// We do one for each hook typedef in malloc_hook.h +MAKE_HOOK_CALLBACK(NewHook, const void*, size_t); +MAKE_HOOK_CALLBACK(DeleteHook, const void*); +MAKE_HOOK_CALLBACK(MmapHook, const void*, const void*, size_t, int, int, int, + off_t); +MAKE_HOOK_CALLBACK(MremapHook, const void*, const void*, size_t, size_t, int, + const void*); +MAKE_HOOK_CALLBACK(MunmapHook, const void *, size_t); +MAKE_HOOK_CALLBACK(SbrkHook, const void *, ptrdiff_t); + +static void TestAlignmentForSize(int size) { + fprintf(LOGSTREAM, "Testing alignment of malloc(%d)\n", size); + static const int kNum = 100; + void* ptrs[kNum]; + for (int i = 0; i < kNum; i++) { + ptrs[i] = malloc(size); + uintptr_t p = reinterpret_cast(ptrs[i]); + CHECK((p % sizeof(void*)) == 0); + CHECK((p % sizeof(double)) == 0); + + // Must have 16-byte (or 8-byte in case of -DTCMALLOC_ALIGN_8BYTES) + // alignment for large enough objects + if (size >= kMinAlign) { + CHECK((p % kMinAlign) == 0); + } + } + for (int i = 0; i < kNum; i++) { + free(ptrs[i]); + } +} + +static void TestMallocAlignment() { + for (int lg = 0; lg < 16; lg++) { + TestAlignmentForSize((1<(arg); + if (state->ptr >= r->address && + state->ptr < r->address + r->length) { + if (state->expected_type == base::MallocRange::FREE) { + // We are expecting r->type == FREE, but ReleaseMemory + // may have already moved us to UNMAPPED state instead (this happens in + // approximately 0.1% of executions). Accept either state. + CHECK(r->type == base::MallocRange::FREE || + r->type == base::MallocRange::UNMAPPED); + } else { + CHECK_EQ(r->type, state->expected_type); + } + CHECK_GE(r->length, state->min_size); + state->matched = true; + } +} + +// Check that at least one of the callbacks from Ranges() contains +// the specified address with the specified type, and has size +// >= min_size. +static void CheckRangeCallback(void* ptr, base::MallocRange::Type type, + size_t min_size) { + RangeCallbackState state; + state.ptr = reinterpret_cast(ptr); + state.expected_type = type; + state.min_size = min_size; + state.matched = false; + MallocExtension::instance()->Ranges(&state, RangeCallback); + CHECK(state.matched); +} + +} + +static bool HaveSystemRelease = + TCMalloc_SystemRelease(TCMalloc_SystemAlloc(kPageSize, NULL, 0), kPageSize); + +static void TestRanges() { + static const int MB = 1048576; + void* a = malloc(MB); + void* b = malloc(MB); + base::MallocRange::Type releasedType = + HaveSystemRelease ? base::MallocRange::UNMAPPED : base::MallocRange::FREE; + + CheckRangeCallback(a, base::MallocRange::INUSE, MB); + CheckRangeCallback(b, base::MallocRange::INUSE, MB); + free(a); + CheckRangeCallback(a, base::MallocRange::FREE, MB); + CheckRangeCallback(b, base::MallocRange::INUSE, MB); + MallocExtension::instance()->ReleaseFreeMemory(); + CheckRangeCallback(a, releasedType, MB); + CheckRangeCallback(b, base::MallocRange::INUSE, MB); + free(b); + CheckRangeCallback(a, releasedType, MB); + CheckRangeCallback(b, base::MallocRange::FREE, MB); +} + +#ifndef DEBUGALLOCATION +static size_t GetUnmappedBytes() { + size_t bytes; + CHECK(MallocExtension::instance()->GetNumericProperty( + "tcmalloc.pageheap_unmapped_bytes", &bytes)); + return bytes; +} +#endif + +class AggressiveDecommitChanger { + size_t old_value_; +public: + AggressiveDecommitChanger(size_t new_value) { + MallocExtension *inst = MallocExtension::instance(); + bool rv = inst->GetNumericProperty("tcmalloc.aggressive_memory_decommit", &old_value_); + CHECK_CONDITION(rv); + rv = inst->SetNumericProperty("tcmalloc.aggressive_memory_decommit", new_value); + CHECK_CONDITION(rv); + } + ~AggressiveDecommitChanger() { + MallocExtension *inst = MallocExtension::instance(); + bool rv = inst->SetNumericProperty("tcmalloc.aggressive_memory_decommit", old_value_); + CHECK_CONDITION(rv); + } +}; + +static void TestReleaseToSystem() { + // Debug allocation mode adds overhead to each allocation which + // messes up all the equality tests here. I just disable the + // teset in this mode. TODO(csilvers): get it to work for debugalloc? +#ifndef DEBUGALLOCATION + + if(!HaveSystemRelease) return; + + const double old_tcmalloc_release_rate = FLAGS_tcmalloc_release_rate; + FLAGS_tcmalloc_release_rate = 0; + + AggressiveDecommitChanger disabler(0); + + static const int MB = 1048576; + void* a = noopt(malloc(MB)); + void* b = noopt(malloc(MB)); + MallocExtension::instance()->ReleaseFreeMemory(); + size_t starting_bytes = GetUnmappedBytes(); + + // Calling ReleaseFreeMemory() a second time shouldn't do anything. + MallocExtension::instance()->ReleaseFreeMemory(); + EXPECT_EQ(starting_bytes, GetUnmappedBytes()); + + // ReleaseToSystem shouldn't do anything either. + MallocExtension::instance()->ReleaseToSystem(MB); + EXPECT_EQ(starting_bytes, GetUnmappedBytes()); + + free(a); + + // The span to release should be 1MB. + MallocExtension::instance()->ReleaseToSystem(MB/2); + EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); + + // Should do nothing since the previous call released too much. + MallocExtension::instance()->ReleaseToSystem(MB/4); + EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); + + free(b); + + // Use up the extra MB/4 bytes from 'a' and also release 'b'. + MallocExtension::instance()->ReleaseToSystem(MB/2); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + // Should do nothing since the previous call released too much. + MallocExtension::instance()->ReleaseToSystem(MB/2); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + // Nothing else to release. + MallocExtension::instance()->ReleaseFreeMemory(); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + a = noopt(malloc(MB)); + free(a); + EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); + + // Releasing less than a page should still trigger a release. + MallocExtension::instance()->ReleaseToSystem(1); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + FLAGS_tcmalloc_release_rate = old_tcmalloc_release_rate; +#endif // #ifndef DEBUGALLOCATION +} + +static void TestAggressiveDecommit() { + // Debug allocation mode adds overhead to each allocation which + // messes up all the equality tests here. I just disable the + // teset in this mode. +#ifndef DEBUGALLOCATION + + if(!HaveSystemRelease) return; + + fprintf(LOGSTREAM, "Testing aggressive de-commit\n"); + + AggressiveDecommitChanger enabler(1); + + static const int MB = 1048576; + void* a = noopt(malloc(MB)); + void* b = noopt(malloc(MB)); + + size_t starting_bytes = GetUnmappedBytes(); + + // ReleaseToSystem shouldn't do anything either. + MallocExtension::instance()->ReleaseToSystem(MB); + EXPECT_EQ(starting_bytes, GetUnmappedBytes()); + + free(a); + + // The span to release should be 1MB. + EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); + + free(b); + + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + // Nothing else to release. + MallocExtension::instance()->ReleaseFreeMemory(); + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + a = noopt(malloc(MB)); + free(a); + + EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); + + fprintf(LOGSTREAM, "Done testing aggressive de-commit\n"); + +#endif // #ifndef DEBUGALLOCATION +} + +// On MSVC10, in release mode, the optimizer convinces itself +// g_no_memory is never changed (I guess it doesn't realize OnNoMemory +// might be called). Work around this by setting the var volatile. +volatile bool g_no_memory = false; +std::new_handler g_old_handler = NULL; +static void OnNoMemory() { + g_no_memory = true; + std::set_new_handler(g_old_handler); +} + +static void TestSetNewMode() { + int old_mode = tc_set_new_mode(1); + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + void* ret = noopt(malloc(noopt(kTooBig))); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + ret = noopt(calloc(1, noopt(kTooBig))); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + ret = noopt(realloc(nullptr, noopt(kTooBig))); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + + if (kOSSupportsMemalign) { + // Not really important, but must be small enough such that + // kAlignment + kTooBig does not overflow. + const int kAlignment = 1 << 5; + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + ret = Memalign(kAlignment, kTooBig); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + + g_old_handler = std::set_new_handler(&OnNoMemory); + g_no_memory = false; + EXPECT_EQ(ENOMEM, + PosixMemalign(&ret, kAlignment, kTooBig)); + EXPECT_EQ(NULL, ret); + EXPECT_TRUE(g_no_memory); + } + + tc_set_new_mode(old_mode); +} + +static void TestErrno(void) { + void* ret; + if (kOSSupportsMemalign) { + errno = 0; + ret = Memalign(128, kTooBig); + EXPECT_EQ(NULL, ret); + EXPECT_EQ(ENOMEM, errno); + } + + errno = 0; + ret = noopt(malloc(noopt(kTooBig))); + EXPECT_EQ(NULL, ret); + EXPECT_EQ(ENOMEM, errno); + + errno = 0; + ret = tc_malloc_skip_new_handler(kTooBig); + EXPECT_EQ(NULL, ret); + EXPECT_EQ(ENOMEM, errno); +} + + +#ifndef DEBUGALLOCATION +// Ensure that nallocx works before main. +struct GlobalNallocx { + GlobalNallocx() { CHECK_GT(nallocx(99, 0), 99); } +} global_nallocx; + +#if defined(__GNUC__) + +static void check_global_nallocx() __attribute__((constructor)); +static void check_global_nallocx() { CHECK_GT(nallocx(99, 0), 99); } + +#endif // __GNUC__ + +static void TestNAllocX() { + for (size_t size = 0; size <= (1 << 20); size += 7) { + size_t rounded = nallocx(size, 0); + ASSERT_GE(rounded, size); + void* ptr = malloc(size); + ASSERT_EQ(rounded, MallocExtension::instance()->GetAllocatedSize(ptr)); + free(ptr); + } +} + +static void TestNAllocXAlignment() { + for (size_t size = 0; size <= (1 << 20); size += 7) { + for (size_t align = 0; align < 10; align++) { + size_t rounded = nallocx(size, MALLOCX_LG_ALIGN(align)); + ASSERT_GE(rounded, size); + ASSERT_EQ(rounded % (1 << align), 0); + void* ptr = tc_memalign(1 << align, size); + ASSERT_EQ(rounded, MallocExtension::instance()->GetAllocatedSize(ptr)); + free(ptr); + } + } +} + +static int saw_new_handler_runs; +static void* volatile oom_test_last_ptr; + +static void test_new_handler() { + get_test_sys_alloc()->simulate_oom = false; + void *ptr = oom_test_last_ptr; + oom_test_last_ptr = NULL; + ::operator delete[](ptr); + saw_new_handler_runs++; +} + +static ATTRIBUTE_NOINLINE void TestNewOOMHandling() { + // debug allocator does internal allocations and crashes when such + // internal allocation fails. So don't test it. + setup_oomable_sys_alloc(); + + std::new_handler old = std::set_new_handler(test_new_handler); + get_test_sys_alloc()->simulate_oom = true; + + ASSERT_EQ(saw_new_handler_runs, 0); + + for (int i = 0; i < 10240; i++) { + oom_test_last_ptr = noopt(new char [512]); + ASSERT_NE(oom_test_last_ptr, NULL); + if (saw_new_handler_runs) { + break; + } + } + + ASSERT_GE(saw_new_handler_runs, 1); + + get_test_sys_alloc()->simulate_oom = false; + std::set_new_handler(old); +} +#endif // !DEBUGALLOCATION + +static int RunAllTests(int argc, char** argv) { + // Optional argv[1] is the seed + AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); + + SetTestResourceLimit(); + +#ifndef DEBUGALLOCATION + TestNewOOMHandling(); +#endif + + // TODO(odo): This test has been disabled because it is only by luck that it + // does not result in fragmentation. When tcmalloc makes an allocation which + // spans previously unused leaves of the pagemap it will allocate and fill in + // the leaves to cover the new allocation. The leaves happen to be 256MiB in + // the 64-bit build, and with the sbrk allocator these allocations just + // happen to fit in one leaf by luck. With other allocators (mmap, + // memfs_malloc when used with small pages) the allocations generally span + // two leaves and this results in a very bad fragmentation pattern with this + // code. The same failure can be forced with the sbrk allocator just by + // allocating something on the order of 128MiB prior to starting this test so + // that the test allocations straddle a 256MiB boundary. + + // TODO(csilvers): port MemoryUsage() over so the test can use that +#if 0 +# include // for getpid() + // Allocate and deallocate blocks of increasing sizes to check if the alloc + // metadata fragments the memory. (Do not put other allocations/deallocations + // before this test, it may break). + { + size_t memory_usage = MemoryUsage(getpid()); + fprintf(LOGSTREAM, "Testing fragmentation\n"); + for ( int i = 200; i < 240; ++i ) { + int size = i << 20; + void *test1 = rnd.alloc(size); + CHECK(test1); + for ( int j = 0; j < size; j += (1 << 12) ) { + static_cast(test1)[j] = 1; + } + free(test1); + } + // There may still be a bit of fragmentation at the beginning, until we + // reach kPageMapBigAllocationThreshold bytes so we check for + // 200 + 240 + margin. + CHECK_LT(MemoryUsage(getpid()), memory_usage + (450 << 20) ); + } +#endif + + // Check that empty allocation works + fprintf(LOGSTREAM, "Testing empty allocation\n"); + { + void* p1 = rnd.alloc(0); + CHECK(p1 != NULL); + void* p2 = rnd.alloc(0); + CHECK(p2 != NULL); + CHECK(p1 != p2); + free(p1); + free(p2); + } + + // This code stresses some of the memory allocation via STL. + // It may call operator delete(void*, nothrow_t). + fprintf(LOGSTREAM, "Testing STL use\n"); + { + std::vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(0); + std::stable_sort(v.begin(), v.end()); + } + +#ifdef ENABLE_SIZED_DELETE + { + fprintf(LOGSTREAM, "Testing large sized delete is not crashing\n"); + // Large sized delete + // case. https://github.com/gperftools/gperftools/issues/1254 + std::vector addresses; + constexpr int kSizedDepth = 1024; + addresses.reserve(kSizedDepth); + for (int i = 0; i < kSizedDepth; i++) { + addresses.push_back(noopt(new char[12686])); + } + for (int i = 0; i < kSizedDepth; i++) { + ::operator delete[](addresses[i], 12686); + } + } +#endif + + // Test each of the memory-allocation functions once, just as a sanity-check + fprintf(LOGSTREAM, "Sanity-testing all the memory allocation functions\n"); + { + // We use new-hook and delete-hook to verify we actually called the + // tcmalloc version of these routines, and not the libc version. + SetNewHook(); // defined as part of MAKE_HOOK_CALLBACK, above + SetDeleteHook(); // ditto + + void* p1 = malloc(10); + CHECK(p1 != NULL); // force use of this variable + VerifyNewHookWasCalled(); + // Also test the non-standard tc_malloc_size + size_t actual_p1_size = tc_malloc_size(p1); + CHECK_GE(actual_p1_size, 10); + CHECK_LT(actual_p1_size, 100000); // a reasonable upper-bound, I think + free(p1); + VerifyDeleteHookWasCalled(); + + p1 = tc_malloc_skip_new_handler(10); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + + p1 = calloc(10, 2); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + // We make sure we realloc to a big size, since some systems (OS + // X) will notice if the realloced size continues to fit into the + // malloc-block and make this a noop if so. + p1 = realloc(p1, 30000); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + VerifyDeleteHookWasCalled(); + cfree(p1); // synonym for free + VerifyDeleteHookWasCalled(); + + if (kOSSupportsMemalign) { + CHECK_EQ(PosixMemalign(&p1, sizeof(p1), 40), 0); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + + p1 = Memalign(sizeof(p1) * 2, 50); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + } + + // Windows has _aligned_malloc. Let's test that that's captured too. +#if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED_MALLOC) + p1 = _aligned_malloc(sizeof(p1) * 2, 64); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + _aligned_free(p1); + VerifyDeleteHookWasCalled(); +#endif + + p1 = noopt(valloc(60)); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + + p1 = noopt(pvalloc(70)); + CHECK(p1 != NULL); + VerifyNewHookWasCalled(); + free(p1); + VerifyDeleteHookWasCalled(); + + char* p2 = noopt(new char); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + delete p2; + VerifyDeleteHookWasCalled(); + + p2 = noopt(new char[100]); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + delete[] p2; + VerifyDeleteHookWasCalled(); + + p2 = noopt(new (std::nothrow) char); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + delete p2; + VerifyDeleteHookWasCalled(); + + p2 = noopt(new (std::nothrow) char[100]); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + delete[] p2; + VerifyDeleteHookWasCalled(); + + // Another way of calling operator new + p2 = noopt(static_cast(::operator new(100))); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + ::operator delete(p2); + VerifyDeleteHookWasCalled(); + + // Try to call nothrow's delete too. Compilers use this. + p2 = noopt(static_cast(::operator new(100, std::nothrow))); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + ::operator delete(p2, std::nothrow); + VerifyDeleteHookWasCalled(); + +#ifdef ENABLE_SIZED_DELETE + p2 = noopt(new char); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + ::operator delete(p2, sizeof(char)); + VerifyDeleteHookWasCalled(); + + p2 = noopt(new char[100]); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + ::operator delete[](p2, sizeof(char) * 100); + VerifyDeleteHookWasCalled(); +#endif + +#if defined(ENABLE_ALIGNED_NEW_DELETE) + + overaligned_type* poveraligned = noopt(new overaligned_type); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + delete poveraligned; + VerifyDeleteHookWasCalled(); + + poveraligned = noopt(new overaligned_type[10]); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + delete[] poveraligned; + VerifyDeleteHookWasCalled(); + + poveraligned = noopt(new(std::nothrow) overaligned_type); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + delete poveraligned; + VerifyDeleteHookWasCalled(); + + poveraligned = noopt(new(std::nothrow) overaligned_type[10]); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + delete[] poveraligned; + VerifyDeleteHookWasCalled(); + + // Another way of calling operator new + p2 = noopt(static_cast(::operator new(100, std::align_val_t(OVERALIGNMENT)))); + CHECK(p2 != NULL); + CHECK((((size_t)p2) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + ::operator delete(p2, std::align_val_t(OVERALIGNMENT)); + VerifyDeleteHookWasCalled(); + + p2 = noopt(static_cast(::operator new(100, std::align_val_t(OVERALIGNMENT), std::nothrow))); + CHECK(p2 != NULL); + CHECK((((size_t)p2) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + ::operator delete(p2, std::align_val_t(OVERALIGNMENT), std::nothrow); + VerifyDeleteHookWasCalled(); + +#ifdef ENABLE_SIZED_DELETE + poveraligned = noopt(new overaligned_type); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + ::operator delete(poveraligned, sizeof(overaligned_type), std::align_val_t(OVERALIGNMENT)); + VerifyDeleteHookWasCalled(); + + poveraligned = noopt(new overaligned_type[10]); + CHECK(poveraligned != NULL); + CHECK((((size_t)poveraligned) % OVERALIGNMENT) == 0u); + VerifyNewHookWasCalled(); + ::operator delete[](poveraligned, sizeof(overaligned_type) * 10, std::align_val_t(OVERALIGNMENT)); + VerifyDeleteHookWasCalled(); +#endif + +#endif // defined(ENABLE_ALIGNED_NEW_DELETE) + + // Try strdup(), which the system allocates but we must free. If + // all goes well, libc will use our malloc! + p2 = noopt(strdup("in memory of James Golick")); + CHECK(p2 != NULL); + VerifyNewHookWasCalled(); + free(p2); + VerifyDeleteHookWasCalled(); + + + // 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); + CHECK(p1 != NULL); + VerifyMmapHookWasCalled(); + p1 = mremap(p1, size, size/2, 0); + CHECK(p1 != NULL); + 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); + CHECK(p1 != NULL); + VerifyMmapHookWasCalled(); + munmap(p1, 8192); + VerifyMunmapHookWasCalled(); + close(fd); +#else // this is just to quiet the compiler: make sure all fns are called + IncrementCallsToMmapHook(NULL, NULL, 0, 0, 0, 0, 0); + IncrementCallsToMunmapHook(NULL, 0); + IncrementCallsToMremapHook(NULL, NULL, 0, 0, 0, NULL); + VerifyMmapHookWasCalled(); + VerifyMremapHookWasCalled(); + VerifyMunmapHookWasCalled(); +#endif + + // Test sbrk + SetSbrkHook(); +#if defined(HAVE___SBRK) && defined(__linux) && \ + (defined(__i386__) || defined(__x86_64__)) + p1 = sbrk(8192); + CHECK(p1 != NULL); + VerifySbrkHookWasCalled(); + p1 = sbrk(-8192); + CHECK(p1 != NULL); + VerifySbrkHookWasCalled(); + // However, sbrk hook should *not* be called with sbrk(0) + p1 = sbrk(0); + CHECK(p1 != NULL); + CHECK_EQ(g_SbrkHook_calls, 0); +#else // this is just to quiet the compiler: make sure all fns are called + IncrementCallsToSbrkHook(NULL, 0); + 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 + fprintf(LOGSTREAM, "Testing large allocation\n"); + { + const int mb_to_allocate = 100; + void* p = rnd.alloc(mb_to_allocate << 20); + CHECK(p != NULL); // could not allocate + free(p); + } + + TestMallocAlignment(); + + // Check calloc() with various arguments + fprintf(LOGSTREAM, "Testing calloc\n"); + TestCalloc(0, 0, true); + TestCalloc(0, 1, true); + TestCalloc(1, 1, true); + TestCalloc(1<<10, 0, true); + TestCalloc(1<<20, 0, true); + TestCalloc(0, 1<<10, true); + TestCalloc(0, 1<<20, true); + TestCalloc(1<<20, 2, true); + TestCalloc(2, 1<<20, true); + TestCalloc(1000, 1000, true); + + TestCalloc(kMaxSize, 2, false); + TestCalloc(2, kMaxSize, false); + TestCalloc(kMaxSize, kMaxSize, false); + + TestCalloc(kMaxSignedSize, 3, false); + TestCalloc(3, kMaxSignedSize, false); + TestCalloc(kMaxSignedSize, kMaxSignedSize, false); + + // Test that realloc doesn't always reallocate and copy memory. + fprintf(LOGSTREAM, "Testing realloc\n"); + TestRealloc(); + + fprintf(LOGSTREAM, "Testing operator new(nothrow).\n"); + TestNothrowNew(&::operator new); + fprintf(LOGSTREAM, "Testing operator new[](nothrow).\n"); + TestNothrowNew(&::operator new[]); + fprintf(LOGSTREAM, "Testing operator new.\n"); + TestNew(&::operator new); + fprintf(LOGSTREAM, "Testing operator new[].\n"); + TestNew(&::operator new[]); + + // Create threads + fprintf(LOGSTREAM, "Testing threaded allocation/deallocation (%d threads)\n", + FLAGS_numthreads); + threads = new TesterThread*[FLAGS_numthreads]; + for (int i = 0; i < FLAGS_numthreads; ++i) { + threads[i] = new TesterThread(i); + } + + // This runs all the tests at the same time, with a 1M stack size each + RunManyThreadsWithId(RunThread, FLAGS_numthreads, 1<<20); + + for (int i = 0; i < FLAGS_numthreads; ++i) delete threads[i]; // Cleanup + + // Do the memory intensive tests after threads are done, since exhausting + // the available address space can make pthread_create to fail. + + // Check that huge allocations fail with NULL instead of crashing + fprintf(LOGSTREAM, "Testing huge allocations\n"); + TestHugeAllocations(&rnd); + + // Check that large allocations fail with NULL instead of crashing +#ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs + fprintf(LOGSTREAM, "Testing out of memory\n"); + size_t old_limit; + CHECK(MallocExtension::instance()->GetNumericProperty("tcmalloc.heap_limit_mb", &old_limit)); + // Don't exercise more than 1 gig, no need to. + CHECK(MallocExtension::instance()->SetNumericProperty("tcmalloc.heap_limit_mb", 1 << 10)); + for (int s = 0; ; s += (10<<20)) { + void* large_object = rnd.alloc(s); + if (large_object == NULL) break; + free(large_object); + } + CHECK(MallocExtension::instance()->SetNumericProperty("tcmalloc.heap_limit_mb", old_limit)); +#endif + + TestHugeThreadCache(); + TestRanges(); + TestReleaseToSystem(); + TestAggressiveDecommit(); + TestSetNewMode(); + TestErrno(); + +// GetAllocatedSize under DEBUGALLOCATION returns the size that we asked for. +#ifndef DEBUGALLOCATION + TestNAllocX(); + TestNAllocXAlignment(); +#endif + + return 0; +} + +} + +using testing::RunAllTests; + +int main(int argc, char** argv) { +#ifdef DEBUGALLOCATION // debug allocation takes forever for huge allocs + FLAGS_max_free_queue_size = 0; // return freed blocks to tcmalloc immediately +#endif + + RunAllTests(argc, argv); + + // Test tc_version() + fprintf(LOGSTREAM, "Testing tc_version()\n"); + int major; + int minor; + const char* patch; + char mmp[64]; + const char* human_version = tc_version(&major, &minor, &patch); + snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); + CHECK(!strcmp(PACKAGE_STRING, human_version)); + CHECK(!strcmp(PACKAGE_VERSION, mmp)); + + fprintf(LOGSTREAM, "PASS\n"); +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.sh b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.sh new file mode 100755 index 000000000..0e7996a21 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/tcmalloc_unittest.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# Copyright (c) 2013, 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: Adhemerval Zanella +# +# Runs the tcmalloc_unittest with various environment variables. +# This is necessary because tuning some environment variables +# (TCMALLOC_TRANSFER_NUM_OBJ for instance) should not change program +# behavior, just performance. + +BINDIR="${BINDIR:-.}" +TCMALLOC_UNITTEST="${1:-$BINDIR/tcmalloc_unittest}" + +TMPDIR=/tmp/tcmalloc_unittest +rm -rf $TMPDIR || exit 2 +mkdir $TMPDIR || exit 3 + +run_unittest() { + if $TCMALLOC_UNITTEST > $TMPDIR/output 2>&1; then + echo "OK" + else + echo "FAILED" + echo "Output from the failed run:" + echo "----" + cat $TMPDIR/output + echo "----" + exit 4 + fi +} + +# $1: value of tcmalloc_unittest env. var. +run_check_transfer_num_obj() { + [ -n "$1" ] && export TCMALLOC_TRANSFER_NUM_OBJ="$1" + + echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_TRANSFER_NUM_OBJ=$1 ... " + run_unittest +} + +run_check_transfer_num_obj "" +run_check_transfer_num_obj "40" +run_check_transfer_num_obj "4096" + +echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_AGGRESSIVE_DECOMMIT=t ... " + +TCMALLOC_AGGRESSIVE_DECOMMIT=t run_unittest + +echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_HEAP_LIMIT_MB=512 ... " + +TCMALLOC_HEAP_LIMIT_MB=512 run_unittest + +echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_ENABLE_SIZED_DELETE=t ..." + +TCMALLOC_ENABLE_SIZED_DELETE=t run_unittest + +echo "PASS" diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.cc new file mode 100644 index 000000000..e5faa65f7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.cc @@ -0,0 +1,224 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein +// +// A few routines that are useful for multiple tests in this directory. + +#include "config_for_unittests.h" +#include // for NULL, abort() +// On FreeBSD, if you #include , you have to get stdint first. +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include "tests/testutil.h" + + +// When compiled 64-bit and run on systems with swap several unittests will end +// up trying to consume all of RAM+swap, and that can take quite some time. By +// limiting the address-space size we get sufficient coverage without blowing +// out job limits. +void SetTestResourceLimit() { +#ifdef HAVE_SYS_RESOURCE_H + // The actual resource we need to set varies depending on which flavour of + // unix. On Linux we need RLIMIT_AS because that covers the use of mmap. + // Otherwise hopefully RLIMIT_RSS is good enough. (Unfortunately 64-bit + // and 32-bit headers disagree on the type of these constants!) +#ifdef RLIMIT_AS +#define USE_RESOURCE RLIMIT_AS +#else +#define USE_RESOURCE RLIMIT_RSS +#endif + + // Restrict the test to 1GiB, which should fit comfortably well on both + // 32-bit and 64-bit hosts, and executes in ~1s. + const rlim_t kMaxMem = 1<<30; + + struct rlimit rlim; + if (getrlimit(USE_RESOURCE, &rlim) == 0) { + if (rlim.rlim_cur == RLIM_INFINITY || rlim.rlim_cur > kMaxMem) { + rlim.rlim_cur = kMaxMem; + setrlimit(USE_RESOURCE, &rlim); // ignore result + } + } +#endif /* HAVE_SYS_RESOURCE_H */ +} + + +struct FunctionAndId { + void (*ptr_to_function)(int); + int id; +}; + +#if defined(NO_THREADS) || !(defined(HAVE_PTHREAD) || defined(_WIN32)) + +extern "C" void RunThread(void (*fn)()) { + (*fn)(); +} + +extern "C" void RunManyThreads(void (*fn)(), int count) { + // I guess the best we can do is run fn sequentially, 'count' times + for (int i = 0; i < count; i++) + (*fn)(); +} + +extern "C" void RunManyThreadsWithId(void (*fn)(int), int count, int) { + for (int i = 0; i < count; i++) + (*fn)(i); // stacksize doesn't make sense in a non-threaded context +} + +#elif defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */ +#endif +#include + +extern "C" { + // This helper function has the signature that pthread_create wants. + DWORD WINAPI RunFunctionInThread(LPVOID ptr_to_ptr_to_fn) { + (**static_cast(ptr_to_ptr_to_fn))(); // runs fn + return 0; + } + + DWORD WINAPI RunFunctionInThreadWithId(LPVOID ptr_to_fnid) { + FunctionAndId* fn_and_id = static_cast(ptr_to_fnid); + (*fn_and_id->ptr_to_function)(fn_and_id->id); // runs fn + return 0; + } + + void RunManyThreads(void (*fn)(), int count) { + DWORD dummy; + HANDLE* hThread = new HANDLE[count]; + for (int i = 0; i < count; i++) { + hThread[i] = CreateThread(NULL, 0, RunFunctionInThread, &fn, 0, &dummy); + if (hThread[i] == NULL) ExitProcess(i); + } + WaitForMultipleObjects(count, hThread, TRUE, INFINITE); + for (int i = 0; i < count; i++) { + CloseHandle(hThread[i]); + } + delete[] hThread; + } + + void RunThread(void (*fn)()) { + RunManyThreads(fn, 1); + } + + void RunManyThreadsWithId(void (*fn)(int), int count, int stacksize) { + DWORD dummy; + HANDLE* hThread = new HANDLE[count]; + FunctionAndId* fn_and_ids = new FunctionAndId[count]; + for (int i = 0; i < count; i++) { + fn_and_ids[i].ptr_to_function = fn; + fn_and_ids[i].id = i; + hThread[i] = CreateThread(NULL, stacksize, RunFunctionInThreadWithId, + &fn_and_ids[i], 0, &dummy); + if (hThread[i] == NULL) ExitProcess(i); + } + WaitForMultipleObjects(count, hThread, TRUE, INFINITE); + for (int i = 0; i < count; i++) { + CloseHandle(hThread[i]); + } + delete[] fn_and_ids; + delete[] hThread; + } +} + +#else // not NO_THREADS, not !HAVE_PTHREAD, not _WIN32 + +#include + +#define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) + +extern "C" { + // This helper function has the signature that pthread_create wants. + static void* RunFunctionInThread(void *ptr_to_ptr_to_fn) { + (**static_cast(ptr_to_ptr_to_fn))(); // runs fn + return NULL; + } + + static void* RunFunctionInThreadWithId(void *ptr_to_fnid) { + FunctionAndId* fn_and_id = static_cast(ptr_to_fnid); + (*fn_and_id->ptr_to_function)(fn_and_id->id); // runs fn + return NULL; + } + + // Run a function in a thread of its own and wait for it to finish. + // This is useful for tcmalloc testing, because each thread is + // handled separately in tcmalloc, so there's interesting stuff to + // test even if the threads are not running concurrently. + void RunThread(void (*fn)()) { + pthread_t thr; + // Even though fn is on the stack, it's safe to pass a pointer to it, + // because we pthread_join immediately (ie, before RunInThread exits). + SAFE_PTHREAD(pthread_create(&thr, NULL, RunFunctionInThread, &fn)); + SAFE_PTHREAD(pthread_join(thr, NULL)); + } + + void RunManyThreads(void (*fn)(), int count) { + pthread_t* thr = new pthread_t[count]; + for (int i = 0; i < count; i++) { + SAFE_PTHREAD(pthread_create(&thr[i], NULL, RunFunctionInThread, &fn)); + } + for (int i = 0; i < count; i++) { + SAFE_PTHREAD(pthread_join(thr[i], NULL)); + } + delete[] thr; + } + + void RunManyThreadsWithId(void (*fn)(int), int count, int stacksize) { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, stacksize); + + pthread_t* thr = new pthread_t[count]; + FunctionAndId* fn_and_ids = new FunctionAndId[count]; + for (int i = 0; i < count; i++) { + fn_and_ids[i].ptr_to_function = fn; + fn_and_ids[i].id = i; + SAFE_PTHREAD(pthread_create(&thr[i], &attr, + RunFunctionInThreadWithId, &fn_and_ids[i])); + } + for (int i = 0; i < count; i++) { + SAFE_PTHREAD(pthread_join(thr[i], NULL)); + } + delete[] fn_and_ids; + delete[] thr; + + pthread_attr_destroy(&attr); + } +} + +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.h b/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.h new file mode 100644 index 000000000..dc1db9b4a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/testutil.h @@ -0,0 +1,73 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein + +#ifndef TCMALLOC_TOOLS_TESTUTIL_H_ +#define TCMALLOC_TOOLS_TESTUTIL_H_ + +// Run a function in a thread of its own and wait for it to finish. +// The function you pass in must have the signature +// void MyFunction(); +extern "C" void RunThread(void (*fn)()); + +// Run a function X times, in X threads, and wait for them all to finish. +// The function you pass in must have the signature +// void MyFunction(); +extern "C" void RunManyThreads(void (*fn)(), int count); + +// The 'advanced' version: run a function X times, in X threads, and +// wait for them all to finish. Give them all the specified stack-size. +// (If you're curious why this takes a stacksize and the others don't, +// it's because the one client of this fn wanted to specify stacksize. :-) ) +// The function you pass in must have the signature +// void MyFunction(int idx); +// where idx is the index of the thread (which of the X threads this is). +extern "C" void RunManyThreadsWithId(void (*fn)(int), int count, int stacksize); + +// When compiled 64-bit and run on systems with swap several unittests will end +// up trying to consume all of RAM+swap, and that can take quite some time. By +// limiting the address-space size we get sufficient coverage without blowing +// out job limits. +void SetTestResourceLimit(); + +static void (* volatile noopt_helper)(void *) = +[] (void* dummy) {}; + +// This function forces compiler to forget specific knowledge about +// value of 'val'. This is useful to avoid compiler optimizing out +// new/delete pairs for our unit tests. +template +T noopt(T val) { + noopt_helper(&val); + return val; +} + +#endif // TCMALLOC_TOOLS_TESTUTIL_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/tests/thread_dealloc_unittest.cc b/trunk/3rdparty/gperftools-2-fit/src/tests/thread_dealloc_unittest.cc new file mode 100644 index 000000000..770a76080 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/tests/thread_dealloc_unittest.cc @@ -0,0 +1,84 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2004, 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: Sanjay Ghemawat +// +// Check that we do not leak memory when cycling through lots of threads. + +#include "config_for_unittests.h" +#include +#ifdef HAVE_UNISTD_H +#include // for sleep() +#endif +#include "base/logging.h" +#include +#include "tests/testutil.h" // for RunThread() + +// Size/number of objects to allocate per thread (1 MB per thread) +static const int kObjectSize = 1024; +static const int kNumObjects = 1024; + +// Number of threads to create and destroy +static const int kNumThreads = 1000; + +// Allocate lots of stuff +static void AllocStuff() { + void** objects = new void*[kNumObjects]; + for (int i = 0; i < kNumObjects; i++) { + objects[i] = malloc(kObjectSize); + } + for (int i = 0; i < kNumObjects; i++) { + free(objects[i]); + } + delete[] objects; +} + +int main(int argc, char** argv) { + static const int kDisplaySize = 1048576; + char* display = new char[kDisplaySize]; + + for (int i = 0; i < kNumThreads; i++) { + RunThread(&AllocStuff); + + if (((i+1) % 200) == 0) { + fprintf(stderr, "Iteration: %d of %d\n", (i+1), kNumThreads); + MallocExtension::instance()->GetStats(display, kDisplaySize); + fprintf(stderr, "%s\n", display); + } + } + delete[] display; + + printf("PASS\n"); +#ifdef HAVE_UNISTD_H + sleep(1); // Prevent exit race problem with glibc +#endif + return 0; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/thread_cache.cc b/trunk/3rdparty/gperftools-2-fit/src/thread_cache.cc new file mode 100644 index 000000000..21d0f8e70 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/thread_cache.cc @@ -0,0 +1,529 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Ken Ashcraft + +#include +#include "thread_cache.h" +#include +#include // for memcpy +#include // for max, min +#include "base/commandlineflags.h" // for SpinLockHolder +#include "base/spinlock.h" // for SpinLockHolder +#include "getenv_safe.h" // for TCMallocGetenvSafe +#include "central_freelist.h" // for CentralFreeListPadded +#include "maybe_threads.h" + +using std::min; +using std::max; + +// Note: this is initialized manually in InitModule to ensure that +// it's configured at right time +// +// DEFINE_int64(tcmalloc_max_total_thread_cache_bytes, +// EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", +// kDefaultOverallThreadCacheSize), +// "Bound on the total amount of bytes allocated to " +// "thread caches. This bound is not strict, so it is possible " +// "for the cache to go over this bound in certain circumstances. " +// "Maximum value of this flag is capped to 1 GB."); + + +namespace tcmalloc { + +static bool phinited = false; + +volatile size_t ThreadCache::per_thread_cache_size_ = kMaxThreadCacheSize; +size_t ThreadCache::overall_thread_cache_size_ = kDefaultOverallThreadCacheSize; +ssize_t ThreadCache::unclaimed_cache_space_ = kDefaultOverallThreadCacheSize; +PageHeapAllocator threadcache_allocator; +ThreadCache* ThreadCache::thread_heaps_ = NULL; +int ThreadCache::thread_heap_count_ = 0; +ThreadCache* ThreadCache::next_memory_steal_ = NULL; +#ifdef HAVE_TLS +__thread ThreadCache::ThreadLocalData ThreadCache::threadlocal_data_ + ATTR_INITIAL_EXEC CACHELINE_ALIGNED; +#endif +bool ThreadCache::tsd_inited_ = false; +pthread_key_t ThreadCache::heap_key_; + +void ThreadCache::Init(pthread_t tid) { + size_ = 0; + + max_size_ = 0; + IncreaseCacheLimitLocked(); + if (max_size_ == 0) { + // There isn't enough memory to go around. Just give the minimum to + // this thread. + SetMaxSize(kMinThreadCacheSize); + + // Take unclaimed_cache_space_ negative. + unclaimed_cache_space_ -= kMinThreadCacheSize; + ASSERT(unclaimed_cache_space_ < 0); + } + + next_ = NULL; + prev_ = NULL; + tid_ = tid; + in_setspecific_ = false; + for (uint32 cl = 0; cl < Static::num_size_classes(); ++cl) { + list_[cl].Init(Static::sizemap()->class_to_size(cl)); + } + + uint32_t sampler_seed; + memcpy(&sampler_seed, &tid, sizeof(sampler_seed)); + sampler_.Init(sampler_seed); +} + +void ThreadCache::Cleanup() { + // Put unused memory back into central cache + for (uint32 cl = 0; cl < Static::num_size_classes(); ++cl) { + if (list_[cl].length() > 0) { + ReleaseToCentralCache(&list_[cl], cl, list_[cl].length()); + } + } +} + +// Remove some objects of class "cl" from central cache and add to thread heap. +// On success, return the first object for immediate use; otherwise return NULL. +void* ThreadCache::FetchFromCentralCache(uint32 cl, int32_t byte_size, + void *(*oom_handler)(size_t size)) { + FreeList* list = &list_[cl]; + ASSERT(list->empty()); + const int batch_size = Static::sizemap()->num_objects_to_move(cl); + + const int num_to_move = min(list->max_length(), batch_size); + void *start, *end; + int fetch_count = Static::central_cache()[cl].RemoveRange( + &start, &end, num_to_move); + + if (fetch_count == 0) { + ASSERT(start == NULL); + return oom_handler(byte_size); + } + ASSERT(start != NULL); + + if (--fetch_count >= 0) { + size_ += byte_size * fetch_count; + list->PushRange(fetch_count, SLL_Next(start), end); + } + + // Increase max length slowly up to batch_size. After that, + // increase by batch_size in one shot so that the length is a + // multiple of batch_size. + if (list->max_length() < batch_size) { + list->set_max_length(list->max_length() + 1); + } else { + // Don't let the list get too long. In 32 bit builds, the length + // is represented by a 16 bit int, so we need to watch out for + // integer overflow. + int new_length = min(list->max_length() + batch_size, + kMaxDynamicFreeListLength); + // The list's max_length must always be a multiple of batch_size, + // and kMaxDynamicFreeListLength is not necessarily a multiple + // of batch_size. + new_length -= new_length % batch_size; + ASSERT(new_length % batch_size == 0); + list->set_max_length(new_length); + } + return start; +} + +void ThreadCache::ListTooLong(FreeList* list, uint32 cl) { + size_ += list->object_size(); + + const int batch_size = Static::sizemap()->num_objects_to_move(cl); + ReleaseToCentralCache(list, cl, batch_size); + + // If the list is too long, we need to transfer some number of + // objects to the central cache. Ideally, we would transfer + // num_objects_to_move, so the code below tries to make max_length + // converge on num_objects_to_move. + + if (list->max_length() < batch_size) { + // Slow start the max_length so we don't overreserve. + list->set_max_length(list->max_length() + 1); + } else if (list->max_length() > batch_size) { + // If we consistently go over max_length, shrink max_length. If we don't + // shrink it, some amount of memory will always stay in this freelist. + list->set_length_overages(list->length_overages() + 1); + if (list->length_overages() > kMaxOverages) { + ASSERT(list->max_length() > batch_size); + list->set_max_length(list->max_length() - batch_size); + list->set_length_overages(0); + } + } + + if (PREDICT_FALSE(size_ > max_size_)) { + Scavenge(); + } +} + +// Remove some objects of class "cl" from thread heap and add to central cache +void ThreadCache::ReleaseToCentralCache(FreeList* src, uint32 cl, int N) { + ASSERT(src == &list_[cl]); + if (N > src->length()) N = src->length(); + size_t delta_bytes = N * Static::sizemap()->ByteSizeForClass(cl); + + // We return prepackaged chains of the correct size to the central cache. + // TODO: Use the same format internally in the thread caches? + int batch_size = Static::sizemap()->num_objects_to_move(cl); + while (N > batch_size) { + void *tail, *head; + src->PopRange(batch_size, &head, &tail); + Static::central_cache()[cl].InsertRange(head, tail, batch_size); + N -= batch_size; + } + void *tail, *head; + src->PopRange(N, &head, &tail); + Static::central_cache()[cl].InsertRange(head, tail, N); + size_ -= delta_bytes; +} + +// Release idle memory to the central cache +void ThreadCache::Scavenge() { + // If the low-water mark for the free list is L, it means we would + // not have had to allocate anything from the central cache even if + // we had reduced the free list size by L. We aim to get closer to + // that situation by dropping L/2 nodes from the free list. This + // may not release much memory, but if so we will call scavenge again + // pretty soon and the low-water marks will be high on that call. + for (int cl = 0; cl < Static::num_size_classes(); cl++) { + FreeList* list = &list_[cl]; + const int lowmark = list->lowwatermark(); + if (lowmark > 0) { + const int drop = (lowmark > 1) ? lowmark/2 : 1; + ReleaseToCentralCache(list, cl, drop); + + // Shrink the max length if it isn't used. Only shrink down to + // batch_size -- if the thread was active enough to get the max_length + // above batch_size, it will likely be that active again. If + // max_length shinks below batch_size, the thread will have to + // go through the slow-start behavior again. The slow-start is useful + // mainly for threads that stay relatively idle for their entire + // lifetime. + const int batch_size = Static::sizemap()->num_objects_to_move(cl); + if (list->max_length() > batch_size) { + list->set_max_length( + max(list->max_length() - batch_size, batch_size)); + } + } + list->clear_lowwatermark(); + } + + IncreaseCacheLimit(); +} + +void ThreadCache::IncreaseCacheLimit() { + SpinLockHolder h(Static::pageheap_lock()); + IncreaseCacheLimitLocked(); +} + +void ThreadCache::IncreaseCacheLimitLocked() { + if (unclaimed_cache_space_ > 0) { + // Possibly make unclaimed_cache_space_ negative. + unclaimed_cache_space_ -= kStealAmount; + SetMaxSize(max_size_ + kStealAmount); + return; + } + // Don't hold pageheap_lock too long. Try to steal from 10 other + // threads before giving up. The i < 10 condition also prevents an + // infinite loop in case none of the existing thread heaps are + // suitable places to steal from. + for (int i = 0; i < 10; + ++i, next_memory_steal_ = next_memory_steal_->next_) { + // Reached the end of the linked list. Start at the beginning. + if (next_memory_steal_ == NULL) { + ASSERT(thread_heaps_ != NULL); + next_memory_steal_ = thread_heaps_; + } + if (next_memory_steal_ == this || + next_memory_steal_->max_size_ <= kMinThreadCacheSize) { + continue; + } + next_memory_steal_->SetMaxSize(next_memory_steal_->max_size_ - kStealAmount); + SetMaxSize(max_size_ + kStealAmount); + + next_memory_steal_ = next_memory_steal_->next_; + return; + } +} + +int ThreadCache::GetSamplePeriod() { + return Sampler::GetSamplePeriod(); +} + +void ThreadCache::InitModule() { + { + SpinLockHolder h(Static::pageheap_lock()); + if (phinited) { + return; + } + const char *tcb = TCMallocGetenvSafe("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"); + if (tcb) { + set_overall_thread_cache_size(strtoll(tcb, NULL, 10)); + } + Static::InitStaticVars(); + threadcache_allocator.Init(); + phinited = 1; + } + + // We do "late" part of initialization without holding lock since + // there is chance it'll recurse into malloc + Static::InitLateMaybeRecursive(); +} + +void ThreadCache::InitTSD() { + ASSERT(!tsd_inited_); + perftools_pthread_key_create(&heap_key_, DestroyThreadCache); + tsd_inited_ = true; + +#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY + // We may have used a fake pthread_t for the main thread. Fix it. + pthread_t zero; + memset(&zero, 0, sizeof(zero)); + SpinLockHolder h(Static::pageheap_lock()); + for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { + if (h->tid_ == zero) { + h->tid_ = pthread_self(); + } + } +#endif +} + +ThreadCache* ThreadCache::CreateCacheIfNecessary() { + if (!tsd_inited_) { +#ifndef NDEBUG + // tests that freeing nullptr very early is working + free(NULL); +#endif + + InitModule(); + } + + // Initialize per-thread data if necessary + ThreadCache* heap = NULL; + + bool seach_condition = true; +#ifdef HAVE_TLS + static __thread ThreadCache** current_heap_ptr ATTR_INITIAL_EXEC; + if (tsd_inited_) { + // In most common case we're avoiding expensive linear search + // through all heaps (see below). Working TLS enables faster + // protection from malloc recursion in pthread_setspecific + seach_condition = false; + + if (current_heap_ptr != NULL) { + // we're being recursively called by pthread_setspecific below. + return *current_heap_ptr; + } + current_heap_ptr = &heap; + } +#endif + + { + SpinLockHolder h(Static::pageheap_lock()); + // On some old glibc's, and on freebsd's libc (as of freebsd 8.1), + // calling pthread routines (even pthread_self) too early could + // cause a segfault. Since we can call pthreads quite early, we + // have to protect against that in such situations by making a + // 'fake' pthread. This is not ideal since it doesn't work well + // when linking tcmalloc statically with apps that create threads + // before main, so we only do it if we have to. +#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY + pthread_t me; + if (!tsd_inited_) { + memset(&me, 0, sizeof(me)); + } else { + me = pthread_self(); + } +#else + const pthread_t me = pthread_self(); +#endif + + // This may be a recursive malloc call from pthread_setspecific() + // In that case, the heap for this thread has already been created + // and added to the linked list. So we search for that first. + if (seach_condition) { + for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { + if (h->tid_ == me) { + heap = h; + break; + } + } + } + + if (heap == NULL) heap = NewHeap(me); + } + + // We call pthread_setspecific() outside the lock because it may + // call malloc() recursively. We check for the recursive call using + // the "in_setspecific_" flag so that we can avoid calling + // pthread_setspecific() if we are already inside pthread_setspecific(). + if (!heap->in_setspecific_ && tsd_inited_) { + heap->in_setspecific_ = true; + perftools_pthread_setspecific(heap_key_, heap); +#ifdef HAVE_TLS + // Also keep a copy in __thread for faster retrieval + threadlocal_data_.heap = heap; + threadlocal_data_.fast_path_heap = heap; +#endif + heap->in_setspecific_ = false; + } +#ifdef HAVE_TLS + current_heap_ptr = NULL; +#endif + return heap; +} + +ThreadCache* ThreadCache::NewHeap(pthread_t tid) { + // Create the heap and add it to the linked list + ThreadCache *heap = threadcache_allocator.New(); + heap->Init(tid); + heap->next_ = thread_heaps_; + heap->prev_ = NULL; + if (thread_heaps_ != NULL) { + thread_heaps_->prev_ = heap; + } else { + // This is the only thread heap at the momment. + ASSERT(next_memory_steal_ == NULL); + next_memory_steal_ = heap; + } + thread_heaps_ = heap; + thread_heap_count_++; + return heap; +} + +void ThreadCache::BecomeIdle() { + if (!tsd_inited_) return; // No caches yet + ThreadCache* heap = GetThreadHeap(); + if (heap == NULL) return; // No thread cache to remove + if (heap->in_setspecific_) return; // Do not disturb the active caller + + heap->in_setspecific_ = true; + perftools_pthread_setspecific(heap_key_, NULL); +#ifdef HAVE_TLS + // Also update the copy in __thread + threadlocal_data_.heap = NULL; + threadlocal_data_.fast_path_heap = NULL; +#endif + heap->in_setspecific_ = false; + if (GetThreadHeap() == heap) { + // Somehow heap got reinstated by a recursive call to malloc + // from pthread_setspecific. We give up in this case. + return; + } + + // We can now get rid of the heap + DeleteCache(heap); +} + +void ThreadCache::BecomeTemporarilyIdle() { + ThreadCache* heap = GetCacheIfPresent(); + if (heap) + heap->Cleanup(); +} + +void ThreadCache::DestroyThreadCache(void* ptr) { + // Note that "ptr" cannot be NULL since pthread promises not + // to invoke the destructor on NULL values, but for safety, + // we check anyway. + if (ptr == NULL) return; +#ifdef HAVE_TLS + // Prevent fast path of GetThreadHeap() from returning heap. + threadlocal_data_.heap = NULL; + threadlocal_data_.fast_path_heap = NULL; +#endif + DeleteCache(reinterpret_cast(ptr)); +} + +void ThreadCache::DeleteCache(ThreadCache* heap) { + // Remove all memory from heap + heap->Cleanup(); + + // Remove from linked list + SpinLockHolder h(Static::pageheap_lock()); + if (heap->next_ != NULL) heap->next_->prev_ = heap->prev_; + if (heap->prev_ != NULL) heap->prev_->next_ = heap->next_; + if (thread_heaps_ == heap) thread_heaps_ = heap->next_; + thread_heap_count_--; + + if (next_memory_steal_ == heap) next_memory_steal_ = heap->next_; + if (next_memory_steal_ == NULL) next_memory_steal_ = thread_heaps_; + unclaimed_cache_space_ += heap->max_size_; + + threadcache_allocator.Delete(heap); +} + +void ThreadCache::RecomputePerThreadCacheSize() { + // Divide available space across threads + int n = thread_heap_count_ > 0 ? thread_heap_count_ : 1; + size_t space = overall_thread_cache_size_ / n; + + // Limit to allowed range + if (space < kMinThreadCacheSize) space = kMinThreadCacheSize; + if (space > kMaxThreadCacheSize) space = kMaxThreadCacheSize; + + double ratio = space / max(1, per_thread_cache_size_); + size_t claimed = 0; + for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { + // Increasing the total cache size should not circumvent the + // slow-start growth of max_size_. + if (ratio < 1.0) { + h->SetMaxSize(h->max_size_ * ratio); + } + claimed += h->max_size_; + } + unclaimed_cache_space_ = overall_thread_cache_size_ - claimed; + per_thread_cache_size_ = space; +} + +void ThreadCache::GetThreadStats(uint64_t* total_bytes, uint64_t* class_count) { + for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { + *total_bytes += h->Size(); + if (class_count) { + for (int cl = 0; cl < Static::num_size_classes(); ++cl) { + class_count[cl] += h->freelist_length(cl); + } + } + } +} + +void ThreadCache::set_overall_thread_cache_size(size_t new_size) { + // Clip the value to a reasonable range + if (new_size < kMinThreadCacheSize) new_size = kMinThreadCacheSize; + if (new_size > (1<<30)) new_size = (1<<30); // Limit to 1GB + overall_thread_cache_size_ = new_size; + + RecomputePerThreadCacheSize(); +} + +} // namespace tcmalloc diff --git a/trunk/3rdparty/gperftools-2-fit/src/thread_cache.h b/trunk/3rdparty/gperftools-2-fit/src/thread_cache.h new file mode 100644 index 000000000..f8be15267 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/thread_cache.h @@ -0,0 +1,510 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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: Sanjay Ghemawat + +#ifndef TCMALLOC_THREAD_CACHE_H_ +#define TCMALLOC_THREAD_CACHE_H_ + +#include +#ifdef HAVE_PTHREAD +#include // for pthread_t, pthread_key_t +#endif +#include // for size_t, NULL +#ifdef HAVE_STDINT_H +#include // for uint32_t, uint64_t +#endif +#include // for ssize_t +#include "base/commandlineflags.h" +#include "common.h" +#include "linked_list.h" +#include "maybe_threads.h" +#include "page_heap_allocator.h" +#include "sampler.h" +#include "static_vars.h" + +#include "common.h" // for SizeMap, kMaxSize, etc +#include "internal_logging.h" // for ASSERT, etc +#include "linked_list.h" // for SLL_Pop, SLL_PopRange, etc +#include "page_heap_allocator.h" // for PageHeapAllocator +#include "sampler.h" // for Sampler +#include "static_vars.h" // for Static + +DECLARE_int64(tcmalloc_sample_parameter); + +namespace tcmalloc { + +//------------------------------------------------------------------- +// Data kept per thread +//------------------------------------------------------------------- + +class ThreadCache { + public: +#ifdef HAVE_TLS + enum { have_tls = true }; +#else + enum { have_tls = false }; +#endif + + void Init(pthread_t tid); + void Cleanup(); + + // Accessors (mostly just for printing stats) + int freelist_length(uint32 cl) const { return list_[cl].length(); } + + // Total byte size in cache + size_t Size() const { return size_; } + + // Allocate an object of the given size and class. The size given + // must be the same as the size of the class in the size map. + void* Allocate(size_t size, uint32 cl, void *(*oom_handler)(size_t size)); + void Deallocate(void* ptr, uint32 size_class); + + void Scavenge(); + + int GetSamplePeriod(); + + // Record allocation of "k" bytes. Return true iff allocation + // should be sampled + bool SampleAllocation(size_t k); + + bool TryRecordAllocationFast(size_t k); + + static void InitModule(); + static void InitTSD(); + static ThreadCache* GetThreadHeap(); + static ThreadCache* GetCache(); + static ThreadCache* GetCacheIfPresent(); + static ThreadCache* GetFastPathCache(); + static ThreadCache* GetCacheWhichMustBePresent(); + static ThreadCache* CreateCacheIfNecessary(); + static void BecomeIdle(); + static void BecomeTemporarilyIdle(); + static void SetUseEmergencyMalloc(); + static void ResetUseEmergencyMalloc(); + static bool IsUseEmergencyMalloc(); + + // Return the number of thread heaps in use. + static inline int HeapsInUse(); + + // Adds to *total_bytes the total number of bytes used by all thread heaps. + // Also, if class_count is not NULL, it must be an array of size kNumClasses, + // and this function will increment each element of class_count by the number + // of items in all thread-local freelists of the corresponding size class. + // REQUIRES: Static::pageheap_lock is held. + static void GetThreadStats(uint64_t* total_bytes, uint64_t* class_count); + + // Sets the total thread cache size to new_size, recomputing the + // individual thread cache sizes as necessary. + // REQUIRES: Static::pageheap lock is held. + static void set_overall_thread_cache_size(size_t new_size); + static size_t overall_thread_cache_size() { + return overall_thread_cache_size_; + } + + private: + class FreeList { + private: + void* list_; // Linked list of nodes + +#ifdef _LP64 + // On 64-bit hardware, manipulating 16-bit values may be slightly slow. + uint32_t length_; // Current length. + uint32_t lowater_; // Low water mark for list length. + uint32_t max_length_; // Dynamic max list length based on usage. + // Tracks the number of times a deallocation has caused + // length_ > max_length_. After the kMaxOverages'th time, max_length_ + // shrinks and length_overages_ is reset to zero. + uint32_t length_overages_; +#else + // If we aren't using 64-bit pointers then pack these into less space. + uint16_t length_; + uint16_t lowater_; + uint16_t max_length_; + uint16_t length_overages_; +#endif + + int32_t size_; + + public: + void Init(size_t size) { + list_ = NULL; + length_ = 0; + lowater_ = 0; + max_length_ = 1; + length_overages_ = 0; + size_ = size; + } + + // Return current length of list + size_t length() const { + return length_; + } + + int32_t object_size() const { + return size_; + } + + // Return the maximum length of the list. + size_t max_length() const { + return max_length_; + } + + // Set the maximum length of the list. If 'new_max' > length(), the + // client is responsible for removing objects from the list. + void set_max_length(size_t new_max) { + max_length_ = new_max; + } + + // Return the number of times that length() has gone over max_length(). + size_t length_overages() const { + return length_overages_; + } + + void set_length_overages(size_t new_count) { + length_overages_ = new_count; + } + + // Is list empty? + bool empty() const { + return list_ == NULL; + } + + // Low-water mark management + int lowwatermark() const { return lowater_; } + void clear_lowwatermark() { lowater_ = length_; } + + uint32_t Push(void* ptr) { + uint32_t length = length_ + 1; + SLL_Push(&list_, ptr); + length_ = length; + return length; + } + + void* Pop() { + ASSERT(list_ != NULL); + length_--; + if (length_ < lowater_) lowater_ = length_; + return SLL_Pop(&list_); + } + + bool TryPop(void **rv) { + if (SLL_TryPop(&list_, rv)) { + length_--; + if (PREDICT_FALSE(length_ < lowater_)) lowater_ = length_; + return true; + } + return false; + } + + void* Next() { + return SLL_Next(&list_); + } + + void PushRange(int N, void *start, void *end) { + SLL_PushRange(&list_, start, end); + length_ += N; + } + + void PopRange(int N, void **start, void **end) { + SLL_PopRange(&list_, N, start, end); + ASSERT(length_ >= N); + length_ -= N; + if (length_ < lowater_) lowater_ = length_; + } + }; + + // Gets and returns an object from the central cache, and, if possible, + // also adds some objects of that size class to this thread cache. + void* FetchFromCentralCache(uint32 cl, int32_t byte_size, + void *(*oom_handler)(size_t size)); + + void ListTooLong(void* ptr, uint32 cl); + + // Releases some number of items from src. Adjusts the list's max_length + // to eventually converge on num_objects_to_move(cl). + void ListTooLong(FreeList* src, uint32 cl); + + // Releases N items from this thread cache. + void ReleaseToCentralCache(FreeList* src, uint32 cl, int N); + + void SetMaxSize(int32 new_max_size); + + // Increase max_size_ by reducing unclaimed_cache_space_ or by + // reducing the max_size_ of some other thread. In both cases, + // the delta is kStealAmount. + void IncreaseCacheLimit(); + // Same as above but requires Static::pageheap_lock() is held. + void IncreaseCacheLimitLocked(); + + // If TLS is available, we also store a copy of the per-thread object + // in a __thread variable since __thread variables are faster to read + // than pthread_getspecific(). We still need pthread_setspecific() + // because __thread variables provide no way to run cleanup code when + // a thread is destroyed. + // We also give a hint to the compiler to use the "initial exec" TLS + // model. This is faster than the default TLS model, at the cost that + // you cannot dlopen this library. (To see the difference, look at + // the CPU use of __tls_get_addr with and without this attribute.) + // Since we don't really use dlopen in google code -- and using dlopen + // on a malloc replacement is asking for trouble in any case -- that's + // a good tradeoff for us. +#ifdef HAVE_TLS + struct ThreadLocalData { + ThreadCache* fast_path_heap; + ThreadCache* heap; + bool use_emergency_malloc; + }; + static __thread ThreadLocalData threadlocal_data_ + CACHELINE_ALIGNED ATTR_INITIAL_EXEC; + +#endif + + // Thread-specific key. Initialization here is somewhat tricky + // because some Linux startup code invokes malloc() before it + // is in a good enough state to handle pthread_keycreate(). + // Therefore, we use TSD keys only after tsd_inited is set to true. + // Until then, we use a slow path to get the heap object. + static ATTRIBUTE_HIDDEN bool tsd_inited_; + static pthread_key_t heap_key_; + + // Linked list of heap objects. Protected by Static::pageheap_lock. + static ThreadCache* thread_heaps_; + static int thread_heap_count_; + + // A pointer to one of the objects in thread_heaps_. Represents + // the next ThreadCache from which a thread over its max_size_ should + // steal memory limit. Round-robin through all of the objects in + // thread_heaps_. Protected by Static::pageheap_lock. + static ThreadCache* next_memory_steal_; + + // Overall thread cache size. Protected by Static::pageheap_lock. + static size_t overall_thread_cache_size_; + + // Global per-thread cache size. Writes are protected by + // Static::pageheap_lock. Reads are done without any locking, which should be + // fine as long as size_t can be written atomically and we don't place + // invariants between this variable and other pieces of state. + static volatile size_t per_thread_cache_size_; + + // Represents overall_thread_cache_size_ minus the sum of max_size_ + // across all ThreadCaches. Protected by Static::pageheap_lock. + static ssize_t unclaimed_cache_space_; + + // This class is laid out with the most frequently used fields + // first so that hot elements are placed on the same cache line. + + FreeList list_[kClassSizesMax]; // Array indexed by size-class + + int32 size_; // Combined size of data + int32 max_size_; // size_ > max_size_ --> Scavenge() + + // We sample allocations, biased by the size of the allocation + Sampler sampler_; // A sampler + + pthread_t tid_; // Which thread owns it + bool in_setspecific_; // In call to pthread_setspecific? + + // Allocate a new heap. REQUIRES: Static::pageheap_lock is held. + static ThreadCache* NewHeap(pthread_t tid); + + // Use only as pthread thread-specific destructor function. + static void DestroyThreadCache(void* ptr); + + static void DeleteCache(ThreadCache* heap); + static void RecomputePerThreadCacheSize(); + +public: + + // All ThreadCache objects are kept in a linked list (for stats collection) + ThreadCache* next_; + ThreadCache* prev_; + + // Ensure that this class is cacheline-aligned. This is critical for + // performance, as false sharing would negate many of the benefits + // of a per-thread cache. +} CACHELINE_ALIGNED; + +// Allocator for thread heaps +// This is logically part of the ThreadCache class, but MSVC, at +// least, does not like using ThreadCache as a template argument +// before the class is fully defined. So we put it outside the class. +extern PageHeapAllocator threadcache_allocator; + +inline int ThreadCache::HeapsInUse() { + return threadcache_allocator.inuse(); +} + +inline ATTRIBUTE_ALWAYS_INLINE void* ThreadCache::Allocate( + size_t size, uint32 cl, void *(*oom_handler)(size_t size)) { + FreeList* list = &list_[cl]; + +#ifdef NO_TCMALLOC_SAMPLES + size = list->object_size(); +#endif + + ASSERT(size <= kMaxSize); + ASSERT(size != 0); + ASSERT(size == 0 || size == Static::sizemap()->ByteSizeForClass(cl)); + + void* rv; + if (!list->TryPop(&rv)) { + return FetchFromCentralCache(cl, size, oom_handler); + } + size_ -= size; + return rv; +} + +inline ATTRIBUTE_ALWAYS_INLINE void ThreadCache::Deallocate(void* ptr, uint32 cl) { + ASSERT(list_[cl].max_length() > 0); + FreeList* list = &list_[cl]; + + // This catches back-to-back frees of allocs in the same size + // class. A more comprehensive (and expensive) test would be to walk + // the entire freelist. But this might be enough to find some bugs. + ASSERT(ptr != list->Next()); + + uint32_t length = list->Push(ptr); + + if (PREDICT_FALSE(length > list->max_length())) { + ListTooLong(list, cl); + return; + } + + size_ += list->object_size(); + if (PREDICT_FALSE(size_ > max_size_)){ + Scavenge(); + } +} + +inline ThreadCache* ThreadCache::GetThreadHeap() { +#ifdef HAVE_TLS + return threadlocal_data_.heap; +#else + return reinterpret_cast( + perftools_pthread_getspecific(heap_key_)); +#endif +} + +inline ThreadCache* ThreadCache::GetCacheWhichMustBePresent() { +#ifdef HAVE_TLS + ASSERT(threadlocal_data_.heap); + return threadlocal_data_.heap; +#else + ASSERT(perftools_pthread_getspecific(heap_key_)); + return reinterpret_cast( + perftools_pthread_getspecific(heap_key_)); +#endif +} + +inline ThreadCache* ThreadCache::GetCache() { +#ifdef HAVE_TLS + ThreadCache* ptr = GetThreadHeap(); +#else + ThreadCache* ptr = NULL; + if (PREDICT_TRUE(tsd_inited_)) { + ptr = GetThreadHeap(); + } +#endif + if (ptr == NULL) ptr = CreateCacheIfNecessary(); + return ptr; +} + +// In deletion paths, we do not try to create a thread-cache. This is +// because we may be in the thread destruction code and may have +// already cleaned up the cache for this thread. +inline ThreadCache* ThreadCache::GetCacheIfPresent() { +#ifndef HAVE_TLS + if (PREDICT_FALSE(!tsd_inited_)) return NULL; +#endif + return GetThreadHeap(); +} + +inline ThreadCache* ThreadCache::GetFastPathCache() { +#ifndef HAVE_TLS + return GetCacheIfPresent(); +#else + return threadlocal_data_.fast_path_heap; +#endif +} + +inline void ThreadCache::SetUseEmergencyMalloc() { +#ifdef HAVE_TLS + threadlocal_data_.fast_path_heap = NULL; + threadlocal_data_.use_emergency_malloc = true; +#endif +} + +inline void ThreadCache::ResetUseEmergencyMalloc() { +#ifdef HAVE_TLS + ThreadCache *heap = threadlocal_data_.heap; + threadlocal_data_.fast_path_heap = heap; + threadlocal_data_.use_emergency_malloc = false; +#endif +} + +inline bool ThreadCache::IsUseEmergencyMalloc() { +#if defined(HAVE_TLS) && defined(ENABLE_EMERGENCY_MALLOC) + return PREDICT_FALSE(threadlocal_data_.use_emergency_malloc); +#else + return false; +#endif +} + +inline void ThreadCache::SetMaxSize(int32 new_max_size) { + max_size_ = new_max_size; +} + +#ifndef NO_TCMALLOC_SAMPLES + +inline bool ThreadCache::SampleAllocation(size_t k) { + return !sampler_.RecordAllocation(k); +} + +inline bool ThreadCache::TryRecordAllocationFast(size_t k) { + return sampler_.TryRecordAllocationFast(k); +} + +#else + +inline bool ThreadCache::SampleAllocation(size_t k) { + return false; +} + +inline bool ThreadCache::TryRecordAllocationFast(size_t k) { + return true; +} + +#endif + +} // namespace tcmalloc + +#endif // TCMALLOC_THREAD_CACHE_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/TODO b/trunk/3rdparty/gperftools-2-fit/src/windows/TODO new file mode 100644 index 000000000..708ec237a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/TODO @@ -0,0 +1,86 @@ +* Get heap-profile-table.cc using DeleteMatchingFiles +* Get heap-profile-table.cc using FillProcSelfMaps, DumpProcSelfMaps +* 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/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) + +---- +More info on windows-level memory-allocation functions: + C runtime malloc + LocalAlloc + GlobalAlloc + HeapAlloc + VirtualAlloc + mmap stuff + +malloc, LocalAlloc and GlobalAlloc call HeapAlloc, which calls +VirtualAlloc when needed, which calls VirtualAllocEx (the __sbrk equiv?) + +siggi sez: If you want to do a generic job, you probably need to +preserve the semantics of all of these Win32 calls: + Heap32First + Heap32ListFirst + Heap32ListNext + Heap32Next + HeapAlloc + HeapCompact + HeapCreate + HeapCreateTagsW + HeapDestroy + HeapExtend + HeapFree + HeapLock + HeapQueryInformation + HeapQueryTagW + HeapReAlloc + HeapSetInformation + HeapSize + HeapSummary + HeapUnlock + HeapUsage + HeapValidate + HeapWalk + +kernel32.dll export functions and nt.dll export functions: + http://www.shorthike.com/svn/trunk/tools_win32/dm/lib/kernel32.def + http://undocumented.ntinternals.net/ + +You can edit the executable IAT to have the patching DLL be the +first one loaded. + +Most complete way to intercept system calls is patch the functions +(not the IAT). + +Microsoft has somee built-in routines for heap-checking: + 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/ +2) Alt-F7 -> C/C++ -> Code Generation -> Runtime Library -> Multi-threaded, debug/release, DLL or not + +--- For DLL: +3) Alt-F7 -> Linker -> Input -> [pulldown "all configurations" ] -> Module Definition File -> src\windows\vc7and8.def +--- For binaries depending on a DLL: +3) Right-click on project -> Project Dependencies -> [add dll] +--- For static binaries (not depending on a DLL) +3) Alt-F7 -> C/C++ -> Command Line -> [pulldown "all configurations"] -> /D PERFTOOLS_DLL_DECL= diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/addr2line-pdb.c b/trunk/3rdparty/gperftools-2-fit/src/windows/addr2line-pdb.c new file mode 100644 index 000000000..88d207bbe --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/addr2line-pdb.c @@ -0,0 +1,183 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2008, 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: David Vitek + * + * Dump function addresses using Microsoft debug symbols. This works + * on PDB files. Note that this program will download symbols to + * c:\websymbols without asking. + */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include + +#include +#include + +#define SEARCH_CAP (1024*1024) +#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols" + +void usage() { + fprintf(stderr, "usage: addr2line-pdb " + "[-f|--functions] [-C|--demangle] [-e|--exe filename]\n"); + fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n"); +} + +int main(int argc, char *argv[]) { + DWORD error; + HANDLE process; + ULONG64 module_base; + int i; + char* search; + char buf[256]; /* Enough to hold one hex address, I trust! */ + int rv = 0; + /* We may add SYMOPT_UNDNAME if --demangle is specified: */ + DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; + char* filename = "a.out"; /* The default if -e isn't specified */ + int print_function_name = 0; /* Set to 1 if -f is specified */ + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { + print_function_name = 1; + } else if (strcmp(argv[i], "--demangle") == 0 || + strcmp(argv[i], "-C") == 0) { + symopts |= SYMOPT_UNDNAME; + } else if (strcmp(argv[i], "--exe") == 0 || + strcmp(argv[i], "-e") == 0) { + if (i + 1 >= argc) { + fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); + return 1; + } + filename = argv[i+1]; + i++; /* to skip over filename too */ + } else if (strcmp(argv[i], "--help") == 0) { + usage(); + exit(0); + } else { + usage(); + exit(1); + } + } + + process = GetCurrentProcess(); + + if (!SymInitialize(process, NULL, FALSE)) { + error = GetLastError(); + fprintf(stderr, "SymInitialize returned error : %lu\n", error); + return 1; + } + + search = malloc(SEARCH_CAP); + if (SymGetSearchPath(process, search, SEARCH_CAP)) { + if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { + fprintf(stderr, "Search path too long\n"); + SymCleanup(process); + return 1; + } + strcat(search, ";" WEBSYM); + } else { + error = GetLastError(); + fprintf(stderr, "SymGetSearchPath returned error : %lu\n", error); + rv = 1; /* An error, but not a fatal one */ + strcpy(search, WEBSYM); /* Use a default value */ + } + if (!SymSetSearchPath(process, search)) { + error = GetLastError(); + fprintf(stderr, "SymSetSearchPath returned error : %lu\n", error); + rv = 1; /* An error, but not a fatal one */ + } + + SymSetOptions(symopts); + module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); + if (!module_base) { + /* SymLoadModuleEx failed */ + error = GetLastError(); + fprintf(stderr, "SymLoadModuleEx returned error : %lu for %s\n", + error, filename); + SymCleanup(process); + return 1; + } + + buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ + while (fgets(buf, sizeof(buf)-1, stdin)) { + /* GNU addr2line seems to just do a strtol and ignore any + * weird characters it gets, so we will too. + */ + unsigned __int64 reladdr = _strtoui64(buf, NULL, 16); + ULONG64 buffer[(sizeof(SYMBOL_INFO) + + MAX_SYM_NAME*sizeof(TCHAR) + + sizeof(ULONG64) - 1) + / sizeof(ULONG64)]; + memset(buffer, 0, sizeof(buffer)); + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + IMAGEHLP_LINE64 line; + DWORD dummy; + + // Just ignore overflow. In an overflow scenario, the resulting address + // will be lower than module_base which hasn't been mapped by any prior + // SymLoadModuleEx() command. This will cause SymFromAddr() and + // SymGetLineFromAddr64() both to return failures and print the correct + // ?? and ??:0 message variant. + ULONG64 absaddr = reladdr + module_base; + + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + // The length of the name is not including the null-terminating character. + pSymbol->MaxNameLen = MAX_SYM_NAME - 1; + if (print_function_name) { + if (SymFromAddr(process, (DWORD64)absaddr, NULL, pSymbol)) { + printf("%s\n", pSymbol->Name); + } else { + printf("??\n"); + } + } + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + if (SymGetLineFromAddr64(process, (DWORD64)absaddr, &dummy, &line)) { + printf("%s:%d\n", line.FileName, (int)line.LineNumber); + } else { + printf("??:0\n"); + } + } + SymUnloadModule64(process, module_base); + SymCleanup(process); + return rv; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/auto_testing_hook.h b/trunk/3rdparty/gperftools-2-fit/src/windows/auto_testing_hook.h new file mode 100644 index 000000000..fc2b71013 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/auto_testing_hook.h @@ -0,0 +1,156 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2010 The Chromium Authors. 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. +// +// Utility for using SideStep with unit tests. + +#ifndef CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_ +#define CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_ + +#include "base/basictypes.h" +#include "base/logging.h" +#include "preamble_patcher.h" + +#define SIDESTEP_CHK(x) CHECK(x) +#define SIDESTEP_EXPECT_TRUE(x) SIDESTEP_CHK(x) + +namespace sidestep { + +// Same trick as common/scope_cleanup.h ScopeGuardImplBase +class AutoTestingHookBase { + public: + virtual ~AutoTestingHookBase() {} +}; + +// This is the typedef you normally use for the class, e.g. +// +// AutoTestingHook hook = MakeTestingHook(TargetFunc, HookTargetFunc); +// +// The 'hook' variable will then be destroyed when it goes out of scope. +// +// NOTE: You must not hold this type as a member of another class. Its +// destructor will not get called. +typedef const AutoTestingHookBase& AutoTestingHook; + +// This is the class you must use when holding a hook as a member of another +// class, e.g. +// +// public: +// AutoTestingHookHolder holder_; +// MyClass() : my_hook_holder(MakeTestingHookHolder(Target, Hook)) {} +class AutoTestingHookHolder { + public: + explicit AutoTestingHookHolder(AutoTestingHookBase* hook) : hook_(hook) {} + ~AutoTestingHookHolder() { delete hook_; } + private: + AutoTestingHookHolder() {} // disallow + AutoTestingHookBase* hook_; +}; + +// This class helps patch a function, then unpatch it when the object exits +// scope, and also maintains the pointer to the original function stub. +// +// To enable use of the class without having to explicitly provide the +// type of the function pointers (and instead only providing it +// implicitly) we use the same trick as ScopeGuard (see +// common/scope_cleanup.h) uses, so to create a hook you use the MakeHook +// function rather than a constructor. +// +// NOTE: This function is only safe for e.g. unit tests and _not_ for +// production code. See PreamblePatcher class for details. +template +class AutoTestingHookImpl : public AutoTestingHookBase { + public: + static AutoTestingHookImpl MakeTestingHook(T target_function, + T replacement_function, + bool do_it) { + return AutoTestingHookImpl(target_function, replacement_function, do_it); + } + + static AutoTestingHookImpl* MakeTestingHookHolder(T target_function, + T replacement_function, + bool do_it) { + return new AutoTestingHookImpl(target_function, + replacement_function, do_it); + } + + ~AutoTestingHookImpl() { + if (did_it_) { + SIDESTEP_CHK(SIDESTEP_SUCCESS == PreamblePatcher::Unpatch( + (void*)target_function_, (void*)replacement_function_, + (void*)original_function_)); + } + } + + // Returns a pointer to the original function. To use this method you will + // have to explicitly create an AutoTestingHookImpl of the specific + // function pointer type (i.e. not use the AutoTestingHook typedef). + T original_function() { + return original_function_; + } + + private: + AutoTestingHookImpl(T target_function, T replacement_function, bool do_it) + : target_function_(target_function), + original_function_(NULL), + replacement_function_(replacement_function), + did_it_(do_it) { + if (do_it) { + SIDESTEP_CHK(SIDESTEP_SUCCESS == PreamblePatcher::Patch(target_function, + replacement_function, + &original_function_)); + } + } + + T target_function_; // always valid + T original_function_; // always valid + T replacement_function_; // always valid + bool did_it_; // Remember if we did it or not... +}; + +template +inline AutoTestingHookImpl MakeTestingHook(T target, + T replacement, + bool do_it) { + return AutoTestingHookImpl::MakeTestingHook(target, replacement, do_it); +} + +template +inline AutoTestingHookImpl MakeTestingHook(T target, T replacement) { + return AutoTestingHookImpl::MakeTestingHook(target, replacement, true); +} + +template +inline AutoTestingHookImpl* MakeTestingHookHolder(T target, T replacement) { + return AutoTestingHookImpl::MakeTestingHookHolder(target, replacement, + true); +} + +}; // namespace sidestep + +#endif // CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/config.h b/trunk/3rdparty/gperftools-2-fit/src/windows/config.h new file mode 100644 index 000000000..bd520e4c6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/config.h @@ -0,0 +1,306 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* A manual version of config.h fit for windows machines. + * + * Use of this source code is governed by a BSD-style license that can + * be found in the LICENSE file. + */ + +/* Sometimes we accidentally #include this config.h instead of the one + in .. -- this is particularly true for msys/mingw, which uses the + unix config.h but also runs code in the windows directory. + */ +#ifdef __MINGW32__ +#include "../config.h" +#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ +#endif + +#ifndef GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ +#define GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ +/* used by tcmalloc.h */ +#define GPERFTOOLS_CONFIG_H_ + +/* Enable aggressive decommit by default */ +/* #undef ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT */ + +/* Build new/delete operators for overaligned types */ +/* #undef ENABLE_ALIGNED_NEW_DELETE */ + +/* Build runtime detection for sized delete */ +/* #undef ENABLE_DYNAMIC_SIZED_DELETE */ + +/* Report large allocation */ +/* #undef ENABLE_LARGE_ALLOC_REPORT */ + +/* Build sized deletion operators */ +/* #undef ENABLE_SIZED_DELETE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_PTRACE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CYGWIN_SIGNAL_H */ + +/* Define to 1 if you have the declaration of `backtrace', and to 0 if you + don't. */ +/* #undef HAVE_DECL_BACKTRACE */ + +/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't. + */ +#define HAVE_DECL_CFREE 0 + +/* Define to 1 if you have the declaration of `memalign', and to 0 if you + don't. */ +#define HAVE_DECL_MEMALIGN 0 + +/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you + don't. */ +#define HAVE_DECL_NANOSLEEP 0 + +/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if + you don't. */ +#define HAVE_DECL_POSIX_MEMALIGN 0 + +/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you + don't. */ +#define HAVE_DECL_PVALLOC 0 + +/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't. + */ +#define HAVE_DECL_SLEEP 0 + +/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't. + */ +#define HAVE_DECL_VALLOC 0 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if the system has the type `Elf32_Versym'. */ +/* #undef HAVE_ELF32_VERSYM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXECINFO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FEATURES_H */ + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GLOB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GRP_H */ + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && _MSC_VER >= 1900 +#define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUNWIND_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_PTRACE_H */ + +/* Define if this is Linux that has SIGEV_THREAD_ID */ +/* #undef HAVE_LINUX_SIGEV_THREAD_ID */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have a working `mmap' system call. */ +/* #undef HAVE_MMAP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_POLL_H */ + +/* define if libc has program_invocation_name */ +/* #undef HAVE_PROGRAM_INVOCATION_NAME */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef HAVE_PTHREAD */ + +/* defined to 1 if pthread symbols are exposed even without include pthread.h + */ +/* #undef HAVE_PTHREAD_DESPITE_ASKING_FOR */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `sbrk' function. */ +/* #undef HAVE_SBRK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SCHED_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if the system has the type `struct mallinfo'. */ +/* #undef HAVE_STRUCT_MALLINFO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_CDEFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PRCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SYSCALL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UCONTEXT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define to 1 if compiler supports __thread */ +#define HAVE_TLS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UCONTEXT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Whether contains _Unwind_Backtrace */ +/* #undef HAVE_UNWIND_BACKTRACE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UNWIND_H */ + +/* define if your compiler has __attribute__ */ +/* #undef HAVE___ATTRIBUTE__ */ + +/* define if your compiler supports alignment of functions */ +/* #undef HAVE___ATTRIBUTE__ALIGNED_FN */ + +/* Define to 1 if compiler supports __environ */ +/* #undef HAVE___ENVIRON */ + +/* Define to 1 if you have the `__sbrk' function. */ +/* #undef HAVE___SBRK */ + +/* prefix where we look for installed files */ +/* #undef INSTALL_PREFIX */ + +/* Define to 1 if int32_t is equivalent to intptr_t */ +#ifndef _WIN64 +#define INT32_EQUALS_INTPTR 1 +#endif + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +/* #undef LT_OBJDIR */ + +/* Name of package */ +#define PACKAGE "gperftools" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "gperftools@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "gperftools" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "gperftools 2.9.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "gperftools" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.9.1" + +/* 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. */ +#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 + +/* Mark the systems where we know it's bad if pthreads runs too + early before main (before threads are initialized, presumably). */ +#ifdef __FreeBSD__ +#define PTHREADS_CRASHES_IF_RUN_TOO_EARLY 1 +#endif + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define 8 bytes of allocation alignment for tcmalloc */ +/* #undef TCMALLOC_ALIGN_8BYTES */ + +/* Define internal page size for tcmalloc as number of left bitshift */ +/* #undef TCMALLOC_PAGE_SIZE_SHIFT */ + +/* Version number of package */ +#define VERSION "2.9.1" + +/* C99 says: define this to get the PRI... macros from stdint.h */ +#ifndef __STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS 1 +#endif + +// --------------------------------------------------------------------- +// Extra stuff not found in config.h.in + +// This must be defined before the windows.h is included. We need at +// least 0x0400 for mutex.h to have access to TryLock, and at least +// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx. +// (This latter is an optimization we could take out if need be.) +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +#endif + +// We want to make sure not to ever try to #include heap-checker.h +#define NO_HEAP_CHECK 1 + +// TODO(csilvers): include windows/port.h in every relevant source file instead? +#include "windows/port.h" + +#endif /* GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/get_mangled_names.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/get_mangled_names.cc new file mode 100644 index 000000000..fd6424be6 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/get_mangled_names.cc @@ -0,0 +1,65 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2008, 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 (opensource@google.com) + +// When you are porting perftools to a new compiler or architecture +// (win64 vs win32) for instance, you'll need to change the mangled +// symbol names for operator new and friends at the top of +// patch_functions.cc. This file helps you do that. +// +// It does this by defining these functions with the proper signature. +// All you need to do is compile this file and the run dumpbin on it. +// (See http://msdn.microsoft.com/en-us/library/5x49w699.aspx for more +// on dumpbin). To do this in MSVC, use the MSVC commandline shell: +// http://msdn.microsoft.com/en-us/library/ms235639(VS.80).aspx) +// +// The run: +// cl /c get_mangled_names.cc +// dumpbin /symbols get_mangled_names.obj +// +// It will print out the mangled (and associated unmangled) names of +// the 8 symbols you need to put at the top of patch_functions.cc + +#include // for size_t +#include // for nothrow_t + +static char m; // some dummy memory so new doesn't return NULL. + +void* operator new(size_t size) { return &m; } +void operator delete(void* p) throw() { } +void* operator new[](size_t size) { return &m; } +void operator delete[](void* p) throw() { } + +void* operator new(size_t size, const std::nothrow_t&) throw() { return &m; } +void operator delete(void* p, const std::nothrow_t&) throw() { } +void* operator new[](size_t size, const std::nothrow_t&) throw() { return &m; } +void operator delete[](void* p, const std::nothrow_t&) throw() { } diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h b/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h new file mode 100644 index 000000000..5116b29f2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h @@ -0,0 +1,155 @@ +// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2003, 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: Sanjay Ghemawat + * .h file by Craig Silverstein + */ + +#ifndef TCMALLOC_TCMALLOC_H_ +#define TCMALLOC_TCMALLOC_H_ + +#include /* for size_t */ +#ifdef __cplusplus +#include /* for std::nothrow_t, std::align_val_t */ +#endif + +/* Define the version number so folks can check against it */ +#define TC_VERSION_MAJOR 2 +#define TC_VERSION_MINOR 9 +#define TC_VERSION_PATCH ".1" +#define TC_VERSION_STRING "gperftools 2.9.1" + +#ifndef PERFTOOLS_NOTHROW + +#if __cplusplus >= 201103L +#define PERFTOOLS_NOTHROW noexcept +#elif defined(__cplusplus) +#define PERFTOOLS_NOTHROW throw() +#else +# ifdef __GNUC__ +# define PERFTOOLS_NOTHROW __attribute__((__nothrow__)) +# else +# define PERFTOOLS_NOTHROW +# endif +#endif + +#endif + +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /* + * Returns a human-readable version string. If major, minor, + * and/or patch are not NULL, they are set to the major version, + * minor version, and patch-code (a string, usually ""). + */ + PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor, + const char** patch) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment, + size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr, + size_t align, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW; + + /* + * This is an alias for MallocExtension::instance()->GetAllocatedSize(). + * It is equivalent to + * OS X: malloc_size() + * glibc: malloc_usable_size() + * Windows: _msize() + */ + PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW; + +#ifdef __cplusplus + PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_new(size_t size); + PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray(size_t size); + PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + +#if defined(__cpp_aligned_new) || (defined(_MSVC_LANG) && _MSVC_LANG > 201402L) + PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; +#endif +} +#endif + +/* We're only un-defining for public */ +#if !defined(GPERFTOOLS_CONFIG_H_) + +#undef PERFTOOLS_NOTHROW + +#endif /* GPERFTOOLS_CONFIG_H_ */ + +#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h.in b/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h.in new file mode 100644 index 000000000..adb79629e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/gperftools/tcmalloc.h.in @@ -0,0 +1,155 @@ +// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2003, 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: Sanjay Ghemawat + * .h file by Craig Silverstein + */ + +#ifndef TCMALLOC_TCMALLOC_H_ +#define TCMALLOC_TCMALLOC_H_ + +#include /* for size_t */ +#ifdef __cplusplus +#include /* for std::nothrow_t, std::align_val_t */ +#endif + +/* Define the version number so folks can check against it */ +#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@ +#define TC_VERSION_MINOR @TC_VERSION_MINOR@ +#define TC_VERSION_PATCH "@TC_VERSION_PATCH@" +#define TC_VERSION_STRING "gperftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@" + +#ifndef PERFTOOLS_NOTHROW + +#if __cplusplus >= 201103L +#define PERFTOOLS_NOTHROW noexcept +#elif defined(__cplusplus) +#define PERFTOOLS_NOTHROW throw() +#else +# ifdef __GNUC__ +# define PERFTOOLS_NOTHROW __attribute__((__nothrow__)) +# else +# define PERFTOOLS_NOTHROW +# endif +#endif + +#endif + +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /* + * Returns a human-readable version string. If major, minor, + * and/or patch are not NULL, they are set to the major version, + * minor version, and patch-code (a string, usually ""). + */ + PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor, + const char** patch) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment, + size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr, + size_t align, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW; + + /* + * This is an alias for MallocExtension::instance()->GetAllocatedSize(). + * It is equivalent to + * OS X: malloc_size() + * glibc: malloc_usable_size() + * Windows: _msize() + */ + PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW; + +#ifdef __cplusplus + PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_new(size_t size); + PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray(size_t size); + PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + +#if defined(__cpp_aligned_new) || (defined(_MSVC_LANG) && _MSVC_LANG > 201402L) + PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; +#endif +} +#endif + +/* We're only un-defining for public */ +#if !defined(GPERFTOOLS_CONFIG_H_) + +#undef PERFTOOLS_NOTHROW + +#endif /* GPERFTOOLS_CONFIG_H_ */ + +#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_modrm_map.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_modrm_map.cc new file mode 100644 index 000000000..817ac438b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_modrm_map.cc @@ -0,0 +1,122 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_opcode_map.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_opcode_map.cc new file mode 100644 index 000000000..9d54f6b1c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/ia32_opcode_map.cc @@ -0,0 +1,1220 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 } }, +#ifdef _M_X64 + /* REX Prefixes in 64-bit mode. */ + /* 0x40 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x41 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x42 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x43 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x44 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x45 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x46 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x47 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x48 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x49 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4A */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4B */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4C */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4D */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0x4F */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, +#else + /* 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 } }, +#endif + /* 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 } }, +#ifdef _M_X64 + /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, + /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V | IOS_64, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, +#else + /* 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 } }, +#endif + /* 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/trunk/3rdparty/gperftools-2-fit/src/windows/mingw.h b/trunk/3rdparty/gperftools-2-fit/src/windows/mingw.h new file mode 100644 index 000000000..542f9ae19 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/mingw.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* 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: Craig Silverstein + * + * MinGW is an interesting mix of unix and windows. We use a normal + * configure script, but still need the windows port.h to define some + * stuff that MinGW doesn't support, like pthreads. + */ + +#ifndef GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ +#define GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ + +#ifdef __MINGW32__ + +// Older version of the mingw msvcrt don't define _aligned_malloc +#if __MSVCRT_VERSION__ < 0x0700 +# define PERFTOOLS_NO_ALIGNED_MALLOC 1 +#endif + +// This must be defined before the windows.h is included. We need at +// least 0x0400 for mutex.h to have access to TryLock, and at least +// 0x0501 for patch_functions.cc to have access to GetModuleHandleEx. +// (This latter is an optimization we could take out if need be.) +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0501 +#endif + +// Some mingw distributions have a pthreads wrapper, but it doesn't +// work as well as native windows spinlocks (at least for us). So +// pretend the pthreads wrapper doesn't exist, even when it does. +#ifndef HAVE_PTHREAD_DESPITE_ASKING_FOR +#undef HAVE_PTHREAD +#endif + +#undef HAVE_FORK + +#define HAVE_PID_T + +#include "windows/port.h" + +#endif /* __MINGW32__ */ + +#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.cc new file mode 100644 index 000000000..35d7a9d5f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.cc @@ -0,0 +1,432 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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( + unsigned char* start_byte, + unsigned int& instruction_bytes) { + // Clean up any state from previous invocations. + Initialize(); + + // Start by processing any prefixes. + unsigned char* 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_; +#ifdef _M_X64 + operand_default_support_64_bits_ = true; +#else + operand_default_support_64_bits_ = false; +#endif + operand_is_64_bits_ = false; + 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(unsigned char* 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; + else if (operand_default_support_64_bits_ && (*start_byte) & 0x48) + operand_is_64_bits_ = 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(unsigned char* start_byte, + unsigned int table_index, + unsigned int& size) { + const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table + unsigned char 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, doubleword or quadword, depending on operand-size + // attribute. + if (operand_is_64_bits_ && flag_operand & AM_I && + flag_operand & IOS_64) + operand_bytes_ += OS_QUAD_WORD; + else 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(unsigned char* 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. + unsigned char modrm = (*start_byte); + unsigned char 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(unsigned char* start_byte, + unsigned char mod, + unsigned int& size) { + // get the mod field from the 2..0 bits of the SIB byte + unsigned char 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/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.h b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.h new file mode 100644 index 000000000..8b3e4ba17 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler.h @@ -0,0 +1,198 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 "config.h" +#include +#include "mini_disassembler_types.h" + +// compatibility shim +#include "base/logging.h" +#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) +#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) + +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 PERFTOOLS_DLL_DECL 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 incremented 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(unsigned char* 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(unsigned char* 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(unsigned char* 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(unsigned char* 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(unsigned char* start, unsigned char 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_; + + // Determines if 64 bit operands are supported (x64). + bool operand_default_support_64_bits_; + + // Current operand size is 64 bits if true, 32 bits if false. + bool operand_is_64_bits_; + + // Huge big opcode table based on the IA-32 manual, defined + // in Ia32OpcodeMap.cc + 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.cc + 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.cc + 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/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler_types.h b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler_types.h new file mode 100644 index 000000000..97da92db3 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/mini_disassembler_types.h @@ -0,0 +1,237 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 +}; + +// Flag that indicates if an immediate operand is 64-bits. +// +// The Intel 64 and IA-32 Architecture Software Developer's Manual currently +// defines MOV as the only instruction supporting a 64-bit immediate operand. +enum ImmediateOperandSize { + IOS_MASK = 0x0000F000, + IOS_DEFAULT = 0x0, + IOS_64 = 0x00001000 +}; + +// 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 enOperandType, enAddressingMethod and + // enImmediateOperandSize flags. + 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. + unsigned flag_dest_; + unsigned flag_source_; + unsigned 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 before 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/trunk/3rdparty/gperftools-2-fit/src/windows/nm-pdb.c b/trunk/3rdparty/gperftools-2-fit/src/windows/nm-pdb.c new file mode 100644 index 000000000..9f6f43107 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/nm-pdb.c @@ -0,0 +1,274 @@ +/* -*- Mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2008, 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: David Vitek + * + * Dump function addresses using Microsoft debug symbols. This works + * on PDB files. Note that this program will download symbols to + * c:\websymbols without asking. + */ + +#define WIN32_LEAN_AND_MEAN +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include +#include // for _strdup + +#include +#include + +// Unfortunately, there is no versioning info in dbghelp.h so I can +// tell whether it has an old-style (circa VC7.1) IMAGEHLP_MODULE64 +// struct, with only a few fields, or a new-style (circa VC8) +// IMAGEHLP_MODULE64, with lots of fields. These fields are just used +// for debugging, so it's fine to just assume the smaller struct, but +// for most people, using a modern MSVC, the full struct is available. +// If you are one of those people and would like this extra debugging +// info, you can uncomment the line below. +//#define VC8_OR_ABOVE + +#define SEARCH_CAP (1024*1024) +#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols" + +typedef struct { + char *name; + ULONG64 addr; + ULONG flags; +} SYM; + +typedef struct { + ULONG64 module_base; + SYM *syms; + DWORD syms_len; + DWORD syms_cap; +} SYM_CONTEXT; + +static int sym_cmp(const void *_s1, const void *_s2) { + const SYM *s1 = (const SYM *)_s1; + const SYM *s2 = (const SYM *)_s2; + + if (s1->addr < s2->addr) + return -1; + if (s1->addr > s2->addr) + return 1; + return 0; +} + +static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO symbol_info, + ULONG symbol_size, + PVOID user_context) { + SYM_CONTEXT *ctx = (SYM_CONTEXT*)user_context; + if (symbol_info->Address < ctx->module_base || + (symbol_info->Flags & SYMFLAG_TLSREL)) { + return TRUE; + } + if (ctx->syms_len == ctx->syms_cap) { + if (!ctx->syms_cap) + ctx->syms_cap++; + ctx->syms_cap *= 2; + ctx->syms = realloc(ctx->syms, sizeof(ctx->syms[0]) * ctx->syms_cap); + } + ctx->syms[ctx->syms_len].name = _strdup(symbol_info->Name); + ctx->syms[ctx->syms_len].addr = symbol_info->Address; + ctx->syms[ctx->syms_len].flags = symbol_info->Flags; + ctx->syms_len++; + return TRUE; +} + +static void MaybePrint(const char* var, const char* description) { + if (var[0]) + printf("%s: %s\n", description, var); +} + +static void PrintAvailability(BOOL var, const char *description) { + printf("%s: %s\n", description, (var ? "Available" : "Not available")); +} + +static void ShowSymbolInfo(HANDLE process, ULONG64 module_base) { + /* Get module information. */ + IMAGEHLP_MODULE64 module_info; + BOOL getmoduleinfo_rv; + printf("Load Address: %I64x\n", module_base); + memset(&module_info, 0, sizeof(module_info)); + module_info.SizeOfStruct = sizeof(module_info); + getmoduleinfo_rv = SymGetModuleInfo64(process, module_base, &module_info); + if (!getmoduleinfo_rv) { + printf("Error: SymGetModuleInfo64() failed. Error code: %u\n", + GetLastError()); + return; + } + /* Display information about symbols, based on kind of symbol. */ + switch (module_info.SymType) { + case SymNone: + printf(("No symbols available for the module.\n")); + break; + case SymExport: + printf(("Loaded symbols: Exports\n")); + break; + case SymCoff: + printf(("Loaded symbols: COFF\n")); + break; + case SymCv: + printf(("Loaded symbols: CodeView\n")); + break; + case SymSym: + printf(("Loaded symbols: SYM\n")); + break; + case SymVirtual: + printf(("Loaded symbols: Virtual\n")); + break; + case SymPdb: + printf(("Loaded symbols: PDB\n")); + break; + case SymDia: + printf(("Loaded symbols: DIA\n")); + break; + case SymDeferred: + printf(("Loaded symbols: Deferred\n")); /* not actually loaded */ + break; + default: + printf(("Loaded symbols: Unknown format.\n")); + break; + } + + MaybePrint("Image name", module_info.ImageName); + MaybePrint("Loaded image name", module_info.LoadedImageName); +#ifdef VC8_OR_ABOVE /* TODO(csilvers): figure out how to tell */ + MaybePrint("PDB file name", module_info.LoadedPdbName); + if (module_info.PdbUnmatched || module_info.DbgUnmatched) { + /* This can only happen if the debug information is contained in a + * separate file (.DBG or .PDB) + */ + printf(("Warning: Unmatched symbols.\n")); + } +#endif + + /* Contents */ +#ifdef VC8_OR_ABOVE /* TODO(csilvers): figure out how to tell */ + PrintAvailability("Line numbers", module_info.LineNumbers); + PrintAvailability("Global symbols", module_info.GlobalSymbols); + PrintAvailability("Type information", module_info.TypeInfo); +#endif +} + +void usage() { + fprintf(stderr, "usage: nm-pdb [-C|--demangle] \n"); +} + +int main(int argc, char *argv[]) { + DWORD error; + HANDLE process; + ULONG64 module_base; + SYM_CONTEXT ctx; + int i; + char* search; + char* filename = NULL; + int rv = 0; + /* We may add SYMOPT_UNDNAME if --demangle is specified: */ + DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) { + symopts |= SYMOPT_UNDNAME; + } else if (strcmp(argv[i], "--help") == 0) { + usage(); + exit(0); + } else { + break; + } + } + if (i != argc - 1) { + usage(); + exit(1); + } + filename = argv[i]; + + process = GetCurrentProcess(); + + if (!SymInitialize(process, NULL, FALSE)) { + error = GetLastError(); + fprintf(stderr, "SymInitialize returned error : %d\n", error); + return 1; + } + + search = malloc(SEARCH_CAP); + if (SymGetSearchPath(process, search, SEARCH_CAP)) { + if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { + fprintf(stderr, "Search path too long\n"); + SymCleanup(process); + return 1; + } + strcat(search, ";" WEBSYM); + } else { + error = GetLastError(); + fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); + rv = 1; /* An error, but not a fatal one */ + strcpy(search, WEBSYM); /* Use a default value */ + } + if (!SymSetSearchPath(process, search)) { + error = GetLastError(); + fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); + rv = 1; /* An error, but not a fatal one */ + } + + SymSetOptions(symopts); + module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); + if (!module_base) { + /* SymLoadModuleEx failed */ + error = GetLastError(); + fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", + error, filename); + SymCleanup(process); + return 1; + } + + ShowSymbolInfo(process, module_base); + + memset(&ctx, 0, sizeof(ctx)); + ctx.module_base = module_base; + if (!SymEnumSymbols(process, module_base, NULL, EnumSymProc, &ctx)) { + error = GetLastError(); + fprintf(stderr, "SymEnumSymbols returned error: %d\n", error); + rv = 1; + } else { + DWORD j; + qsort(ctx.syms, ctx.syms_len, sizeof(ctx.syms[0]), sym_cmp); + for (j = 0; j < ctx.syms_len; j++) { + printf("%016I64x X %s\n", ctx.syms[j].addr, ctx.syms[j].name); + } + /* In a perfect world, maybe we'd clean up ctx's memory? */ + } + SymUnloadModule64(process, module_base); + SymCleanup(process); + return rv; +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/override_functions.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/override_functions.cc new file mode 100644 index 000000000..8afb85102 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/override_functions.cc @@ -0,0 +1,173 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Mike Belshe +// +// To link tcmalloc into a EXE or DLL statically without using the patching +// facility, we can take a stock libcmt and remove all the allocator functions. +// When we relink the EXE/DLL with the modified libcmt and tcmalloc, a few +// functions are missing. This file contains the additional overrides which +// are required in the VS2005 libcmt in order to link the modified libcmt. +// +// See also +// http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b + +#include + +#ifndef _WIN32 +# error You should only be including this file in a windows environment! +#endif + +#ifndef WIN32_OVERRIDE_ALLOCATORS +# error This file is intended for use when overriding allocators +#endif + +#include "tcmalloc.cc" + +extern "C" { + +void* _malloc_base(size_t size) { + return malloc(size); +} + +void _free_base(void* p) { + free(p); +} + +void* _calloc_base(size_t n, size_t size) { + return calloc(n, size); +} + +void* _recalloc(void* old_ptr, size_t n, size_t size) { + // Ensure that (n * size) does not overflow + if (!(n == 0 || (std::numeric_limits::max)() / n >= size)) { + errno = ENOMEM; + return NULL; + } + + const size_t old_size = tc_malloc_size(old_ptr); + const size_t new_size = n * size; + + void* new_ptr = realloc(old_ptr, new_size); + + // If the reallocation succeeded and the new block is larger, zero-fill the + // new bytes: + if (new_ptr != NULL && new_size > old_size) { + memset(static_cast(new_ptr) + old_size, 0, tc_nallocx(new_size, 0) - old_size); + } + + return new_ptr; +} + +void* _calloc_impl(size_t n, size_t size) { + return calloc(n, size); +} + +size_t _msize(void* p) { + return MallocExtension::instance()->GetAllocatedSize(p); +} + +HANDLE __acrt_heap = nullptr; + +bool __acrt_initialize_heap() { + new TCMallocGuard(); + return true; +} + +bool __acrt_uninitialize_heap(bool) { + return true; +} + +intptr_t _get_heap_handle() { + return 0; +} + +HANDLE __acrt_getheap() { + return __acrt_heap; +} + +// The CRT heap initialization stub. +int _heap_init() { + // We intentionally leak this object. It lasts for the process + // lifetime. Trying to teardown at _heap_term() is so late that + // you can't do anything useful anyway. + new TCMallocGuard(); + return 1; +} + +// The CRT heap cleanup stub. +void _heap_term() { +} + +// We set this to 1 because part of the CRT uses a check of _crtheap != 0 +// to test whether the CRT has been initialized. Once we've ripped out +// the allocators from libcmt, we need to provide this definition so that +// the rest of the CRT is still usable. +void* _crtheap = reinterpret_cast(1); + +int _set_new_mode(int flag) { + return tc_set_new_mode(flag); +} + +int _query_new_mode() { + return tc_query_new_mode(); +} + +} // extern "C" + +#ifndef NDEBUG +#undef malloc +#undef free +#undef calloc +int _CrtDbgReport(int, const char*, int, const char*, const char*, ...) { + return 0; +} + +int _CrtDbgReportW(int, const wchar_t*, int, const wchar_t*, const wchar_t*, ...) { + return 0; +} + +int _CrtSetReportMode(int, int) { + return 0; +} + +extern "C" void* _malloc_dbg(size_t size, int , const char*, int) { + return malloc(size); +} + +extern "C" void _free_dbg(void* ptr, int) { + free(ptr); +} + +extern "C" void* _calloc_dbg(size_t n, size_t size, int, const char*, int) { + return calloc(n, size); +} +#endif // NDEBUG diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/patch_functions.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/patch_functions.cc new file mode 100644 index 000000000..a2d0a0365 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/patch_functions.cc @@ -0,0 +1,1098 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// 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: Craig Silverstein +// +// The main purpose of this file is to patch the libc allocation +// routines (malloc and friends, but also _msize and other +// windows-specific libc-style routines). However, we also patch +// windows routines to do accounting. We do better at the former than +// the latter. Here are some comments from Paul Pluzhnikov about what +// it might take to do a really good job patching windows routines to +// keep track of memory usage: +// +// "You should intercept at least the following: +// HeapCreate HeapDestroy HeapAlloc HeapReAlloc HeapFree +// RtlCreateHeap RtlDestroyHeap RtlAllocateHeap RtlFreeHeap +// malloc calloc realloc free +// malloc_dbg calloc_dbg realloc_dbg free_dbg +// Some of these call the other ones (but not always), sometimes +// recursively (i.e. HeapCreate may call HeapAlloc on a different +// heap, IIRC)." +// +// Since Paul didn't mention VirtualAllocEx, he may not have even been +// considering all the mmap-like functions that windows has (or he may +// just be ignoring it because he's seen we already patch it). Of the +// above, we do not patch the *_dbg functions, and of the windows +// functions, we only patch HeapAlloc and HeapFree. +// +// The *_dbg functions come into play with /MDd, /MTd, and /MLd, +// probably. It may be ok to just turn off tcmalloc in those cases -- +// if the user wants the windows debug malloc, they probably don't +// want tcmalloc! We should also test with all of /MD, /MT, and /ML, +// which we're not currently doing. + +// TODO(csilvers): try to do better here? Paul does conclude: +// "Keeping track of all of this was a nightmare." + +#ifndef _WIN32 +# error You should only be including windows/patch_functions.cc in a windows environment! +#endif + +#include + +#ifdef WIN32_OVERRIDE_ALLOCATORS +#error This file is intended for patching allocators - use override_functions.cc instead. +#endif + +// We use psapi. Non-MSVC systems will have to link this in themselves. +#ifdef _MSC_VER +#pragma comment(lib, "Psapi.lib") +#endif + +// Make sure we always use the 'old' names of the psapi functions. +#ifndef PSAPI_VERSION +#define PSAPI_VERSION 1 +#endif + +#include +#include +#include // for _msize and _expand +#include // for EnumProcessModules, GetModuleInformation, etc. +#include +#include +#include +#include +#include "base/spinlock.h" +#include "gperftools/malloc_hook.h" +#include "malloc_hook-inl.h" +#include "preamble_patcher.h" + +// The maximum number of modules we allow to be in one executable +const int kMaxModules = 8182; + +// These are hard-coded, unfortunately. :-( They are also probably +// compiler specific. See get_mangled_names.cc, in this directory, +// for instructions on how to update these names for your compiler. +#ifdef _WIN64 +const char kMangledNew[] = "??2@YAPEAX_K@Z"; +const char kMangledNewArray[] = "??_U@YAPEAX_K@Z"; +const char kMangledDelete[] = "??3@YAXPEAX@Z"; +const char kMangledDeleteArray[] = "??_V@YAXPEAX@Z"; +const char kMangledNewNothrow[] = "??2@YAPEAX_KAEBUnothrow_t@std@@@Z"; +const char kMangledNewArrayNothrow[] = "??_U@YAPEAX_KAEBUnothrow_t@std@@@Z"; +const char kMangledDeleteNothrow[] = "??3@YAXPEAXAEBUnothrow_t@std@@@Z"; +const char kMangledDeleteArrayNothrow[] = "??_V@YAXPEAXAEBUnothrow_t@std@@@Z"; +#else +const char kMangledNew[] = "??2@YAPAXI@Z"; +const char kMangledNewArray[] = "??_U@YAPAXI@Z"; +const char kMangledDelete[] = "??3@YAXPAX@Z"; +const char kMangledDeleteArray[] = "??_V@YAXPAX@Z"; +const char kMangledNewNothrow[] = "??2@YAPAXIABUnothrow_t@std@@@Z"; +const char kMangledNewArrayNothrow[] = "??_U@YAPAXIABUnothrow_t@std@@@Z"; +const char kMangledDeleteNothrow[] = "??3@YAXPAXABUnothrow_t@std@@@Z"; +const char kMangledDeleteArrayNothrow[] = "??_V@YAXPAXABUnothrow_t@std@@@Z"; +#endif + +// This is an unused but exported symbol that we can use to tell the +// MSVC linker to bring in libtcmalloc, via the /INCLUDE linker flag. +// Without this, the linker will likely decide that libtcmalloc.dll +// doesn't add anything to the executable (since it does all its work +// through patching, which the linker can't see), and ignore it +// entirely. (The name 'tcmalloc' is already reserved for a +// namespace. I'd rather export a variable named "_tcmalloc", but I +// couldn't figure out how to get that to work. This function exports +// the symbol "__tcmalloc".) +extern "C" PERFTOOLS_DLL_DECL void _tcmalloc(); +void _tcmalloc() { } + +// This is the version needed for windows x64, which has a different +// decoration scheme which doesn't auto-add a leading underscore. +extern "C" PERFTOOLS_DLL_DECL void __tcmalloc(); +void __tcmalloc() { } + +namespace { // most everything here is in an unnamed namespace + +typedef void (*GenericFnPtr)(); + +using sidestep::PreamblePatcher; + +struct ModuleEntryCopy; // defined below + +// These functions are how we override the memory allocation +// functions, just like tcmalloc.cc and malloc_hook.cc do. + +// This is information about the routines we're patching, for a given +// module that implements libc memory routines. A single executable +// can have several libc implementations running about (in different +// .dll's), and we need to patch/unpatch them all. This defines +// everything except the new functions we're patching in, which +// are defined in LibcFunctions, below. +class LibcInfo { + public: + LibcInfo() { + memset(this, 0, sizeof(*this)); // easiest way to initialize the array + } + + bool patched() const { return is_valid(); } + void set_is_valid(bool b) { is_valid_ = b; } + // According to http://msdn.microsoft.com/en-us/library/ms684229(VS.85).aspx: + // "The load address of a module (lpBaseOfDll) is the same as the HMODULE + // value." + HMODULE hmodule() const { + return reinterpret_cast(const_cast(module_base_address_)); + } + + // Populates all the windows_fn_[] vars based on our module info. + // Returns false if windows_fn_ is all NULL's, because there's + // nothing to patch. Also populates the rest of the module_entry + // info, such as the module's name. + bool PopulateWindowsFn(const ModuleEntryCopy& module_entry); + + protected: + void CopyFrom(const LibcInfo& that) { + if (this == &that) + return; + this->is_valid_ = that.is_valid_; + memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_)); + this->module_base_address_ = that.module_base_address_; + this->module_base_size_ = that.module_base_size_; + } + + enum { + kMalloc, kFree, kRealloc, kCalloc, + kNew, kNewArray, kDelete, kDeleteArray, + kNewNothrow, kNewArrayNothrow, kDeleteNothrow, kDeleteArrayNothrow, + // These are windows-only functions from malloc.h + k_Msize, k_Expand, + // A MS CRT "internal" function, implemented using _calloc_impl + k_CallocCrt, + // Underlying deallocation functions called by CRT internal functions or operator delete + kFreeBase, kFreeDbg, + kNumFunctions + }; + + // I'd like to put these together in a struct (perhaps in the + // subclass, so we can put in perftools_fn_ as well), but vc8 seems + // to have a bug where it doesn't initialize the struct properly if + // we try to take the address of a function that's not yet loaded + // from a dll, as is the common case for static_fn_. So we need + // each to be in its own array. :-( + static const char* const function_name_[kNumFunctions]; + + // This function is only used when statically linking the binary. + // In that case, loading malloc/etc from the dll (via + // PatchOneModule) won't work, since there are no dlls. Instead, + // you just want to be taking the address of malloc/etc directly. + // In the common, non-static-link case, these pointers will all be + // NULL, since this initializer runs before msvcrt.dll is loaded. + static const GenericFnPtr static_fn_[kNumFunctions]; + + // This is the address of the function we are going to patch + // (malloc, etc). Other info about the function is in the + // patch-specific subclasses, below. + GenericFnPtr windows_fn_[kNumFunctions]; + + // This is set to true when this structure is initialized (because + // we're patching a new library) and set to false when it's + // uninitialized (because we've freed that library). + bool is_valid_; + + const void *module_base_address_; + size_t module_base_size_; + + public: + // These shouldn't have to be public, since only subclasses of + // LibcInfo need it, but they do. Maybe something to do with + // templates. Shrug. I hide them down here so users won't see + // them. :-) (OK, I also need to define ctrgProcAddress late.) + bool is_valid() const { return is_valid_; } + GenericFnPtr windows_fn(int ifunction) const { + return windows_fn_[ifunction]; + } + // These three are needed by ModuleEntryCopy. + static const int ctrgProcAddress = kNumFunctions; + static GenericFnPtr static_fn(int ifunction) { + return static_fn_[ifunction]; + } + static const char* const function_name(int ifunction) { + return function_name_[ifunction]; + } +}; + +// Template trickiness: logically, a LibcInfo would include +// Windows_malloc_, origstub_malloc_, and Perftools_malloc_: for a +// given module, these three go together. And in fact, +// Perftools_malloc_ may need to call origstub_malloc_, which means we +// either need to change Perftools_malloc_ to take origstub_malloc_ as +// an argument -- unfortunately impossible since it needs to keep the +// same API as normal malloc -- or we need to write a different +// version of Perftools_malloc_ for each LibcInfo instance we create. +// We choose the second route, and use templates to implement it (we +// could have also used macros). So to get multiple versions +// of the struct, we say "struct<1> var1; struct<2> var2;". The price +// we pay is some code duplication, and more annoying, each instance +// of this var is a separate type. +template class LibcInfoWithPatchFunctions : public LibcInfo { + public: + // me_info should have had PopulateWindowsFn() called on it, so the + // module_* vars and windows_fn_ are set up. + bool Patch(const LibcInfo& me_info); + void Unpatch(); + + private: + // This holds the original function contents after we patch the function. + // This has to be defined static in the subclass, because the perftools_fns + // reference origstub_fn_. + static GenericFnPtr origstub_fn_[kNumFunctions]; + + // This is the function we want to patch in + static const GenericFnPtr perftools_fn_[kNumFunctions]; + + static void* Perftools_malloc(size_t size) __THROW; + static void Perftools_free(void* ptr) __THROW; + static void Perftools_free_base(void* ptr) __THROW; + static void Perftools_free_dbg(void* ptr, int block_use) __THROW; + static void* Perftools_realloc(void* ptr, size_t size) __THROW; + static void* Perftools_calloc(size_t nmemb, size_t size) __THROW; + static void* Perftools_new(size_t size); + static void* Perftools_newarray(size_t size); + static void Perftools_delete(void *ptr); + static void Perftools_deletearray(void *ptr); + static void* Perftools_new_nothrow(size_t size, + const std::nothrow_t&) __THROW; + static void* Perftools_newarray_nothrow(size_t size, + const std::nothrow_t&) __THROW; + static void Perftools_delete_nothrow(void *ptr, + const std::nothrow_t&) __THROW; + static void Perftools_deletearray_nothrow(void *ptr, + const std::nothrow_t&) __THROW; + static size_t Perftools__msize(void *ptr) __THROW; + static void* Perftools__expand(void *ptr, size_t size) __THROW; + // malloc.h also defines these functions: + // _aligned_malloc, _aligned_free, + // _recalloc, _aligned_offset_malloc, _aligned_realloc, _aligned_recalloc + // _aligned_offset_realloc, _aligned_offset_recalloc, _malloca, _freea + // But they seem pretty obscure, and I'm fine not overriding them for now. + // It may be they all call into malloc/free anyway. +}; + +// This is a subset of MODDULEENTRY32, that we need for patching. +struct ModuleEntryCopy { + LPVOID modBaseAddr; // the same as hmodule + DWORD modBaseSize; + // This is not part of MODDULEENTRY32, but is needed to avoid making + // windows syscalls while we're holding patch_all_modules_lock (see + // lock-inversion comments at patch_all_modules_lock definition, below). + GenericFnPtr rgProcAddresses[LibcInfo::ctrgProcAddress]; + + ModuleEntryCopy() { + modBaseAddr = NULL; + modBaseSize = 0; + for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) + rgProcAddresses[i] = LibcInfo::static_fn(i); + } + ModuleEntryCopy(const MODULEINFO& mi) { + this->modBaseAddr = mi.lpBaseOfDll; + this->modBaseSize = mi.SizeOfImage; + LPVOID modEndAddr = (char*)mi.lpBaseOfDll + mi.SizeOfImage; + for (int i = 0; i < sizeof(rgProcAddresses)/sizeof(*rgProcAddresses); i++) { + FARPROC target = ::GetProcAddress( + reinterpret_cast(mi.lpBaseOfDll), + LibcInfo::function_name(i)); + // Sometimes a DLL forwards a function to a function in another + // DLL. We don't want to patch those forwarded functions -- + // they'll get patched when the other DLL is processed. + if (target >= modBaseAddr && target < modEndAddr) + rgProcAddresses[i] = (GenericFnPtr)target; + else + rgProcAddresses[i] = (GenericFnPtr)NULL; + } + } +}; + +// This class is easier because there's only one of them. +class WindowsInfo { + public: + void Patch(); + void Unpatch(); + + private: + // TODO(csilvers): should we be patching GlobalAlloc/LocalAlloc instead, + // for pre-XP systems? + enum { + kHeapAlloc, kHeapFree, kVirtualAllocEx, kVirtualFreeEx, + kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW, kFreeLibrary, + kNumFunctions + }; + + struct FunctionInfo { + const char* const name; // name of fn in a module (eg "malloc") + GenericFnPtr windows_fn; // the fn whose name we call (&malloc) + GenericFnPtr origstub_fn; // original fn contents after we patch + const GenericFnPtr perftools_fn; // fn we want to patch in + }; + + static FunctionInfo function_info_[kNumFunctions]; + + // A Windows-API equivalent of malloc and free + static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags, + DWORD_PTR dwBytes); + static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags, + LPVOID lpMem); + // A Windows-API equivalent of mmap and munmap, for "anonymous regions" + static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address, + SIZE_T size, DWORD type, + DWORD protect); + static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address, + SIZE_T size, DWORD type); + // A Windows-API equivalent of mmap and munmap, for actual files + static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + SIZE_T dwNumberOfBytesToMap, + LPVOID lpBaseAddress); + static BOOL WINAPI Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress); + // We don't need the other 3 variants because they all call this one. */ + static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName, + HANDLE hFile, + DWORD dwFlags); + static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule); +}; + +// If you run out, just add a few more to the array. You'll also need +// to update the switch statement in PatchOneModule(), and the list in +// UnpatchWindowsFunctions(). +// main_executable and main_executable_windows are two windows into +// the same executable. One is responsible for patching the libc +// routines that live in the main executable (if any) to use tcmalloc; +// the other is responsible for patching the windows routines like +// HeapAlloc/etc to use tcmalloc. +static LibcInfoWithPatchFunctions<0> main_executable; +static LibcInfoWithPatchFunctions<1> libc1; +static LibcInfoWithPatchFunctions<2> libc2; +static LibcInfoWithPatchFunctions<3> libc3; +static LibcInfoWithPatchFunctions<4> libc4; +static LibcInfoWithPatchFunctions<5> libc5; +static LibcInfoWithPatchFunctions<6> libc6; +static LibcInfoWithPatchFunctions<7> libc7; +static LibcInfoWithPatchFunctions<8> libc8; +static LibcInfo* g_module_libcs[] = { + &libc1, &libc2, &libc3, &libc4, &libc5, &libc6, &libc7, &libc8 +}; +static WindowsInfo main_executable_windows; + +const char* const LibcInfo::function_name_[] = { + "malloc", "free", "realloc", "calloc", + kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray, + // Ideally we should patch the nothrow versions of new/delete, but + // at least in msvcrt, nothrow-new machine-code is of a type we + // can't patch. Since these are relatively rare, I'm hoping it's ok + // not to patch them. (NULL name turns off patching.) + NULL, // kMangledNewNothrow, + NULL, // kMangledNewArrayNothrow, + NULL, // kMangledDeleteNothrow, + NULL, // kMangledDeleteArrayNothrow, + "_msize", "_expand", "_calloc_crt", "_free_base", "_free_dbg" +}; + +// For mingw, I can't patch the new/delete here, because the +// instructions are too small to patch. Luckily, they're so small +// because all they do is call into malloc/free, so they still end up +// calling tcmalloc routines, and we don't actually lose anything +// (except maybe some stacktrace goodness) by not patching. +const GenericFnPtr LibcInfo::static_fn_[] = { + (GenericFnPtr)&::malloc, + (GenericFnPtr)&::free, + (GenericFnPtr)&::realloc, + (GenericFnPtr)&::calloc, +#ifdef __MINGW32__ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +#else + (GenericFnPtr)(void*(*)(size_t))&::operator new, + (GenericFnPtr)(void*(*)(size_t))&::operator new[], + (GenericFnPtr)(void(*)(void*))&::operator delete, + (GenericFnPtr)(void(*)(void*))&::operator delete[], + (GenericFnPtr) + (void*(*)(size_t, struct std::nothrow_t const &))&::operator new, + (GenericFnPtr) + (void*(*)(size_t, struct std::nothrow_t const &))&::operator new[], + (GenericFnPtr) + (void(*)(void*, struct std::nothrow_t const &))&::operator delete, + (GenericFnPtr) + (void(*)(void*, struct std::nothrow_t const &))&::operator delete[], +#endif + (GenericFnPtr)&::_msize, + (GenericFnPtr)&::_expand, + (GenericFnPtr)&::calloc, + (GenericFnPtr)&::free, + (GenericFnPtr)&::free +}; + +template GenericFnPtr LibcInfoWithPatchFunctions::origstub_fn_[] = { + // This will get filled in at run-time, as patching is done. +}; + +template +const GenericFnPtr LibcInfoWithPatchFunctions::perftools_fn_[] = { + (GenericFnPtr)&Perftools_malloc, + (GenericFnPtr)&Perftools_free, + (GenericFnPtr)&Perftools_realloc, + (GenericFnPtr)&Perftools_calloc, + (GenericFnPtr)&Perftools_new, + (GenericFnPtr)&Perftools_newarray, + (GenericFnPtr)&Perftools_delete, + (GenericFnPtr)&Perftools_deletearray, + (GenericFnPtr)&Perftools_new_nothrow, + (GenericFnPtr)&Perftools_newarray_nothrow, + (GenericFnPtr)&Perftools_delete_nothrow, + (GenericFnPtr)&Perftools_deletearray_nothrow, + (GenericFnPtr)&Perftools__msize, + (GenericFnPtr)&Perftools__expand, + (GenericFnPtr)&Perftools_calloc, + (GenericFnPtr)&Perftools_free_base, + (GenericFnPtr)&Perftools_free_dbg +}; + +/*static*/ WindowsInfo::FunctionInfo WindowsInfo::function_info_[] = { + { "HeapAlloc", NULL, NULL, (GenericFnPtr)&Perftools_HeapAlloc }, + { "HeapFree", NULL, NULL, (GenericFnPtr)&Perftools_HeapFree }, + { "VirtualAllocEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualAllocEx }, + { "VirtualFreeEx", NULL, NULL, (GenericFnPtr)&Perftools_VirtualFreeEx }, + { "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx }, + { "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile }, + { "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW }, + { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary }, +}; + +bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) { + // First, store the location of the function to patch before + // patching it. If none of these functions are found in the module, + // then this module has no libc in it, and we just return false. + for (int i = 0; i < kNumFunctions; i++) { + if (!function_name_[i]) // we can turn off patching by unsetting name + continue; + // The ::GetProcAddress calls were done in the ModuleEntryCopy + // constructor, so we don't have to make any windows calls here. + const GenericFnPtr fn = module_entry.rgProcAddresses[i]; + if (fn) { + windows_fn_[i] = PreamblePatcher::ResolveTarget(fn); + } + } + + // Some modules use the same function pointer for new and new[]. If + // we find that, set one of the pointers to NULL so we don't double- + // patch. Same may happen with new and nothrow-new, or even new[] + // and nothrow-new. It's easiest just to check each fn-ptr against + // every other. + for (int i = 0; i < kNumFunctions; i++) { + for (int j = i+1; j < kNumFunctions; j++) { + if (windows_fn_[i] == windows_fn_[j]) { + // We NULL the later one (j), so as to minimize the chances we + // NULL kFree and kRealloc. See comments below. This is fragile! + windows_fn_[j] = NULL; + } + } + } + + // There's always a chance that our module uses the same function + // as another module that we've already loaded. In that case, we + // need to set our windows_fn to NULL, to avoid double-patching. + for (int ifn = 0; ifn < kNumFunctions; ifn++) { + for (int imod = 0; + imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs); imod++) { + if (g_module_libcs[imod]->is_valid() && + this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) { + windows_fn_[ifn] = NULL; + } + } + } + + bool found_non_null = false; + for (int i = 0; i < kNumFunctions; i++) { + if (windows_fn_[i]) + found_non_null = true; + } + if (!found_non_null) + return false; + + // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc]. + // The reason is, if those are NULL-ed out, we'll never patch them + // and thus never get an origstub_fn_ value for them, and when we + // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and + // Perftools_realloc, below, it will fail. We could work around + // that by adding a pointer from one patch-unit to the other, but we + // haven't needed to yet. + CHECK(windows_fn_[kFree]); + CHECK(windows_fn_[kRealloc]); + + // OK, we successfully populated. Let's store our member information. + module_base_address_ = module_entry.modBaseAddr; + module_base_size_ = module_entry.modBaseSize; + return true; +} + +template +bool LibcInfoWithPatchFunctions::Patch(const LibcInfo& me_info) { + CopyFrom(me_info); // copies the module_entry and the windows_fn_ array + for (int i = 0; i < kNumFunctions; i++) { + if (windows_fn_[i] && windows_fn_[i] != perftools_fn_[i]) { + // if origstub_fn_ is not NULL, it's left around from a previous + // patch. We need to set it to NULL for the new Patch call. + // + // Note that origstub_fn_ was logically freed by + // PreamblePatcher::Unpatch, so we don't have to do anything + // about it. + origstub_fn_[i] = NULL; // Patch() will fill this in + CHECK_EQ(sidestep::SIDESTEP_SUCCESS, + PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i], + &origstub_fn_[i])); + } + } + set_is_valid(true); + return true; +} + +template +void LibcInfoWithPatchFunctions::Unpatch() { + // We have to cast our GenericFnPtrs to void* for unpatch. This is + // contra the C++ spec; we use C-style casts to empahsize that. + for (int i = 0; i < kNumFunctions; i++) { + if (windows_fn_[i]) + CHECK_EQ(sidestep::SIDESTEP_SUCCESS, + PreamblePatcher::Unpatch((void*)windows_fn_[i], + (void*)perftools_fn_[i], + (void*)origstub_fn_[i])); + } + set_is_valid(false); +} + +void WindowsInfo::Patch() { + HMODULE hkernel32 = ::GetModuleHandleA("kernel32"); + CHECK_NE(hkernel32, NULL); + + // Unlike for libc, we know these exist in our module, so we can get + // and patch at the same time. + for (int i = 0; i < kNumFunctions; i++) { + function_info_[i].windows_fn = (GenericFnPtr) + ::GetProcAddress(hkernel32, function_info_[i].name); + // If origstub_fn is not NULL, it's left around from a previous + // patch. We need to set it to NULL for the new Patch call. + // Since we've patched Unpatch() not to delete origstub_fn_ (it + // causes problems in some contexts, though obviously not this + // one), we should delete it now, before setting it to NULL. + // NOTE: casting from a function to a pointer is contra the C++ + // spec. It's not safe on IA64, but is on i386. We use + // a C-style cast here to emphasize this is not legal C++. + delete[] (char*)(function_info_[i].origstub_fn); + function_info_[i].origstub_fn = NULL; // Patch() will fill this in + CHECK_EQ(sidestep::SIDESTEP_SUCCESS, + PreamblePatcher::Patch(function_info_[i].windows_fn, + function_info_[i].perftools_fn, + &function_info_[i].origstub_fn)); + } +} + +void WindowsInfo::Unpatch() { + // We have to cast our GenericFnPtrs to void* for unpatch. This is + // contra the C++ spec; we use C-style casts to empahsize that. + for (int i = 0; i < kNumFunctions; i++) { + CHECK_EQ(sidestep::SIDESTEP_SUCCESS, + PreamblePatcher::Unpatch((void*)function_info_[i].windows_fn, + (void*)function_info_[i].perftools_fn, + (void*)function_info_[i].origstub_fn)); + } +} + +// You should hold the patch_all_modules_lock when calling this. +void PatchOneModuleLocked(const LibcInfo& me_info) { + // If we don't already have info on this module, let's add it. This + // is where we're sad that each libcX has a different type, so we + // can't use an array; instead, we have to use a switch statement. + // Patch() returns false if there were no libc functions in the module. + for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) { + if (!g_module_libcs[i]->is_valid()) { // found an empty spot to add! + switch (i) { + case 0: libc1.Patch(me_info); return; + case 1: libc2.Patch(me_info); return; + case 2: libc3.Patch(me_info); return; + case 3: libc4.Patch(me_info); return; + case 4: libc5.Patch(me_info); return; + case 5: libc6.Patch(me_info); return; + case 6: libc7.Patch(me_info); return; + case 7: libc8.Patch(me_info); return; + } + } + } + printf("PERFTOOLS ERROR: Too many modules containing libc in this executable\n"); +} + +void PatchMainExecutableLocked() { + if (main_executable.patched()) + return; // main executable has already been patched + ModuleEntryCopy fake_module_entry; // make a fake one to pass into Patch() + // No need to call PopulateModuleEntryProcAddresses on the main executable. + main_executable.PopulateWindowsFn(fake_module_entry); + main_executable.Patch(main_executable); +} + +// This lock is subject to a subtle and annoying lock inversion +// problem: it may interact badly with unknown internal windows locks. +// In particular, windows may be holding a lock when it calls +// LoadLibraryExW and FreeLibrary, which we've patched. We have those +// routines call PatchAllModules, which acquires this lock. If we +// make windows system calls while holding this lock, those system +// calls may need the internal windows locks that are being held in +// the call to LoadLibraryExW, resulting in deadlock. The solution is +// to be very careful not to call *any* windows routines while holding +// patch_all_modules_lock, inside PatchAllModules(). +static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED); + +// last_loaded: The set of modules that were loaded the last time +// PatchAllModules was called. This is an optimization for only +// looking at modules that were added or removed from the last call. +static std::set *g_last_loaded; + +// Iterates over all the modules currently loaded by the executable, +// according to windows, and makes sure they're all patched. Most +// modules will already be in loaded_modules, meaning we have already +// loaded and either patched them or determined they did not need to +// be patched. Others will not, which means we need to patch them +// (if necessary). Finally, we have to go through the existing +// g_module_libcs and see if any of those are *not* in the modules +// currently loaded by the executable. If so, we need to invalidate +// them. Returns true if we did any work (patching or invalidating), +// false if we were a noop. May update loaded_modules as well. +// NOTE: you must hold the patch_all_modules_lock to access loaded_modules. +bool PatchAllModules() { + std::vector modules; + bool made_changes = false; + + const HANDLE hCurrentProcess = GetCurrentProcess(); + DWORD num_modules = 0; + HMODULE hModules[kMaxModules]; // max # of modules we support in one process + if (!::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules), + &num_modules)) { + num_modules = 0; + } + // EnumProcessModules actually set the bytes written into hModules, + // so we need to divide to make num_modules actually be a module-count. + num_modules /= sizeof(*hModules); + if (num_modules >= kMaxModules) { + printf("PERFTOOLS ERROR: Too many modules in this executable to try" + " to patch them all (if you need to, raise kMaxModules in" + " patch_functions.cc).\n"); + num_modules = kMaxModules; + } + + // Now we handle the unpatching of modules we have in g_module_libcs + // but that were not found in EnumProcessModules. We need to + // invalidate them. To speed that up, we store the EnumProcessModules + // output in a set. + // At the same time, we prepare for the adding of new modules, by + // removing from hModules all the modules we know we've already + // patched (or decided don't need to be patched). At the end, + // hModules will hold only the modules that we need to consider patching. + std::set currently_loaded_modules; + { + SpinLockHolder h(&patch_all_modules_lock); + if (!g_last_loaded) g_last_loaded = new std::set; + // At the end of this loop, currently_loaded_modules contains the + // full list of EnumProcessModules, and hModules just the ones we + // haven't handled yet. + for (int i = 0; i < num_modules; ) { + currently_loaded_modules.insert(hModules[i]); + if (g_last_loaded->count(hModules[i]) > 0) { + hModules[i] = hModules[--num_modules]; // replace element i with tail + } else { + i++; // keep element i + } + } + // Now we do the unpatching/invalidation. + for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) { + if (g_module_libcs[i]->patched() && + currently_loaded_modules.count(g_module_libcs[i]->hmodule()) == 0) { + // Means g_module_libcs[i] is no longer loaded (no me32 matched). + // We could call Unpatch() here, but why bother? The module + // has gone away, so nobody is going to call into it anyway. + g_module_libcs[i]->set_is_valid(false); + made_changes = true; + } + } + // Update the loaded module cache. + g_last_loaded->swap(currently_loaded_modules); + } + + // Now that we know what modules are new, let's get the info we'll + // need to patch them. Note this *cannot* be done while holding the + // lock, since it needs to make windows calls (see the lock-inversion + // comments before the definition of patch_all_modules_lock). + MODULEINFO mi; + for (int i = 0; i < num_modules; i++) { + if (::GetModuleInformation(hCurrentProcess, hModules[i], &mi, sizeof(mi))) + modules.push_back(ModuleEntryCopy(mi)); + } + + // Now we can do the patching of new modules. + { + SpinLockHolder h(&patch_all_modules_lock); + for (std::vector::iterator it = modules.begin(); + it != modules.end(); ++it) { + LibcInfo libc_info; + if (libc_info.PopulateWindowsFn(*it)) { // true==module has libc routines + PatchOneModuleLocked(libc_info); + made_changes = true; + } + } + + // Now that we've dealt with the modules (dlls), update the main + // executable. We do this last because PatchMainExecutableLocked + // wants to look at how other modules were patched. + if (!main_executable.patched()) { + PatchMainExecutableLocked(); + made_changes = true; + } + } + // TODO(csilvers): for this to be reliable, we need to also take + // into account if we *would* have patched any modules had they not + // already been loaded. (That is, made_changes should ignore + // g_last_loaded.) + return made_changes; +} + + +} // end unnamed namespace + +// --------------------------------------------------------------------- +// Now that we've done all the patching machinery, let's actually +// define the functions we're patching in. Mostly these are +// simple wrappers around the do_* routines in tcmalloc.cc. +// +// In fact, we #include tcmalloc.cc to get at the tcmalloc internal +// do_* functions, the better to write our own hook functions. +// U-G-L-Y, I know. But the alternatives are, perhaps, worse. This +// also lets us define _msize(), _expand(), and other windows-specific +// functions here, using tcmalloc internals, without polluting +// tcmalloc.cc. +// ------------------------------------------------------------------- + +// TODO(csilvers): refactor tcmalloc.cc into two files, so I can link +// against the file with do_malloc, and ignore the one with malloc. +#include "tcmalloc.cc" + +template +void* LibcInfoWithPatchFunctions::Perftools_malloc(size_t size) __THROW { + return malloc_fast_path(size); +} + +template +void LibcInfoWithPatchFunctions::Perftools_free(void* ptr) __THROW { + MallocHook::InvokeDeleteHook(ptr); + // This calls the windows free if do_free decides ptr was not + // allocated by tcmalloc. Note it calls the origstub_free from + // *this* templatized instance of LibcInfo. See "template + // trickiness" above. + do_free_with_callback(ptr, (void (*)(void*))origstub_fn_[kFree], false, 0); +} + +template +void LibcInfoWithPatchFunctions::Perftools_free_base(void* ptr) __THROW{ + MallocHook::InvokeDeleteHook(ptr); + // This calls the windows free if do_free decides ptr was not + // allocated by tcmalloc. Note it calls the origstub_free from + // *this* templatized instance of LibcInfo. See "template + // trickiness" above. + do_free_with_callback(ptr, (void(*)(void*))origstub_fn_[kFreeBase], false, 0); +} + +template +void LibcInfoWithPatchFunctions::Perftools_free_dbg(void* ptr, int block_use) __THROW { + MallocHook::InvokeDeleteHook(ptr); + // The windows _free_dbg is called if ptr isn't owned by tcmalloc. + if (MallocExtension::instance()->GetOwnership(ptr) == MallocExtension::kOwned) { + do_free(ptr); + } else { + reinterpret_cast(origstub_fn_[kFreeDbg])(ptr, block_use); + } +} + +template +void* LibcInfoWithPatchFunctions::Perftools_realloc( + void* old_ptr, size_t new_size) __THROW { + if (old_ptr == NULL) { + void* result = do_malloc_or_cpp_alloc(new_size); + MallocHook::InvokeNewHook(result, new_size); + return result; + } + if (new_size == 0) { + MallocHook::InvokeDeleteHook(old_ptr); + do_free_with_callback(old_ptr, + (void (*)(void*))origstub_fn_[kFree], false, 0); + return NULL; + } + return do_realloc_with_callback( + old_ptr, new_size, + (void (*)(void*))origstub_fn_[kFree], + (size_t (*)(const void*))origstub_fn_[k_Msize]); +} + +template +void* LibcInfoWithPatchFunctions::Perftools_calloc( + size_t n, size_t elem_size) __THROW { + void* result = do_calloc(n, elem_size); + MallocHook::InvokeNewHook(result, n * elem_size); + return result; +} + +template +void* LibcInfoWithPatchFunctions::Perftools_new(size_t size) { + return malloc_fast_path(size); +} + +template +void* LibcInfoWithPatchFunctions::Perftools_newarray(size_t size) { + return malloc_fast_path(size); +} + +template +void LibcInfoWithPatchFunctions::Perftools_delete(void *p) { + MallocHook::InvokeDeleteHook(p); + do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0); +} + +template +void LibcInfoWithPatchFunctions::Perftools_deletearray(void *p) { + MallocHook::InvokeDeleteHook(p); + do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0); +} + +template +void* LibcInfoWithPatchFunctions::Perftools_new_nothrow( + size_t size, const std::nothrow_t&) __THROW { + return malloc_fast_path(size); +} + +template +void* LibcInfoWithPatchFunctions::Perftools_newarray_nothrow( + size_t size, const std::nothrow_t&) __THROW { + return malloc_fast_path(size); +} + +template +void LibcInfoWithPatchFunctions::Perftools_delete_nothrow( + void *p, const std::nothrow_t&) __THROW { + MallocHook::InvokeDeleteHook(p); + do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0); +} + +template +void LibcInfoWithPatchFunctions::Perftools_deletearray_nothrow( + void *p, const std::nothrow_t&) __THROW { + MallocHook::InvokeDeleteHook(p); + do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree], false, 0); +} + + +// _msize() lets you figure out how much space is reserved for a +// pointer, in Windows. Even if applications don't call it, any DLL +// with global constructors will call (transitively) something called +// __dllonexit_lk in order to make sure the destructors get called +// when the dll unloads. And that will call msize -- horrible things +// can ensue if this is not hooked. Other parts of libc may also call +// this internally. + +template +size_t LibcInfoWithPatchFunctions::Perftools__msize(void* ptr) __THROW { + return GetSizeWithCallback(ptr, (size_t (*)(const void*))origstub_fn_[k_Msize]); +} + +// We need to define this because internal windows functions like to +// call into it(?). _expand() is like realloc but doesn't move the +// pointer. We punt, which will cause callers to fall back on realloc. +template +void* LibcInfoWithPatchFunctions::Perftools__expand(void *ptr, + size_t size) __THROW { + return NULL; +} + +LPVOID WINAPI WindowsInfo::Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags, + DWORD_PTR dwBytes) { + LPVOID result = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD_PTR)) + function_info_[kHeapAlloc].origstub_fn)( + hHeap, dwFlags, dwBytes); + MallocHook::InvokeNewHook(result, dwBytes); + return result; +} + +BOOL WINAPI WindowsInfo::Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags, + LPVOID lpMem) { + MallocHook::InvokeDeleteHook(lpMem); + return ((BOOL (WINAPI *)(HANDLE, DWORD, LPVOID)) + function_info_[kHeapFree].origstub_fn)( + hHeap, dwFlags, lpMem); +} + +LPVOID WINAPI WindowsInfo::Perftools_VirtualAllocEx(HANDLE process, + LPVOID address, + SIZE_T size, DWORD type, + DWORD protect) { + LPVOID result = ((LPVOID (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD)) + function_info_[kVirtualAllocEx].origstub_fn)( + 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; +} + +BOOL WINAPI WindowsInfo::Perftools_VirtualFreeEx(HANDLE process, LPVOID address, + SIZE_T size, DWORD type) { + MallocHook::InvokeMunmapHook(address, size); + return ((BOOL (WINAPI *)(HANDLE, LPVOID, SIZE_T, DWORD)) + function_info_[kVirtualFreeEx].origstub_fn)( + process, address, size, type); +} + +LPVOID WINAPI WindowsInfo::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 = ((LPVOID (WINAPI *)(HANDLE, DWORD, DWORD, DWORD, + SIZE_T, LPVOID)) + function_info_[kMapViewOfFileEx].origstub_fn)( + hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, + dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress); + MallocHook::InvokeNewHook(result, dwNumberOfBytesToMap); + return result; +} + +BOOL WINAPI WindowsInfo::Perftools_UnmapViewOfFile(LPCVOID lpBaseAddress) { + MallocHook::InvokeDeleteHook(lpBaseAddress); + return ((BOOL (WINAPI *)(LPCVOID)) + function_info_[kUnmapViewOfFile].origstub_fn)( + lpBaseAddress); +} + +HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName, + HANDLE hFile, + DWORD dwFlags) { + HMODULE rv; + // Check to see if the modules is already loaded, flag 0 gets a + // reference if it was loaded. If it was loaded no need to call + // PatchAllModules, just increase the reference count to match + // what GetModuleHandleExW does internally inside windows. + if (::GetModuleHandleExW(0, lpFileName, &rv)) { + return rv; + } else { + // Not already loaded, so load it. + rv = ((HMODULE (WINAPI *)(LPCWSTR, HANDLE, DWORD)) + function_info_[kLoadLibraryExW].origstub_fn)( + lpFileName, hFile, dwFlags); + // This will patch any newly loaded libraries, if patching needs + // to be done. + PatchAllModules(); + + return rv; + } +} + +BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) { + BOOL rv = ((BOOL (WINAPI *)(HMODULE)) + function_info_[kFreeLibrary].origstub_fn)(hLibModule); + + // Check to see if the module is still loaded by passing the base + // address and seeing if it comes back with the same address. If it + // is the same address it's still loaded, so the FreeLibrary() call + // was a noop, and there's no need to redo the patching. + HMODULE owner = NULL; + BOOL result = ::GetModuleHandleExW( + (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), + (LPCWSTR)hLibModule, + &owner); + if (result && owner == hLibModule) + return rv; + + PatchAllModules(); // this will fix up the list of patched libraries + return rv; +} + + +// --------------------------------------------------------------------- +// PatchWindowsFunctions() +// This is the function that is exposed to the outside world. +// It should be called before the program becomes multi-threaded, +// since main_executable_windows.Patch() is not thread-safe. +// --------------------------------------------------------------------- + +void PatchWindowsFunctions() { + // This does the libc patching in every module, and the main executable. + PatchAllModules(); + main_executable_windows.Patch(); +} + +#if 0 +// It's possible to unpatch all the functions when we are exiting. + +// The idea is to handle properly windows-internal data that is +// allocated before PatchWindowsFunctions is called. If all +// destruction happened in reverse order from construction, then we +// could call UnpatchWindowsFunctions at just the right time, so that +// that early-allocated data would be freed using the windows +// allocation functions rather than tcmalloc. The problem is that +// windows allocates some structures lazily, so it would allocate them +// late (using tcmalloc) and then try to deallocate them late as well. +// So instead of unpatching, we just modify all the tcmalloc routines +// so they call through to the libc rountines if the memory in +// question doesn't seem to have been allocated with tcmalloc. I keep +// this unpatch code around for reference. + +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. + main_executable_windows.Unpatch(); + main_executable.Unpatch(); + if (libc1.is_valid()) libc1.Unpatch(); + if (libc2.is_valid()) libc2.Unpatch(); + if (libc3.is_valid()) libc3.Unpatch(); + if (libc4.is_valid()) libc4.Unpatch(); + if (libc5.is_valid()) libc5.Unpatch(); + if (libc6.is_valid()) libc6.Unpatch(); + if (libc7.is_valid()) libc7.Unpatch(); + if (libc8.is_valid()) libc8.Unpatch(); +} +#endif diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/port.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/port.cc new file mode 100644 index 000000000..e73c5086f --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/port.cc @@ -0,0 +1,249 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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: Craig Silverstein + */ + +#ifndef _WIN32 +# error You should only be including windows/port.cc in a windows environment! +#endif + +#define NOMINMAX // so std::max, below, compiles correctly +#include +#include // for strlen(), memset(), memcmp() +#include +#include // for va_list, va_start, va_end +#include // for std:{min,max} +#include +#include "port.h" +#include "base/logging.h" +#include "base/spinlock.h" +#include "internal_logging.h" + +// ----------------------------------------------------------------------- +// Basic libraries + +PERFTOOLS_DLL_DECL +int getpagesize() { + static int pagesize = 0; + if (pagesize == 0) { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + pagesize = std::max(system_info.dwPageSize, + system_info.dwAllocationGranularity); + } + return pagesize; +} + +extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) { + LOG(FATAL, "Windows doesn't implement sbrk!\n"); + return NULL; +} + +// We need to write to 'stderr' without having windows allocate memory. +// The safest way is via a low-level call like WriteConsoleA(). But +// even then we need to be sure to print in small bursts so as to not +// require memory allocation. +extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) { + // Looks like windows allocates for writes of >80 bytes + for (int i = 0; i < len; i += 80) { + write(STDERR_FILENO, buf + i, std::min(80, len - i)); + } +} + + +// ----------------------------------------------------------------------- +// Threads code + +// Windows doesn't support pthread_key_create's destr_function, and in +// fact it's a bit tricky to get code to run when a thread exits. This +// is cargo-cult magic from https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way +// and http://lallouslab.net/2017/05/30/using-cc-tls-callbacks-in-visual-studio-with-your-32-or-64bits-programs/. +// This code is for VC++ 7.1 and later; VC++ 6.0 support is possible +// but more busy-work -- see the webpage for how to do it. If all +// this fails, we could use DllMain instead. The big problem with +// DllMain is it doesn't run if this code is statically linked into a +// binary (it also doesn't run if the thread is terminated via +// TerminateThread, which if we're lucky this routine does). + +// Force a reference to _tls_used to make the linker create the TLS directory +// if it's not already there (that is, even if __declspec(thread) is not used). +// Force a reference to p_thread_callback_tcmalloc and p_process_term_tcmalloc +// to prevent whole program optimization from discarding the variables. +#ifdef _MSC_VER +#if defined(_M_IX86) +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback_tcmalloc") +#pragma comment(linker, "/INCLUDE:_p_process_term_tcmalloc") +#elif defined(_M_X64) +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback_tcmalloc") +#pragma comment(linker, "/INCLUDE:p_process_term_tcmalloc") +#endif +#endif + +// When destr_fn eventually runs, it's supposed to take as its +// argument the tls-value associated with key that pthread_key_create +// creates. (Yeah, it sounds confusing but it's really not.) We +// store the destr_fn/key pair in this data structure. Because we +// store this in a single var, this implies we can only have one +// destr_fn in a program! That's enough in practice. If asserts +// trigger because we end up needing more, we'll have to turn this +// into an array. +struct DestrFnClosure { + void (*destr_fn)(void*); + pthread_key_t key_for_destr_fn_arg; +}; + +static DestrFnClosure destr_fn_info; // initted to all NULL/0. + +static int on_process_term(void) { + if (destr_fn_info.destr_fn) { + void *ptr = TlsGetValue(destr_fn_info.key_for_destr_fn_arg); + // This shouldn't be necessary, but in Release mode, Windows + // sometimes trashes the pointer in the TLS slot, so we need to + // remove the pointer from the TLS slot before the thread dies. + TlsSetValue(destr_fn_info.key_for_destr_fn_arg, NULL); + if (ptr) // pthread semantics say not to call if ptr is NULL + (*destr_fn_info.destr_fn)(ptr); + } + return 0; +} + +static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) { + if (dwReason == DLL_THREAD_DETACH) { // thread is being destroyed! + on_process_term(); + } +} + +#ifdef _MSC_VER + +// extern "C" suppresses C++ name mangling so we know the symbol names +// for the linker /INCLUDE:symbol pragmas above. +// Note that for some unknown reason, the extern "C" {} construct is ignored +// by the MSVC VS2017 compiler (at least) when a const modifier is used +#if defined(_M_IX86) +extern "C" { +// In x86, the PE loader looks for callbacks in a data segment +#pragma data_seg(push, old_seg) +#pragma data_seg(".CRT$XLB") +void (NTAPI *p_thread_callback_tcmalloc)( + HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback; +#pragma data_seg(".CRT$XTU") +int (*p_process_term_tcmalloc)(void) = on_process_term; +#pragma data_seg(pop, old_seg) +} // extern "C" +#elif defined(_M_X64) +// In x64, the PE loader looks for callbacks in a constant segment +#pragma const_seg(push, oldseg) +#pragma const_seg(".CRT$XLB") +extern "C" void (NTAPI * const p_thread_callback_tcmalloc)( + HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback; +#pragma const_seg(".CRT$XTU") +extern "C" int (NTAPI * const p_process_term_tcmalloc)(void) = on_process_term; +#pragma const_seg(pop, oldseg) +#endif + +#else // #ifdef _MSC_VER [probably msys/mingw] + +// We have to try the DllMain solution here, because we can't use the +// msvc-specific pragmas. +BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, PVOID pv) { + if (dwReason == DLL_THREAD_DETACH) + on_tls_callback(h, dwReason, pv); + else if (dwReason == DLL_PROCESS_DETACH) + on_process_term(); + return TRUE; +} + +#endif // #ifdef _MSC_VER + +extern "C" pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) { + // Semantics are: we create a new key, and then promise to call + // destr_fn with TlsGetValue(key) when the thread is destroyed + // (as long as TlsGetValue(key) is not NULL). + pthread_key_t key = TlsAlloc(); + if (destr_fn) { // register it + // If this assert fails, we'll need to support an array of destr_fn_infos + assert(destr_fn_info.destr_fn == NULL); + destr_fn_info.destr_fn = destr_fn; + destr_fn_info.key_for_destr_fn_arg = key; + } + return key; +} + +// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION... +extern "C" int perftools_pthread_once(pthread_once_t *once_control, + void (*init_routine)(void)) { + // Try for a fast path first. Note: this should be an acquire semantics read. + // It is on x86 and x64, where Windows runs. + if (*once_control != 1) { + while (true) { + switch (InterlockedCompareExchange(once_control, 2, 0)) { + case 0: + init_routine(); + InterlockedExchange(once_control, 1); + return 0; + case 1: + // The initializer has already been executed + return 0; + default: + // The initializer is being processed by another thread + SwitchToThread(); + } + } + } + return 0; +} + + +// ----------------------------------------------------------------------- +// 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) + HANDLE hFind = FindFirstFileA(full_glob, &found); // A is for Ansi + if (hFind != INVALID_HANDLE_VALUE) { + const int prefix_length = strlen(prefix); + do { + const char *fname = found.cFileName; + if ((strlen(fname) >= prefix_length) && + (memcmp(fname, prefix, prefix_length) == 0)) { + RAW_VLOG(0, "Removing old heap profile %s\n", fname); + // TODO(csilvers): we really need to unlink dirname + fname + _unlink(fname); + } + } while (FindNextFileA(hFind, &found) != FALSE); // A is for Ansi + FindClose(hFind); + } +} diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/port.h b/trunk/3rdparty/gperftools-2-fit/src/windows/port.h new file mode 100644 index 000000000..29c6cb941 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/port.h @@ -0,0 +1,477 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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: Craig Silverstein + * + * These are some portability typedefs and defines to make it a bit + * easier to compile this code under VC++. + * + * Several of these are taken from glib: + * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html + */ + +#ifndef GOOGLE_BASE_WINDOWS_H_ +#define GOOGLE_BASE_WINDOWS_H_ + +/* You should never include this file directly, but always include it + from either config.h (MSVC) or mingw.h (MinGW/msys). */ +#if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \ + !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_) +# error "port.h should only be included from config.h or mingw.h" +#endif + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */ +#endif +#include +#include /* because we so often use open/close/etc */ +#include /* for _getcwd */ +#include /* for _getpid */ +#include /* for PATH_MAX */ +#include /* for va_list */ +#include /* need this to override stdio's (v)snprintf */ +#include /* for _off_t */ +#include +#include /* for rand, srand, _strtoxxx */ + +#if defined(_MSC_VER) && _MSC_VER >= 1900 +#define _TIMESPEC_DEFINED +#include +#endif + +/* + * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i) + * 4244: otherwise we get problems when subtracting two size_t's to an int + * 4288: VC++7 gets confused when a var is defined in a loop and then after it + * 4267: too many false positives for "conversion gives possible data loss" + * 4290: it's ok windows ignores the "throw" directive + * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv() + * 4146: internal_logging.cc intentionally negates an unsigned value + */ +#ifdef _MSC_VER +#pragma warning(disable:4018 4244 4288 4267 4290 4996 4146) +#endif + +#ifndef __cplusplus +/* MSVC does not support C99 */ +# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L +# ifdef _MSC_VER +# define inline __inline +# else +# define inline static +# endif +# endif +#endif + +#ifdef __cplusplus +# define EXTERN_C extern "C" +#else +# define EXTERN_C extern +#endif + +/* ----------------------------------- BASIC TYPES */ + +#ifndef HAVE_STDINT_H +# error Do not know how to set up type aliases. Edit port.h for your system. +#endif + +/* I guess MSVC's doesn't include ssize_t by default? */ +#ifdef _MSC_VER +typedef intptr_t ssize_t; +#endif + +/* ----------------------------------- THREADS */ + +#ifndef HAVE_PTHREAD /* not true for MSVC, but may be true for MSYS */ +typedef DWORD pthread_t; +typedef DWORD pthread_key_t; +typedef LONG pthread_once_t; +enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */ + +inline pthread_t pthread_self(void) { + return GetCurrentThreadId(); +} + +#ifdef __cplusplus +inline bool pthread_equal(pthread_t left, pthread_t right) { + return left == right; +} + +/* + * windows/port.h defines compatibility APIs for several .h files, which + * we therefore shouldn't be #including directly. This hack keeps us from + * doing so. TODO(csilvers): do something more principled. + */ +#define GOOGLE_MAYBE_THREADS_H_ 1 +/* This replaces maybe_threads.{h,cc} */ + +EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */ + +inline int perftools_pthread_key_create(pthread_key_t *pkey, + void (*destructor)(void*)) { + pthread_key_t key = PthreadKeyCreate(destructor); + if (key != TLS_OUT_OF_INDEXES) { + *(pkey) = key; + return 0; + } else { + return GetLastError(); + } +} + +inline void* perftools_pthread_getspecific(DWORD key) { + DWORD err = GetLastError(); + void* rv = TlsGetValue(key); + if (err) SetLastError(err); + return rv; +} + +inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) { + if (TlsSetValue(key, (LPVOID)value)) + return 0; + else + return GetLastError(); +} + +EXTERN_C int perftools_pthread_once(pthread_once_t *once_control, + void (*init_routine)(void)); + +#endif /* __cplusplus */ + +inline void sched_yield(void) { + Sleep(0); +} + +#endif /* HAVE_PTHREAD */ + +/* + * __declspec(thread) isn't usable in a dll opened via LoadLibrary(). + * But it doesn't work to LoadLibrary() us anyway, because of all the + * things we need to do before main()! So this kind of TLS is safe for us. + */ +#define __thread __declspec(thread) + +/* + * This code is obsolete, but I keep it around in case we are ever in + * an environment where we can't or don't want to use google spinlocks + * (from base/spinlock.{h,cc}). In that case, uncommenting this out, + * and removing spinlock.cc from the build, should be enough to revert + * back to using native spinlocks. + */ +#if 0 +// Windows uses a spinlock internally for its mutexes, making our life easy! +// However, the Windows spinlock must always be initialized, making life hard, +// since we want LINKER_INITIALIZED. We work around this by having the +// linker initialize a bool to 0, and check that before accessing the mutex. +// This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops) +#ifdef __cplusplus +class SpinLock { + public: + SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {} + // Used for global SpinLock vars (see base/spinlock.h for more details). + enum StaticInitializer { LINKER_INITIALIZED }; + explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) { + perftools_pthread_once(&initialize_token_, InitializeMutex); + } + + // It's important SpinLock not have a destructor: otherwise we run + // into problems when the main thread has exited, but other threads + // are still running and try to access a main-thread spinlock. This + // means we leak mutex_ (we should call DeleteCriticalSection() + // here). However, I've verified that all SpinLocks used in + // perftools have program-long scope anyway, so the leak is + // perfectly fine. But be aware of this for the future! + + void Lock() { + // You'd thionk this would be unnecessary, since we call + // InitializeMutex() in our constructor. But sometimes Lock() can + // be called before our constructor is! This can only happen in + // global constructors, when this is a global. If we live in + // bar.cc, and some global constructor in foo.cc calls a routine + // in bar.cc that calls this->Lock(), then Lock() may well run + // before our global constructor does. To protect against that, + // we do this check. For SpinLock objects created after main() + // has started, this pthread_once call will always be a noop. + perftools_pthread_once(&initialize_token_, InitializeMutex); + EnterCriticalSection(&mutex_); + } + void Unlock() { + LeaveCriticalSection(&mutex_); + } + + // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h). + inline bool IsHeld() const { + // This works, but probes undocumented internals, so I've commented it out. + // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/ + //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId(); + return true; + } + private: + void InitializeMutex() { InitializeCriticalSection(&mutex_); } + + pthread_once_t initialize_token_; + CRITICAL_SECTION mutex_; +}; + +class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts + private: + SpinLock* lock_; + public: + inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); } + inline ~SpinLockHolder() { lock_->Unlock(); } +}; +#endif // #ifdef __cplusplus + +// This keeps us from using base/spinlock.h's implementation of SpinLock. +#define BASE_SPINLOCK_H_ 1 + +#endif /* #if 0 */ + +/* ----------------------------------- MMAP and other memory allocation */ + +#ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */ +#define MAP_FAILED 0 +#define MREMAP_FIXED 2 /* the value in linux, though it doesn't really matter */ +/* These, when combined with the mmap invariants below, yield the proper action */ +#define PROT_READ PAGE_READWRITE +#define PROT_WRITE PAGE_READWRITE +#define MAP_ANONYMOUS MEM_RESERVE +#define MAP_PRIVATE MEM_COMMIT +#define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */ + +#if __STDC__ && !defined(__MINGW32__) +typedef _off_t off_t; +#endif + +/* VirtualAlloc only replaces for mmap when certain invariants are kept. */ +inline void *mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) { + if (addr == NULL && fd == -1 && offset == 0 && + prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) { + return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + } else { + return NULL; + } +} + +inline int munmap(void *addr, size_t length) { + return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1; +} +#endif /* HAVE_MMAP */ + +/* We could maybe use VirtualAlloc for sbrk as well, but no need */ +inline void *sbrk(intptr_t increment) { + // sbrk returns -1 on failure + return (void*)-1; +} + + +/* ----------------------------------- STRING ROUTINES */ + +/* + * We can't just use _vsnprintf and _snprintf as drop-in-replacements, + * because they don't always NUL-terminate. :-( We also can't use the + * name vsnprintf, since windows defines that (but not snprintf (!)). + */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +/* We can use safe CRT functions, which the required functionality */ +inline int perftools_vsnprintf(char *str, size_t size, const char *format, + va_list ap) { + return vsnprintf_s(str, size, _TRUNCATE, format, ap); +} +#else +inline int perftools_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); +} +#endif + +#ifndef HAVE_INTTYPES_H +#define PRIx64 "I64x" +#define SCNx64 "I64x" +#define PRId64 "I64d" +#define SCNd64 "I64d" +#define PRIu64 "I64u" +#ifdef _WIN64 +# define PRIuPTR "llu" +# define PRIxPTR "llx" +#else +# define PRIuPTR "lu" +# define PRIxPTR "lx" +#endif +#endif + +/* ----------------------------------- FILE IO */ + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif +#ifndef __MINGW32__ +enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 }; +#endif +#ifndef O_RDONLY +#define O_RDONLY _O_RDONLY +#endif + +#if __STDC__ && !defined(__MINGW32__) +/* These functions are considered non-standard */ +inline int access(const char *pathname, int mode) { + return _access(pathname, mode); +} +inline int open(const char *pathname, int flags, int mode = 0) { + return _open(pathname, flags, mode); +} +inline int close(int fd) { + return _close(fd); +} +inline ssize_t read(int fd, void *buf, size_t count) { + return _read(fd, buf, count); +} +inline ssize_t write(int fd, const void *buf, size_t count) { + return _write(fd, buf, count); +} +inline off_t lseek(int fd, off_t offset, int whence) { + return _lseek(fd, offset, whence); +} +inline char *getcwd(char *buf, size_t size) { + return _getcwd(buf, size); +} +inline int mkdir(const char *pathname, int) { + return _mkdir(pathname); +} + +inline FILE *popen(const char *command, const char *type) { + return _popen(command, type); +} +inline int pclose(FILE *stream) { + return _pclose(stream); +} +#endif + +EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len); + +/* ----------------------------------- SYSTEM/PROCESS */ + +#ifndef HAVE_PID_T +typedef int pid_t; +#endif + +#if __STDC__ && !defined(__MINGW32__) +inline pid_t getpid(void) { return _getpid(); } +#endif +inline pid_t getppid(void) { return 0; } + +/* Handle case when poll is used to simulate sleep. */ +inline int poll(struct pollfd* fds, int nfds, int timeout) { + assert(fds == NULL); + assert(nfds == 0); + Sleep(timeout); + return 0; +} + +EXTERN_C PERFTOOLS_DLL_DECL int getpagesize(); /* in port.cc */ + +/* ----------------------------------- OTHER */ + +inline void srandom(unsigned int seed) { srand(seed); } +inline long random(void) { return rand(); } + +#ifndef HAVE_DECL_SLEEP +#define HAVE_DECL_SLEEP 0 +#endif + +#if !HAVE_DECL_SLEEP +inline unsigned int sleep(unsigned int seconds) { + Sleep(seconds * 1000); + return 0; +} +#endif + +// mingw64 seems to define timespec (though mingw.org mingw doesn't), +// protected by the _TIMESPEC_DEFINED macro. +#ifndef _TIMESPEC_DEFINED +struct timespec { + int tv_sec; + int tv_nsec; +}; +#endif + +#ifndef HAVE_DECL_NANOSLEEP +#define HAVE_DECL_NANOSLEEP 0 +#endif + +// latest mingw64 has nanosleep. Earlier mingw and MSVC do not +#if !HAVE_DECL_NANOSLEEP +inline int nanosleep(const struct timespec *req, struct timespec *rem) { + Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000); + return 0; +} +#endif + +#ifndef __MINGW32__ +#if defined(_MSC_VER) && _MSC_VER < 1800 +inline long long int strtoll(const char *nptr, char **endptr, int base) { + return _strtoi64(nptr, endptr, base); +} +inline unsigned long long int strtoull(const char *nptr, char **endptr, + int base) { + return _strtoui64(nptr, endptr, base); +} +inline long long int strtoq(const char *nptr, char **endptr, int base) { + return _strtoi64(nptr, endptr, base); +} +#endif +inline unsigned long long int strtouq(const char *nptr, char **endptr, + int base) { + return _strtoui64(nptr, endptr, base); +} +inline long long atoll(const char *nptr) { + return _atoi64(nptr); +} +#endif + +#define __THROW throw() + +/* ----------------------------------- TCMALLOC-SPECIFIC */ + +/* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */ +extern void PatchWindowsFunctions(); + +#endif /* _WIN32 */ + +#undef inline +#undef EXTERN_C + +#endif /* GOOGLE_BASE_WINDOWS_H_ */ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.cc new file mode 100644 index 000000000..5b5fc35b1 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.cc @@ -0,0 +1,736 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 + * Author: Scott Francis + * + * 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 +#define ASM_JMP32ABS_0 0xFF +#define ASM_JMP32ABS_1 0x25 +#define ASM_JMP8REL 0xEB +#define ASM_JCC32REL_0 0x0F +#define ASM_JCC32REL_1_MASK 0x80 +#define ASM_NOP 0x90 +// X64 opcodes +#define ASM_REXW 0x48 +#define ASM_MOVRAX_IMM 0xB8 +#define ASM_JMP 0xFF +#define ASM_JMP_RAX 0xE0 + +namespace sidestep { + +PreamblePatcher::PreamblePage* PreamblePatcher::preamble_pages_ = NULL; +long PreamblePatcher::granularity_ = 0; +long PreamblePatcher::pagesize_ = 0; +bool PreamblePatcher::initialized_ = false; + +static const unsigned int kPreamblePageMagic = 0x4347414D; // "MAGC" + +// Handle 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_JMP32*. For +// instance, malloc() might be implemented as a JMP to __malloc(). +// This function follows the initial JMPs for us, until we get to the +// place where the actual code is defined. If we get to STOP_BEFORE, +// we return the address before stop_before. The stop_before_trampoline +// flag is used in 64-bit mode. If true, we will return the address +// before a trampoline is detected. Trampolines are defined as: +// +// nop +// mov rax, +// jmp rax +// +// See PreamblePatcher::RawPatchWithStub for more information. +void* PreamblePatcher::ResolveTargetImpl(unsigned char* target, + unsigned char* stop_before, + bool stop_before_trampoline) { + if (target == NULL) + return NULL; + while (1) { + unsigned char* new_target; + 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 + SIDESTEP_ASSERT(sizeof(relative_offset) == 4); + memcpy(reinterpret_cast(&relative_offset), + reinterpret_cast(target + 1), 4); + new_target = target + 5 + relative_offset; + } else if (target[0] == ASM_JMP8REL) { + // Visual Studio 7.1 implements new[] as an 8 bit jump to new + signed char relative_offset; + memcpy(reinterpret_cast(&relative_offset), + reinterpret_cast(target + 1), 1); + new_target = target + 2 + relative_offset; + } else if (target[0] == ASM_JMP32ABS_0 && + target[1] == ASM_JMP32ABS_1) { + jmp32rel: + // Visual studio seems to sometimes do it this way instead of the + // previous way. Not sure what the rules are, but it was happening + // with operator new in some binaries. + void** new_target_v; + if (kIs64BitBinary) { + // In 64-bit mode JMPs are RIP-relative, not absolute + int target_offset; + memcpy(reinterpret_cast(&target_offset), + reinterpret_cast(target + 2), 4); + new_target_v = reinterpret_cast(target + target_offset + 6); + } else { + SIDESTEP_ASSERT(sizeof(new_target) == 4); + memcpy(&new_target_v, reinterpret_cast(target + 2), 4); + } + new_target = reinterpret_cast(*new_target_v); + } else if (kIs64BitBinary && target[0] == ASM_REXW + && target[1] == ASM_JMP32ABS_0 + && target[2] == ASM_JMP32ABS_1) { + // in Visual Studio 2012 we're seeing jump like that: + // rex.W jmpq *0x11d019(%rip) + // + // according to docs I have, rex prefix is actually unneeded and + // can be ignored. I.e. docs say for jumps like that operand + // already defaults to 64-bit. But clearly it breaks abs. jump + // detection above and we just skip rex + target++; + goto jmp32rel; + } else { + break; + } + if (new_target == stop_before) + break; + if (stop_before_trampoline && *new_target == ASM_NOP + && new_target[1] == ASM_REXW && new_target[2] == ASM_MOVRAX_IMM) + break; + target = new_target; + } + return target; +} + +// Special case scoped_ptr to avoid dependency on scoped_ptr below. +class DeleteUnsignedCharArray { + public: + DeleteUnsignedCharArray(unsigned char* array) : array_(array) { + } + + ~DeleteUnsignedCharArray() { + if (array_) { + PreamblePatcher::FreePreambleBlock(array_); + } + } + + unsigned char* Release() { + unsigned char* temp = array_; + array_ = NULL; + return temp; + } + + private: + unsigned char* array_; +}; + +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(target_function), + MAX_PREAMBLE_STUB_SIZE, + PAGE_EXECUTE_READWRITE, + &old_target_function_protect); + if (!succeeded) { + SIDESTEP_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); + + // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of + // pTargetFunction to what they were before we started goofing around. + // We do this regardless of whether the patch succeeded or not. + succeeded = ::VirtualProtect(reinterpret_cast(target_function), + MAX_PREAMBLE_STUB_SIZE, + old_target_function_protect, + &old_target_function_protect); + if (!succeeded) { + SIDESTEP_ASSERT(false && + "Failed to restore protection to target function."); + // We must not return an error here because the function has + // likely actually been patched, and returning an error might + // cause our client code not to unpatch it. So we just keep + // going. + } + + if (SIDESTEP_SUCCESS != error_code) { // Testing RawPatchWithStub, above + SIDESTEP_ASSERT(false); + return error_code; + } + + // 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) { + SIDESTEP_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) { + SIDESTEP_ASSERT(false && "Preconditions not met"); + return SIDESTEP_INVALID_PARAMETER; + } + + BOOL succeeded = FALSE; + + // 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. + void* new_target = ResolveTarget(target_function); + if (new_target != target_function) { + target_function = new_target; + } + + // In 64-bit mode, preamble_stub must be within 2GB of target function + // so that if target contains a jump, we can translate it. + unsigned char* preamble_stub = AllocPreambleBlockNear(target_function); + if (!preamble_stub) { + SIDESTEP_ASSERT(false && "Unable to allocate preamble-stub."); + return SIDESTEP_INSUFFICIENT_BUFFER; + } + + // Frees the array at end of scope. + DeleteUnsignedCharArray guard_preamble_stub(preamble_stub); + + SideStepError error_code = RawPatchWithStubAndProtections( + target_function, replacement_function, preamble_stub, + MAX_PREAMBLE_STUB_SIZE, NULL); + + if (SIDESTEP_SUCCESS != error_code) { + SIDESTEP_ASSERT(false); + return error_code; + } + + // 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) { + SIDESTEP_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. + } + + SIDESTEP_LOG("PreamblePatcher::RawPatch successfully patched."); + + // detach the scoped pointer so the memory is not freed + *original_function_stub = + reinterpret_cast(guard_preamble_stub.Release()); + return SIDESTEP_SUCCESS; +} + +SideStepError PreamblePatcher::Unpatch(void* target_function, + void* replacement_function, + void* original_function_stub) { + SIDESTEP_ASSERT(target_function && replacement_function && + original_function_stub); + if (!target_function || !replacement_function || + !original_function_stub) { + return SIDESTEP_INVALID_PARAMETER; + } + + // 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(target_function); + target = reinterpret_cast( + ResolveTargetImpl( + target, reinterpret_cast(replacement_function), + true)); + // We should end at the function we patched. When we patch, we insert + // a ASM_JMP32REL instruction, so look for that as a sanity check. + if (target[0] != ASM_JMP32REL) { + SIDESTEP_ASSERT(false && + "target_function does not look like it was patched."); + return SIDESTEP_INVALID_PARAMETER; + } + + const unsigned int kRequiredTargetPatchBytes = 5; + + // We need to be able to write to a process-local copy of the first + // kRequiredTargetPatchBytes bytes of target_function + DWORD old_target_function_protect = 0; + BOOL succeeded = ::VirtualProtect(reinterpret_cast(target), + kRequiredTargetPatchBytes, + PAGE_EXECUTE_READWRITE, + &old_target_function_protect); + if (!succeeded) { + SIDESTEP_ASSERT(false && "Failed to make page containing target function " + "copy-on-write."); + return SIDESTEP_ACCESS_DENIED; + } + + unsigned char* preamble_stub = reinterpret_cast( + original_function_stub); + + // Disassemble the preamble of stub and copy the bytes back to target. + // If we've done any conditional jumps in the preamble we need to convert + // them back to the original REL8 jumps in the target. + MiniDisassembler disassembler; + unsigned int preamble_bytes = 0; + unsigned int target_bytes = 0; + while (target_bytes < kRequiredTargetPatchBytes) { + unsigned int cur_bytes = 0; + InstructionType instruction_type = + disassembler.Disassemble(preamble_stub + preamble_bytes, cur_bytes); + if (IT_JUMP == instruction_type) { + unsigned int jump_bytes = 0; + SideStepError jump_ret = SIDESTEP_JUMP_INSTRUCTION; + if (IsNearConditionalJump(preamble_stub + preamble_bytes, cur_bytes) || + IsNearRelativeJump(preamble_stub + preamble_bytes, cur_bytes) || + IsNearAbsoluteCall(preamble_stub + preamble_bytes, cur_bytes) || + IsNearRelativeCall(preamble_stub + preamble_bytes, cur_bytes)) { + jump_ret = PatchNearJumpOrCall(preamble_stub + preamble_bytes, + cur_bytes, target + target_bytes, + &jump_bytes, MAX_PREAMBLE_STUB_SIZE); + } + if (jump_ret == SIDESTEP_JUMP_INSTRUCTION) { + SIDESTEP_ASSERT(false && + "Found unsupported jump instruction in stub!!"); + return SIDESTEP_UNSUPPORTED_INSTRUCTION; + } + target_bytes += jump_bytes; + } else if (IT_GENERIC == instruction_type) { + if (IsMovWithDisplacement(preamble_stub + preamble_bytes, cur_bytes)) { + unsigned int mov_bytes = 0; + if (PatchMovWithDisplacement(preamble_stub + preamble_bytes, cur_bytes, + target + target_bytes, &mov_bytes, + MAX_PREAMBLE_STUB_SIZE) + != SIDESTEP_SUCCESS) { + SIDESTEP_ASSERT(false && + "Found unsupported generic instruction in stub!!"); + return SIDESTEP_UNSUPPORTED_INSTRUCTION; + } + } else { + memcpy(reinterpret_cast(target + target_bytes), + reinterpret_cast(reinterpret_cast( + original_function_stub) + preamble_bytes), cur_bytes); + target_bytes += cur_bytes; + } + } else { + SIDESTEP_ASSERT(false && + "Found unsupported instruction in stub!!"); + return SIDESTEP_UNSUPPORTED_INSTRUCTION; + } + preamble_bytes += cur_bytes; + } + + FreePreambleBlock(reinterpret_cast(original_function_stub)); + + // Restore the protection of the first kRequiredTargetPatchBytes bytes of + // target to what they were before we started goofing around. + succeeded = ::VirtualProtect(reinterpret_cast(target), + kRequiredTargetPatchBytes, + 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) { + SIDESTEP_ASSERT(false && "Failed to flush instruction cache."); + return SIDESTEP_UNEXPECTED; + } + + SIDESTEP_LOG("PreamblePatcher::Unpatch successfully unpatched."); + return SIDESTEP_SUCCESS; +} + +void PreamblePatcher::Initialize() { + if (!initialized_) { + SYSTEM_INFO si = { 0 }; + ::GetSystemInfo(&si); + granularity_ = si.dwAllocationGranularity; + pagesize_ = si.dwPageSize; + initialized_ = true; + } +} + +unsigned char* PreamblePatcher::AllocPreambleBlockNear(void* target) { + PreamblePage* preamble_page = preamble_pages_; + while (preamble_page != NULL) { + if (preamble_page->free_ != NULL) { + __int64 val = reinterpret_cast<__int64>(preamble_page) - + reinterpret_cast<__int64>(target); + if ((val > 0 && val + pagesize_ <= INT_MAX) || + (val < 0 && val >= INT_MIN)) { + break; + } + } + preamble_page = preamble_page->next_; + } + + // The free_ member of the page is used to store the next available block + // of memory to use or NULL if there are no chunks available, in which case + // we'll allocate a new page. + if (preamble_page == NULL || preamble_page->free_ == NULL) { + // Create a new preamble page and initialize the free list + preamble_page = reinterpret_cast(AllocPageNear(target)); + SIDESTEP_ASSERT(preamble_page != NULL && "Could not allocate page!"); + void** pp = &preamble_page->free_; + unsigned char* ptr = reinterpret_cast(preamble_page) + + MAX_PREAMBLE_STUB_SIZE; + unsigned char* limit = reinterpret_cast(preamble_page) + + pagesize_; + while (ptr < limit) { + *pp = ptr; + pp = reinterpret_cast(ptr); + ptr += MAX_PREAMBLE_STUB_SIZE; + } + *pp = NULL; + // Insert the new page into the list + preamble_page->magic_ = kPreamblePageMagic; + preamble_page->next_ = preamble_pages_; + preamble_pages_ = preamble_page; + } + unsigned char* ret = reinterpret_cast(preamble_page->free_); + preamble_page->free_ = *(reinterpret_cast(preamble_page->free_)); + return ret; +} + +void PreamblePatcher::FreePreambleBlock(unsigned char* block) { + SIDESTEP_ASSERT(block != NULL); + SIDESTEP_ASSERT(granularity_ != 0); + uintptr_t ptr = reinterpret_cast(block); + ptr -= ptr & (granularity_ - 1); + PreamblePage* preamble_page = reinterpret_cast(ptr); + SIDESTEP_ASSERT(preamble_page->magic_ == kPreamblePageMagic); + *(reinterpret_cast(block)) = preamble_page->free_; + preamble_page->free_ = block; +} + +void* PreamblePatcher::AllocPageNear(void* target) { + MEMORY_BASIC_INFORMATION mbi = { 0 }; + if (!::VirtualQuery(target, &mbi, sizeof(mbi))) { + SIDESTEP_ASSERT(false && "VirtualQuery failed on target address"); + return 0; + } + if (initialized_ == false) { + PreamblePatcher::Initialize(); + SIDESTEP_ASSERT(initialized_); + } + void* pv = NULL; + unsigned char* allocation_base = reinterpret_cast( + mbi.AllocationBase); + __int64 i = 1; + bool high_target = reinterpret_cast<__int64>(target) > UINT_MAX; + while (pv == NULL) { + __int64 val = reinterpret_cast<__int64>(allocation_base) - + (i * granularity_); + if (high_target && + reinterpret_cast<__int64>(target) - val > INT_MAX) { + // We're further than 2GB from the target + break; + } else if (val <= 0) { + // Less than 0 + break; + } + pv = ::VirtualAlloc(reinterpret_cast(allocation_base - + (i++ * granularity_)), + pagesize_, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + } + + // We couldn't allocate low, try to allocate high + if (pv == NULL) { + i = 1; + // Round up to the next multiple of page granularity + allocation_base = reinterpret_cast( + (reinterpret_cast<__int64>(target) & + (~(granularity_ - 1))) + granularity_); + while (pv == NULL) { + __int64 val = reinterpret_cast<__int64>(allocation_base) + + (i * granularity_) - reinterpret_cast<__int64>(target); + if (val > INT_MAX || val < 0) { + // We're too far or we overflowed + break; + } + pv = ::VirtualAlloc(reinterpret_cast(allocation_base + + (i++ * granularity_)), + pagesize_, MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + } + } + return pv; +} + +bool PreamblePatcher::IsShortConditionalJump( + unsigned char* target, + unsigned int instruction_size) { + return (*(target) & 0x70) == 0x70 && instruction_size == 2; +} + +bool PreamblePatcher::IsShortJump( + unsigned char* target, + unsigned int instruction_size) { + return target[0] == 0xeb && instruction_size == 2; +} + +bool PreamblePatcher::IsNearConditionalJump( + unsigned char* target, + unsigned int instruction_size) { + return *(target) == 0xf && (*(target + 1) & 0x80) == 0x80 && + instruction_size == 6; +} + +bool PreamblePatcher::IsNearRelativeJump( + unsigned char* target, + unsigned int instruction_size) { + return *(target) == 0xe9 && instruction_size == 5; +} + +bool PreamblePatcher::IsNearAbsoluteCall( + unsigned char* target, + unsigned int instruction_size) { + return *(target) == 0xff && (*(target + 1) & 0x10) == 0x10 && + instruction_size == 6; +} + +bool PreamblePatcher::IsNearRelativeCall( + unsigned char* target, + unsigned int instruction_size) { + return *(target) == 0xe8 && instruction_size == 5; +} + +bool PreamblePatcher::IsMovWithDisplacement( + unsigned char* target, + unsigned int instruction_size) { + // In this case, the ModRM byte's mod field will be 0 and r/m will be 101b (5) + return instruction_size == 7 && *target == 0x48 && *(target + 1) == 0x8b && + (*(target + 2) >> 6) == 0 && (*(target + 2) & 0x7) == 5; +} + +SideStepError PreamblePatcher::PatchShortConditionalJump( + unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size) { + // note: rel8 offset is signed. Thus we need to ask for signed char + // to negative offsets right + unsigned char* original_jump_dest = (source + 2) + static_cast(source[1]); + unsigned char* stub_jump_from = target + 6; + __int64 fixup_jump_offset = original_jump_dest - stub_jump_from; + if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) { + SIDESTEP_ASSERT(false && + "Unable to fix up short jump because target" + " is too far away."); + return SIDESTEP_JUMP_INSTRUCTION; + } + + *target_bytes = 6; + if (target_size > *target_bytes) { + // Convert the short jump to a near jump. + // + // 0f 8x xx xx xx xx = Jcc rel32off + unsigned short jmpcode = ((0x80 | (source[0] & 0xf)) << 8) | 0x0f; + memcpy(reinterpret_cast(target), + reinterpret_cast(&jmpcode), 2); + memcpy(reinterpret_cast(target + 2), + reinterpret_cast(&fixup_jump_offset), 4); + } + + return SIDESTEP_SUCCESS; +} + +SideStepError PreamblePatcher::PatchShortJump( + unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size) { + // note: rel8 offset is _signed_. Thus we need signed char here. + unsigned char* original_jump_dest = (source + 2) + static_cast(source[1]); + unsigned char* stub_jump_from = target + 5; + __int64 fixup_jump_offset = original_jump_dest - stub_jump_from; + if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) { + SIDESTEP_ASSERT(false && + "Unable to fix up short jump because target" + " is too far away."); + return SIDESTEP_JUMP_INSTRUCTION; + } + + *target_bytes = 5; + if (target_size > *target_bytes) { + // Convert the short jump to a near jump. + // + // e9 xx xx xx xx = jmp rel32off + target[0] = 0xe9; + memcpy(reinterpret_cast(target + 1), + reinterpret_cast(&fixup_jump_offset), 4); + } + + return SIDESTEP_SUCCESS; +} + +SideStepError PreamblePatcher::PatchNearJumpOrCall( + unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size) { + SIDESTEP_ASSERT(instruction_size == 5 || instruction_size == 6); + unsigned int jmp_offset_in_instruction = instruction_size == 5 ? 1 : 2; + unsigned char* original_jump_dest = reinterpret_cast( + reinterpret_cast<__int64>(source + instruction_size) + + *(reinterpret_cast(source + jmp_offset_in_instruction))); + unsigned char* stub_jump_from = target + instruction_size; + __int64 fixup_jump_offset = original_jump_dest - stub_jump_from; + if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) { + SIDESTEP_ASSERT(false && + "Unable to fix up near jump because target" + " is too far away."); + return SIDESTEP_JUMP_INSTRUCTION; + } + + if ((fixup_jump_offset < SCHAR_MAX && fixup_jump_offset > SCHAR_MIN)) { + *target_bytes = 2; + if (target_size > *target_bytes) { + // If the new offset is in range, use a short jump instead of a near jump. + if (source[0] == ASM_JCC32REL_0 && + (source[1] & ASM_JCC32REL_1_MASK) == ASM_JCC32REL_1_MASK) { + unsigned short jmpcode = (static_cast( + fixup_jump_offset) << 8) | (0x70 | (source[1] & 0xf)); + memcpy(reinterpret_cast(target), + reinterpret_cast(&jmpcode), + 2); + } else { + target[0] = ASM_JMP8REL; + target[1] = static_cast(fixup_jump_offset); + } + } + } else { + *target_bytes = instruction_size; + if (target_size > *target_bytes) { + memcpy(reinterpret_cast(target), + reinterpret_cast(source), + jmp_offset_in_instruction); + memcpy(reinterpret_cast(target + jmp_offset_in_instruction), + reinterpret_cast(&fixup_jump_offset), + 4); + } + } + + return SIDESTEP_SUCCESS; +} + +SideStepError PreamblePatcher::PatchMovWithDisplacement( + unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size) { + SIDESTEP_ASSERT(instruction_size == 7); + const int mov_offset_in_instruction = 3; // 0x48 0x8b 0x0d + unsigned char* original_mov_dest = reinterpret_cast( + reinterpret_cast<__int64>(source + instruction_size) + + *(reinterpret_cast(source + mov_offset_in_instruction))); + unsigned char* stub_mov_from = target + instruction_size; + __int64 fixup_mov_offset = original_mov_dest - stub_mov_from; + if (fixup_mov_offset > INT_MAX || fixup_mov_offset < INT_MIN) { + SIDESTEP_ASSERT(false && + "Unable to fix up near MOV because target is too far away."); + return SIDESTEP_UNEXPECTED; + } + *target_bytes = instruction_size; + if (target_size > *target_bytes) { + memcpy(reinterpret_cast(target), + reinterpret_cast(source), + mov_offset_in_instruction); + memcpy(reinterpret_cast(target + mov_offset_in_instruction), + reinterpret_cast(&fixup_mov_offset), + 4); + } + return SIDESTEP_SUCCESS; +} + +}; // namespace sidestep diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.h b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.h new file mode 100644 index 000000000..701e57068 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher.h @@ -0,0 +1,620 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 + * Author: Scott Francis + * + * Definition of PreamblePatcher + */ + +#ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ +#define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ + +#include "config.h" +#include + +// compatibility shim +#include "base/logging.h" +#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) +#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) + +// 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 :) +#ifdef _M_X64 +// In 64-bit mode we may need more room. In 64-bit mode all jumps must be +// within +/-2GB of RIP. Because of this limitation we may need to use a +// trampoline to jump to the replacement function if it is further than 2GB +// away from the target. The trampoline is 14 bytes. +// +// So 4 bytes + max instruction size (17 bytes) + 5 bytes to jump back to the +// original code + trampoline size. 64 bytes is a nice number :-) +#define MAX_PREAMBLE_STUB_SIZE (64) +#else +#define MAX_PREAMBLE_STUB_SIZE (32) +#endif + +// Determines if this is a 64-bit binary. +#ifdef _M_X64 +static const bool kIs64BitBinary = true; +#else +static const bool kIs64BitBinary = false; +#endif + +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, +}; + +#define SIDESTEP_TO_HRESULT(error) \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) + +class DeleteUnsignedCharArray; + +// 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.cc 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_test.cc for an example. +class PERFTOOLS_DLL_DECL 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 + static SideStepError Patch(T target_function, + T replacement_function, + T* original_function_stub) { + // NOTE: casting from a function to a pointer is contra the C++ + // spec. It's not safe on IA64, but is on i386. We use + // a C-style cast here to emphasize this is not legal C++. + return RawPatch((void*)(target_function), + (void*)(replacement_function), + (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 + static SideStepError Patch(LPCTSTR module_name, + LPCSTR function_name, + T replacement_function, + T* original_function_stub) { + SIDESTEP_ASSERT(module_name && function_name); + if (!module_name || !function_name) { + SIDESTEP_ASSERT(false && + "You must specify a module name and function name."); + return SIDESTEP_INVALID_PARAMETER; + } + HMODULE module = ::GetModuleHandle(module_name); + SIDESTEP_ASSERT(module != NULL); + if (!module) { + SIDESTEP_ASSERT(false && "Invalid module name."); + return SIDESTEP_NO_SUCH_MODULE; + } + FARPROC existing_function = ::GetProcAddress(module, function_name); + if (!existing_function) { + SIDESTEP_ASSERT( + false && "Did not find any function with that name in the module."); + return SIDESTEP_NO_SUCH_FUNCTION; + } + // NOTE: casting from a function to a pointer is contra the C++ + // spec. It's not safe on IA64, but is on i386. We use + // a C-style cast here to emphasize this is not legal C++. + return RawPatch((void*)existing_function, (void*)replacement_function, + (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 + // Patch(VirtualAlloc, MyVirtualAlloc, &origptr) + // 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); + + // A helper routine when patching, which follows jmp instructions at + // function addresses, to get to the "actual" function contents. + // This allows us to identify two functions that are at different + // addresses but actually resolve to the same code. + // + // @param target_function Pointer to a function. + // + // @return Either target_function (the input parameter), or if + // target_function's body consists entirely of a JMP instruction, + // the address it JMPs to (or more precisely, the address at the end + // of a chain of JMPs). + template + static T ResolveTarget(T target_function) { + return (T)ResolveTargetImpl((unsigned char*)target_function, NULL); + } + + // Allocates a block of memory of size MAX_PREAMBLE_STUB_SIZE that is as + // close (within 2GB) as possible to target. This is done to ensure that + // we can perform a relative jump from target to a trampoline if the + // replacement function is > +-2GB from target. This means that we only need + // to patch 5 bytes in the target function. + // + // @param target Pointer to target function. + // + // @return Returns a block of memory of size MAX_PREAMBLE_STUB_SIZE that can + // be used to store a function preamble block. + static unsigned char* AllocPreambleBlockNear(void* target); + + // Frees a block allocated by AllocPreambleBlockNear. + // + // @param block Block that was returned by AllocPreambleBlockNear. + static void FreePreambleBlock(unsigned char* block); + + private: + friend class DeleteUnsignedCharArray; + + // Used to store data allocated for preamble stubs + struct PreamblePage { + unsigned int magic_; + PreamblePage* next_; + // This member points to a linked list of free blocks within the page + // or NULL if at the end + void* free_; + }; + + // In 64-bit mode, the replacement function must be within 2GB of the original + // target in order to only require 5 bytes for the function patch. To meet + // this requirement we're creating an allocator within this class to + // allocate blocks that are within 2GB of a given target. This member is the + // head of a linked list of pages used to allocate blocks that are within + // 2GB of the target. + static PreamblePage* preamble_pages_; + + // Page granularity + static long granularity_; + + // Page size + static long pagesize_; + + // Determines if the patcher has been initialized. + static bool initialized_; + + // Used to initialize static members. + static void Initialize(); + + // 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 work. Defined in + // preamble_patcher_with_stub.cc. + // + // @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 RawPatchWithStub(void* target_function, + void* replacement_function, + unsigned char* preamble_stub, + unsigned long stub_size, + unsigned long* bytes_needed); + + + // A helper routine when patching, which follows jmp instructions at + // function addresses, to get to the "actual" function contents. + // This allows us to identify two functions that are at different + // addresses but actually resolve to the same code. + // + // @param target_function Pointer to a function. + // + // @param stop_before If, when following JMP instructions from + // target_function, we get to the address stop, we return + // immediately, the address that jumps to stop_before. + // + // @param stop_before_trampoline When following JMP instructions from + // target_function, stop before a trampoline is detected. See comment in + // PreamblePatcher::RawPatchWithStub for more information. This parameter + // has no effect in 32-bit mode. + // + // @return Either target_function (the input parameter), or if + // target_function's body consists entirely of a JMP instruction, + // the address it JMPs to (or more precisely, the address at the end + // of a chain of JMPs). + static void* ResolveTargetImpl(unsigned char* target_function, + unsigned char* stop_before, + bool stop_before_trampoline = false); + + // Helper routine that attempts to allocate a page as close (within 2GB) + // as possible to target. + // + // @param target Pointer to target function. + // + // @return Returns an address that is within 2GB of target. + static void* AllocPageNear(void* target); + + // Helper routine that determines if a target instruction is a short + // conditional jump. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a short conditional jump. + static bool IsShortConditionalJump(unsigned char* target, + unsigned int instruction_size); + + static bool IsShortJump(unsigned char *target, unsigned int instruction_size); + + // Helper routine that determines if a target instruction is a near + // conditional jump. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a near conditional jump. + static bool IsNearConditionalJump(unsigned char* target, + unsigned int instruction_size); + + // Helper routine that determines if a target instruction is a near + // relative jump. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a near absolute jump. + static bool IsNearRelativeJump(unsigned char* target, + unsigned int instruction_size); + + // Helper routine that determines if a target instruction is a near + // absolute call. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a near absolute call. + static bool IsNearAbsoluteCall(unsigned char* target, + unsigned int instruction_size); + + // Helper routine that determines if a target instruction is a near + // absolute call. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a near absolute call. + static bool IsNearRelativeCall(unsigned char* target, + unsigned int instruction_size); + + // Helper routine that determines if a target instruction is a 64-bit MOV + // that uses a RIP-relative displacement. + // + // @param target Pointer to instruction. + // + // @param instruction_size Size of the instruction in bytes. + // + // @return Returns true if the instruction is a MOV with displacement. + static bool IsMovWithDisplacement(unsigned char* target, + unsigned int instruction_size); + + // Helper routine that converts a short conditional jump instruction + // to a near conditional jump in a target buffer. Note that the target + // buffer must be within 2GB of the source for the near jump to work. + // + // A short conditional jump instruction is in the format: + // 7x xx = Jcc rel8off + // + // @param source Pointer to instruction. + // + // @param instruction_size Size of the instruction. + // + // @param target Target buffer to write the new instruction. + // + // @param target_bytes Pointer to a buffer that contains the size + // of the target instruction, in bytes. + // + // @param target_size Size of the target buffer. + // + // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. + static SideStepError PatchShortConditionalJump(unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size); + + static SideStepError PatchShortJump(unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size); + + // Helper routine that converts an instruction that will convert various + // jump-like instructions to corresponding instructions in the target buffer. + // What this routine does is fix up the relative offsets contained in jump + // instructions to point back to the original target routine. Like with + // PatchShortConditionalJump, the target buffer must be within 2GB of the + // source. + // + // We currently handle the following instructions: + // + // E9 xx xx xx xx = JMP rel32off + // 0F 8x xx xx xx xx = Jcc rel32off + // FF /2 xx xx xx xx = CALL reg/mem32/mem64 + // E8 xx xx xx xx = CALL rel32off + // + // It should not be hard to update this function to support other + // instructions that jump to relative targets. + // + // @param source Pointer to instruction. + // + // @param instruction_size Size of the instruction. + // + // @param target Target buffer to write the new instruction. + // + // @param target_bytes Pointer to a buffer that contains the size + // of the target instruction, in bytes. + // + // @param target_size Size of the target buffer. + // + // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. + static SideStepError PatchNearJumpOrCall(unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size); + + // Helper routine that patches a 64-bit MOV instruction with a RIP-relative + // displacement. The target buffer must be within 2GB of the source. + // + // 48 8B 0D XX XX XX XX = MOV rel32off + // + // @param source Pointer to instruction. + // + // @param instruction_size Size of the instruction. + // + // @param target Target buffer to write the new instruction. + // + // @param target_bytes Pointer to a buffer that contains the size + // of the target instruction, in bytes. + // + // @param target_size Size of the target buffer. + // + // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. + static SideStepError PatchMovWithDisplacement(unsigned char* source, + unsigned int instruction_size, + unsigned char* target, + unsigned int* target_bytes, + unsigned int target_size); +}; + +}; // namespace sidestep + +#endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_test.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_test.cc new file mode 100644 index 000000000..f3e051131 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_test.cc @@ -0,0 +1,368 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2011, 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 + * Author: Scott Francis + * + * Unit tests for PreamblePatcher + */ + +#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 +#include + +// 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(IncrementNumber); + void * new_target = PreamblePatcher::ResolveTarget(target); + if (target != new_target) + target = new_target; + + while (1) { + sidestep::InstructionType instructionType = disassembler.Disassemble( + reinterpret_cast(target) + instruction_size, + instruction_size); + if (sidestep::IT_RETURN == instructionType) { + return true; + } + } +} + +bool TestPatchWithLongJump() { + original_function = NULL; + void *p = ::VirtualAlloc(reinterpret_cast(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(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(0x110000000); + void* p2 = reinterpret_cast(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/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_with_stub.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_with_stub.cc new file mode 100644 index 000000000..d2c896c90 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/preamble_patcher_with_stub.cc @@ -0,0 +1,302 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* 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 + * Author: Scott Francis + * + * 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 +#define ASM_NOP 0x90 +// X64 opcodes +#define ASM_MOVRAX_IMM 0xB8 +#define ASM_REXW 0x48 +#define ASM_JMP 0xFF +#define ASM_JMP_RAX 0xE0 +#define ASM_PUSH 0x68 +#define ASM_RET 0xC3 + +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)) { + SIDESTEP_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(target_function); + unsigned int required_trampoline_bytes = 0; + const unsigned int kRequiredStubJumpBytes = 5; + const unsigned int kRequiredTargetPatchBytes = 5; + + // Initialize the stub with INT3's just in case. + if (stub_size) { + memset(preamble_stub, 0xcc, stub_size); + } + if (kIs64BitBinary) { + // In 64-bit mode JMP instructions are always relative to RIP. If the + // replacement - target offset is > 2GB, we can't JMP to the replacement + // function. In this case, we're going to use a trampoline - that is, + // we're going to do a relative jump to a small chunk of code in the stub + // that will then do the absolute jump to the replacement function. By + // doing this, we only need to patch 5 bytes in the target function, as + // opposed to patching 12 bytes if we were to do an absolute jump. + // + // Note that the first byte of the trampoline is a NOP instruction. This + // is used as a trampoline signature that will be detected when unpatching + // the function. + // + // jmp + // + // trampoline: + // nop + // mov rax, + // jmp rax + // + __int64 replacement_target_offset = reinterpret_cast<__int64>( + replacement_function) - reinterpret_cast<__int64>(target) - 5; + if (replacement_target_offset > INT_MAX + || replacement_target_offset < INT_MIN) { + // The stub needs to be within 2GB of the target for the trampoline to + // work! + __int64 trampoline_offset = reinterpret_cast<__int64>(preamble_stub) + - reinterpret_cast<__int64>(target) - 5; + if (trampoline_offset > INT_MAX || trampoline_offset < INT_MIN) { + // We're screwed. + SIDESTEP_ASSERT(false + && "Preamble stub is too far from target to patch."); + return SIDESTEP_UNEXPECTED; + } + required_trampoline_bytes = 13; + } + } + + // 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; + unsigned int stub_bytes = 0; + while (preamble_bytes < kRequiredTargetPatchBytes) { + unsigned int cur_bytes = 0; + InstructionType instruction_type = + disassembler.Disassemble(target + preamble_bytes, cur_bytes); + if (IT_JUMP == instruction_type) { + unsigned int jump_bytes = 0; + SideStepError jump_ret = SIDESTEP_JUMP_INSTRUCTION; + if (IsShortConditionalJump(target + preamble_bytes, cur_bytes)) { + jump_ret = PatchShortConditionalJump(target + preamble_bytes, cur_bytes, + preamble_stub + stub_bytes, + &jump_bytes, + stub_size - stub_bytes); + } else if (IsShortJump(target + preamble_bytes, cur_bytes)) { + jump_ret = PatchShortJump(target + preamble_bytes, cur_bytes, + preamble_stub + stub_bytes, + &jump_bytes, + stub_size - stub_bytes); + } else if (IsNearConditionalJump(target + preamble_bytes, cur_bytes) || + IsNearRelativeJump(target + preamble_bytes, cur_bytes) || + IsNearAbsoluteCall(target + preamble_bytes, cur_bytes) || + IsNearRelativeCall(target + preamble_bytes, cur_bytes)) { + jump_ret = PatchNearJumpOrCall(target + preamble_bytes, cur_bytes, + preamble_stub + stub_bytes, &jump_bytes, + stub_size - stub_bytes); + } + if (jump_ret != SIDESTEP_SUCCESS) { + SIDESTEP_ASSERT(false && + "Unable to patch because there is an unhandled branch " + "instruction in the initial preamble bytes."); + return SIDESTEP_JUMP_INSTRUCTION; + } + stub_bytes += jump_bytes; + } else if (IT_RETURN == instruction_type) { + SIDESTEP_ASSERT(false && + "Unable to patch because function is too short"); + return SIDESTEP_FUNCTION_TOO_SMALL; + } else if (IT_GENERIC == instruction_type) { + if (IsMovWithDisplacement(target + preamble_bytes, cur_bytes)) { + unsigned int mov_bytes = 0; + if (PatchMovWithDisplacement(target + preamble_bytes, cur_bytes, + preamble_stub + stub_bytes, &mov_bytes, + stub_size - stub_bytes) + != SIDESTEP_SUCCESS) { + return SIDESTEP_UNSUPPORTED_INSTRUCTION; + } + stub_bytes += mov_bytes; + } else { + memcpy(reinterpret_cast(preamble_stub + stub_bytes), + reinterpret_cast(target + preamble_bytes), cur_bytes); + stub_bytes += cur_bytes; + } + } else { + SIDESTEP_ASSERT(false && + "Disassembler encountered unsupported instruction " + "(either unused or unknown"); + return SIDESTEP_UNSUPPORTED_INSTRUCTION; + } + preamble_bytes += cur_bytes; + } + + if (NULL != bytes_needed) + *bytes_needed = stub_bytes + kRequiredStubJumpBytes + + required_trampoline_bytes; + + // 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 + + // kRequiredStubJumpBytes (5) + required_trampoline_bytes (0 or 13) + if (stub_bytes + kRequiredStubJumpBytes + required_trampoline_bytes + > stub_size) { + SIDESTEP_ASSERT(false); + return SIDESTEP_INSUFFICIENT_BUFFER; + } + + // 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 +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + int relative_offset_to_target_rest + = ((reinterpret_cast(target) + preamble_bytes) - + (preamble_stub + stub_bytes + kRequiredStubJumpBytes)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + // jmp (Jump near, relative, displacement relative to next instruction) + preamble_stub[stub_bytes] = ASM_JMP32REL; + // copy the address + memcpy(reinterpret_cast(preamble_stub + stub_bytes + 1), + reinterpret_cast(&relative_offset_to_target_rest), 4); + + if (kIs64BitBinary && required_trampoline_bytes != 0) { + // Construct the trampoline + unsigned int trampoline_pos = stub_bytes + kRequiredStubJumpBytes; + preamble_stub[trampoline_pos] = ASM_NOP; + preamble_stub[trampoline_pos + 1] = ASM_REXW; + preamble_stub[trampoline_pos + 2] = ASM_MOVRAX_IMM; + memcpy(reinterpret_cast(preamble_stub + trampoline_pos + 3), + reinterpret_cast(&replacement_function), + sizeof(void *)); + preamble_stub[trampoline_pos + 11] = ASM_JMP; + preamble_stub[trampoline_pos + 12] = ASM_JMP_RAX; + + // Now update replacement_function to point to the trampoline + replacement_function = preamble_stub + trampoline_pos; + } + + // 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. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +#endif + int offset_to_replacement_function = + reinterpret_cast(replacement_function) - + reinterpret_cast(target) - 5; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + // complete the jmp instruction + memcpy(reinterpret_cast(target + 1), + reinterpret_cast(&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 > kRequiredTargetPatchBytes) { + memset(reinterpret_cast(target + kRequiredTargetPatchBytes), + ASM_INT3, preamble_bytes - kRequiredTargetPatchBytes); + } + + // 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. + // + // In 64-bit mode the memory pointed to by target_function *may* point to a + // relative jump instruction that jumps to a trampoline which will then + // perform an absolute jump to the replacement function. The preamble stub + // still contains the original target function's preamble code, followed by a + // jump back to the instructions after the first preamble bytes. + // + return SIDESTEP_SUCCESS; +} + +}; // namespace sidestep diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/shortproc.asm b/trunk/3rdparty/gperftools-2-fit/src/windows/shortproc.asm new file mode 100644 index 000000000..7e8e3d783 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/shortproc.asm @@ -0,0 +1,169 @@ +; Copyright (c) 2011, 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: Scott Francis +; +; Unit tests for PreamblePatcher + +.MODEL small + +.CODE + +TooShortFunction PROC + ret +TooShortFunction ENDP + +JumpShortCondFunction PROC + test cl, 1 + jnz jumpspot + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 + int 3 +jumpspot: + nop + nop + nop + nop + mov rax, 1 + ret +JumpShortCondFunction ENDP + +JumpNearCondFunction PROC + test cl, 1 + jnz jumpspot + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H +jumpspot: + nop + nop + mov rax, 1 + ret +JumpNearCondFunction ENDP + +JumpAbsoluteFunction PROC + test cl, 1 + jmp jumpspot + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H +jumpspot: + nop + nop + mov rax, 1 + ret +JumpAbsoluteFunction ENDP + +CallNearRelativeFunction PROC + test cl, 1 + call TooShortFunction + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + mov rdx, 0ffff1111H + nop + nop + nop + ret +CallNearRelativeFunction ENDP + +END diff --git a/trunk/3rdparty/gperftools-2-fit/src/windows/system-alloc.cc b/trunk/3rdparty/gperftools-2-fit/src/windows/system-alloc.cc new file mode 100644 index 000000000..bdd03921d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/src/windows/system-alloc.cc @@ -0,0 +1,205 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// Copyright (c) 2013, 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: Petr Hosek + +#ifndef _WIN32 +# error You should only be including windows/system-alloc.cc in a windows environment! +#endif + +#include +#include +#include // std::min +#include +#include "base/logging.h" +#include "base/spinlock.h" +#include "internal_logging.h" +#include "system-alloc.h" + +static SpinLock spinlock(SpinLock::LINKER_INITIALIZED); + +// The current system allocator declaration +SysAllocator* tcmalloc_sys_alloc = NULL; +// Number of bytes taken from system. +size_t TCMalloc_SystemTaken = 0; + +class VirtualSysAllocator : public SysAllocator { +public: + VirtualSysAllocator() : SysAllocator() { + } + void* Alloc(size_t size, size_t *actual_size, size_t alignment); +}; +static char virtual_space[sizeof(VirtualSysAllocator)]; + +// This is mostly like MmapSysAllocator::Alloc, except it does these weird +// munmap's in the middle of the page, which is forbidden in windows. +void* VirtualSysAllocator::Alloc(size_t size, size_t *actual_size, + size_t alignment) { + // Align on the pagesize boundary + const int pagesize = getpagesize(); + if (alignment < pagesize) alignment = pagesize; + size = ((size + alignment - 1) / alignment) * alignment; + + // Report the total number of bytes the OS actually delivered. This might be + // greater than |size| because of alignment concerns. The full size is + // necessary so that adjacent spans can be coalesced. + // TODO(antonm): proper processing of alignments + // in actual_size and decommitting. + if (actual_size) { + *actual_size = size; + } + + // We currently do not support alignments larger than the pagesize or + // alignments that are not multiples of the pagesize after being floored. + // If this ability is needed it can be done by the caller (assuming it knows + // the page size). + assert(alignment <= pagesize); + + void* result = VirtualAlloc(0, size, + MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + if (result == NULL) + return NULL; + + // If the result is not aligned memory fragmentation will result which can + // lead to pathological memory use. + assert((reinterpret_cast(result) & (alignment - 1)) == 0); + + return result; +} + +#ifdef _MSC_VER + +extern "C" SysAllocator* tc_get_sysalloc_override(SysAllocator *def); +extern "C" SysAllocator* tc_get_sysalloc_default(SysAllocator *def) +{ + return def; +} + +#if defined(_M_IX86) +#pragma comment(linker, "/alternatename:_tc_get_sysalloc_override=_tc_get_sysalloc_default") +#elif defined(_M_X64) +#pragma comment(linker, "/alternatename:tc_get_sysalloc_override=tc_get_sysalloc_default") +#endif + +#else // !_MSC_VER + +extern "C" ATTRIBUTE_NOINLINE +SysAllocator* tc_get_sysalloc_override(SysAllocator *def) +{ + return def; +} + +#endif + +static bool system_alloc_inited = false; +void InitSystemAllocators(void) { + VirtualSysAllocator *alloc = new (virtual_space) VirtualSysAllocator(); + tcmalloc_sys_alloc = tc_get_sysalloc_override(alloc); +} + +extern PERFTOOLS_DLL_DECL +void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, + size_t alignment) { + SpinLockHolder lock_holder(&spinlock); + + if (!system_alloc_inited) { + InitSystemAllocators(); + system_alloc_inited = true; + } + + void* result = tcmalloc_sys_alloc->Alloc(size, actual_size, alignment); + if (result != NULL) { + if (actual_size) { + TCMalloc_SystemTaken += *actual_size; + } else { + TCMalloc_SystemTaken += size; + } + } + return result; +} + +extern PERFTOOLS_DLL_DECL +bool TCMalloc_SystemRelease(void* start, size_t length) { + if (VirtualFree(start, length, MEM_DECOMMIT)) + return true; + + // The decommit may fail if the memory region consists of allocations + // from more than one call to VirtualAlloc. In this case, fall back to + // using VirtualQuery to retrieve the allocation boundaries and decommit + // them each individually. + + char* ptr = static_cast(start); + char* end = ptr + length; + MEMORY_BASIC_INFORMATION info; + while (ptr < end) { + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); + assert(resultSize == sizeof(info)); + size_t decommitSize = std::min(info.RegionSize, end - ptr); + BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT); + assert(success == TRUE); + ptr += decommitSize; + } + + return true; +} + +extern PERFTOOLS_DLL_DECL +void TCMalloc_SystemCommit(void* start, size_t length) { + if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start) + return; + + // The commit may fail if the memory region consists of allocations + // from more than one call to VirtualAlloc. In this case, fall back to + // using VirtualQuery to retrieve the allocation boundaries and commit them + // each individually. + + char* ptr = static_cast(start); + char* end = ptr + length; + MEMORY_BASIC_INFORMATION info; + while (ptr < end) { + size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); + assert(resultSize == sizeof(info)); + + size_t commitSize = std::min(info.RegionSize, end - ptr); + void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, + PAGE_READWRITE); + assert(newAddress == ptr); + ptr += commitSize; + } +} + +bool RegisterSystemAllocator(SysAllocator *allocator, int priority) { + return false; // we don't allow registration on windows, right now +} + +void DumpSystemAllocatorStats(TCMalloc_Printer* printer) { + // We don't dump stats on windows, right now +} diff --git a/trunk/3rdparty/gperftools-2-fit/test-driver b/trunk/3rdparty/gperftools-2-fit/test-driver new file mode 100755 index 000000000..9759384aa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/test-driver @@ -0,0 +1,150 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 2011-2020 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/addr2line-pdb/addr2line-pdb.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/addr2line-pdb/addr2line-pdb.vcxproj new file mode 100644 index 000000000..4801616be --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/addr2line-pdb/addr2line-pdb.vcxproj @@ -0,0 +1,191 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {81CA712E-90B8-4AE5-9E89-5B436578D6DA} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + dbghelp.lib;%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/addressmap_unittest/addressmap_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/addressmap_unittest/addressmap_unittest.vcxproj new file mode 100644 index 000000000..de44f7417 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/addressmap_unittest/addressmap_unittest.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {32EECEB6-7D18-477E-BC7A-30CE98457A88} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj new file mode 100644 index 000000000..be6ebcf54 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {4AFFF21D-9D0A-410C-A7DB-7D21DA5166C0} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/frag_unittest/frag_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/frag_unittest/frag_unittest.vcxproj new file mode 100644 index 000000000..d4635829e --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/frag_unittest/frag_unittest.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {24754725-DE0D-4214-8979-324247AAD78E} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj new file mode 100644 index 000000000..1bd87bcc7 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcxproj @@ -0,0 +1,297 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} + Win32Proj + + + + DynamicLibrary + false + v140 + Unicode + true + + + StaticLibrary + false + v140 + Unicode + true + + + DynamicLibrary + false + v140 + Unicode + true + + + StaticLibrary + false + v140 + Unicode + true + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Windows + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Windows + true + true + + + + + WIN32_OVERRIDE_ALLOCATORS;PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Windows + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Windows + true + true + + + + + WIN32_OVERRIDE_ALLOCATORS;PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj new file mode 100644 index 000000000..8f1a22b53 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcxproj @@ -0,0 +1,238 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {A765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + true + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_extension_test/malloc_extension_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_extension_test/malloc_extension_test.vcxproj new file mode 100644 index 000000000..e1a891898 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_extension_test/malloc_extension_test.vcxproj @@ -0,0 +1,216 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {3765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_hook_test/malloc_hook_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_hook_test/malloc_hook_test.vcxproj new file mode 100644 index 000000000..8cfbf7a9b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/malloc_hook_test/malloc_hook_test.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {3765198D-AA05-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/markidle_unittest/markidle_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/markidle_unittest/markidle_unittest.vcxproj new file mode 100644 index 000000000..6294d5678 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/markidle_unittest/markidle_unittest.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/nm-pdb/nm-pdb.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/nm-pdb/nm-pdb.vcxproj new file mode 100644 index 000000000..ac6caeb8d --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/nm-pdb/nm-pdb.vcxproj @@ -0,0 +1,191 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {3A559C75-FD26-4300-B86B-165FD43EE1CE} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + dbghelp.lib;%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + dbghelp.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/packed-cache_test/packed-cache_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/packed-cache_test/packed-cache_test.vcxproj new file mode 100644 index 000000000..9f57d1959 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/packed-cache_test/packed-cache_test.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {605D3CED-B530-424E-B7D2-2A31F14FD570} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/page_heap_test/page_heap_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/page_heap_test/page_heap_test.vcxproj new file mode 100644 index 000000000..8503a0d05 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/page_heap_test/page_heap_test.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {9765198D-5305-4AB0-9A21-A0CD8201EB2B} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/pagemap_unittest/pagemap_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/pagemap_unittest/pagemap_unittest.vcxproj new file mode 100644 index 000000000..e5f267c7a --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/pagemap_unittest/pagemap_unittest.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {9765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj new file mode 100644 index 000000000..cf3daadc2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/preamble_patcher_test/preamble_patcher_test.vcxproj @@ -0,0 +1,234 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {5765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + $(OutDir)%(Filename).obj;%(Outputs) + $(OutDir)%(Filename).obj;%(Outputs) + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + ml64 /Fo"$(OutDir)%(Filename).obj" /c /Cx /coff "%(FullPath)" + $(OutDir)%(Filename).obj;%(Outputs) + $(OutDir)%(Filename).obj;%(Outputs) + $(OutDir)%(Filename).obj;%(Outputs) + $(OutDir)%(Filename).obj;%(Outputs) + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/realloc_unittest/realloc_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/realloc_unittest/realloc_unittest.vcxproj new file mode 100644 index 000000000..e16c02faa --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/realloc_unittest/realloc_unittest.vcxproj @@ -0,0 +1,214 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {4765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/sampler_test/sampler_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/sampler_test/sampler_test.vcxproj new file mode 100644 index 000000000..98d6bb40c --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/sampler_test/sampler_test.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {B765198D-5305-4AB0-9A21-A0CD8201EB2A} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj new file mode 100644 index 000000000..23de72683 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/stack_trace_table_test/stack_trace_table_test.vcxproj @@ -0,0 +1,214 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {A4754725-DE0D-4214-8979-324247AAD78E} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj new file mode 100644 index 000000000..a6dca2b11 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/system-alloc_unittest/system-alloc_unittest.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {387F753A-0312-4A7B-A1D6-B2795E832E96} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj new file mode 100644 index 000000000..dd0f686bc --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {2D8B9599-C74C-4298-B723-6CF6077563E3} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj new file mode 100644 index 000000000..96689fff2 --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {7CC73D97-C057-43A6-82EF-E6B567488D02} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2-fit/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj b/trunk/3rdparty/gperftools-2-fit/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj new file mode 100644 index 000000000..41f31c18b --- /dev/null +++ b/trunk/3rdparty/gperftools-2-fit/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release-Override + Win32 + + + Release-Override + x64 + + + Release-Patch + Win32 + + + Release-Patch + x64 + + + + true + {6CFFBD0F-09E3-4282-A711-0564451FDF74} + Win32Proj + + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + false + v140 + Unicode + true + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25431.1 + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + ..\..\src\windows;..\..\src;$(IncludePath) + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + _DEBUG;%(PreprocessorDefinitions) + Level3 + true + + + Console + __tcmalloc;%(ForceSymbolReferences) + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + NDEBUG;%(PreprocessorDefinitions) + Level3 + false + true + + + Console + true + true + __tcmalloc;%(ForceSymbolReferences) + + + + + PERFTOOLS_DLL_DECL=;NDEBUG;%(PreprocessorDefinitions) + Level3 + MultiThreaded + false + true + + + Console + true + true + + + + + + + + + + + + + + + {55e2b3ae-3ca1-4db6-97f7-0a044d6f446f} + false + + + + + + \ No newline at end of file diff --git a/trunk/3rdparty/gperftools-2.1.zip b/trunk/3rdparty/gperftools-2.1.zip deleted file mode 100644 index 49a01918f99bfd6caa3b0408c1412ef69c269ce3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1624882 zcmagDbF42wvn}}Bwr$(CZQJ(Qwr$(CZQHhO^K6~@?#m=M^X9&pPO4IWbXHd?sg>1L ziZURe(18Cs4MxAh|10>v9RdIsVBuiqWbR^bZ|h9QOwYuirV0fB=?;EZ`Y&_!fB^u3 z{@3OI@Z_ z$%3e9S3)<-TFeXP8(5Mo8~cKM)1-3kEu=jYz@ED|6Y7F4OUxq(GpsZuUauN`R!vN=sz)kZUve z7?0(sC$1K=E&L5rt$rm^k4Q)%M6{aHwT=wpu9qTC5-nz$ z;Pz!S9yQ|vM zTzup#Potxbep5E`c1i2k9>cgtPWb?QfnA@>>TS0fKBb9bqlN67h`VA3ZCuk$7K`P_ zU=QEttryb`EIrfO@EGN9qo#%41SPsLRMTC!lQ-y^V(%AMyd{CJc*#9j18jowWT~Bg zcG2_d*j=04V#kl^ieuhn#|f_;=3|9IpVlC6kg+zp(Z{Ey3T_}vWo+6YM8`i-q;T!f zG$xxPjuTz>MQ!7b_7mF3h6mWrRcAZtjEcwFZMwFHTQcc~uL`z+$kwWC#|U3_alAn# z!EGefPGtZC8@LV93#vKDIwxBfG|eg+BR1zq`-r>vT3MM=Yaa-eW>i;GqHqx63nM<_ z)=|M${BXue(ATon39FkoZbkC5?N zyvg|e{6^G6FxPvl%M)+vn5Qz$)|aisYjrg?R%ri4BgbB_i*s~gSV`-<3>6$6<#p+8%fhNIBkfNAnc-5bWv3C=#64FX zvWj?+&jtApwxPl6*`Pv4qixsph}fH7U zzelS3$i_L@xtu@!sM5P@MUkR>+~<||Lm=jGSHdSH$bI?23O$AbW~p??GP9PJR>Alb z-(ve5161sW=X%eFGi3YgZ_9ZswVg&v6x8liR^2=kVICgcK3-p=Ba|58!(mIeNc^ZuKrY-axauKkC!ynz4!y#JY|tp1pq zdC*(B*xCMnF;#5BwDm9}qS*Uq6w#MxBopY2>cN>312VR@`=XlCsUs=1gm~J&{=`&a z87dbRMh$L=Gh;OZgdnCGw^MaSSaMBd1iruQoE8u#R7Mla2x0H>+w0f-+Jk@vY#>eH z*Ou-5*`TYER(U#?iyK+cTPb#DvQ+kTmJ*JWQ+vhaoBb5>SD|0v zA-}&jpkSW2H~=4uroCu|@*`|_aF%Aw4acn_70aSmP!i|{)(LiPa_;?o9QC*0A< zItJlvgPKYi(pq5ipkW+6^c$ZMaaa@xN=3G7xPF47v9RdFB;dV;m8Y}mrW%Cf-X*6g<-z`3+gwFAIJr|}-9@|rw?np<{L*GGAH2z^=daOk)Xc>B4 zAkuET^rSyS+CJt@Dx15VUuVl9r#e6|c8T&5@NUYh%XBUI(sJ#paRIZKXXvq)(-_pg zY_rfSWlFoc)rt%>OdWbB2sO&9p`1%$yhyaWQ#5N`ePueg`-S+GRf(y`u<%o!NjB_o28dIIlCxgjObm6 z`98q(I!8K&MOv%R&(n7|i;WhAEA`w|6SeW!b3`wimJ-aHyedLb(sbkJo_5^o^V-vP z^}XL%Kh3!<7J8zeJ6G9tF!6zuM<1_uax-mYSe@NGxGf!KJTcNBjx29lku-DSIoH12R;P`ztUK2;< zNiRW`4S#OBJ3)Ni0~{;_4JrB!FEVN&ckZo5QEhE27Wa>IsJwMbO2nGP1Mn3oQ02e2 z1HhPexg}IO7^{4Klh3iMsnTWegPw$hG)1KHf{+u(MwC-oyFDFYf6uvQ2YA)5VVfXRr#!G>h-mvpR9+E$jd#QgjbL{um*@nE+QJ&N3{bQfMh>2Z3`VKoRl85H7{yvb0XGp z)5fTQQpr4cV^Mi0%L@oPG}a8yAw|o;XtA3-P;Vm=Tu0)5_EvQ zBp%!kw+BpLIA?MH!*$Kzen1J!pffVl-7wr>N*`Gel^2G%M%-@VZL7kroTkVv<_J*h zZ@M6wT{{(bz@{qB7<)iHn#fAPXQB3}5`(ZXFMQS{v&_O^lja|oR+e}VIKX7~5Lba;ob_{P$($nV`ALE&!%Q|l2;R%t z#=(W*fK^K3b0Xn3p|yl8g0y3JRmN?{`Ijv{a0|TEgHD#_8^UGBRc7uK%t`M^m|a3; znd?Ypg|*O7q%iV5DJ)hh2S}SJ@`WNq<7?>UmzMEEcRg+a942x zVbyCDj_wgbj6NUG-&Dr!QQ}Fn*gP(Nth`?2R~yE0o}-fE@&xF?C4s+N4qO+3E`o>q z4?u|E$_07lUc<7i2Zwy6pj?g}W*dphb9~(azgK5*QME#)VAWt1^vrEw>tc-jL~^}e z;flkkYH=({PBbwYi&HVn*sl<>`ICO4onr8va6d(+v`RJTq+DZO9+ZfX<`a*U)h(pj zk;XKN-BUMlYSM*igx7WUF7knysPGVV>y@z+1W8pBEYRlIieA(l4D|C1^mY0>eLVd= zeI8I7UfzCxpUzIV>HM(Tr6upIVPOz>?YOlzR$g`YA+!+zwnj~t_<1f%V47D2VhC}R z9qKk8db8D^nDq&73NIIHOlFr?R=UE&cAEtRfd_%pzD zf-j*Xs6h;*wh0riD~lZ~*m&+K1q*Ov2<%^38ux^&_5}Qk*CN4dBY&W6q1!5k3m@GM zW9%#X6=?JW#(0QF&bx_Nz?{nZb{3366ho z&oWhA$&kRe?0c7pM6y-Si>;J)P>NkyCjWRC0NA+7?@R}A-QoRvBd7f~yI*O(ARb?D zgL%{;DdbJ&gu(J7MeJYi4`kkorw=I(9$8_BZzULFcHT@ZzY2Y)lujzIj~nh*@;B#V zOyBHZL+5;wj)X?xJi+upl~(u@fMRpzLqsYM5E0Y;y8`UWBmz(#TS`d-Q0ZWEE*=rv1NXbivq%d&sJC9I=H{HlgI zqcq3rc9sW$!Qzb%E#%HyM<$|;Y2S-9>rL-sJD)$-O~2wEGxg1?NG;LEBjyNV8*FWuQmfzN%AyidScfx;PqqSe`E9H~RQLyIot!^$?C>0i#F zHz8QW6+g~uJYomYQX_D*4Z|HwuzZUNung&Y6*p39da9A(qy*5``gucj(UWXrf}&4KlfVQ6u1o6c^6IsGIgNMVJHb}z z!?3r<>Y@&iLpvM01-QvIix5-x_kc8?@z8p&g=Oe`ua+qD4=i8 zk#ZIVJuv?KgH(?9^PD?RmP3Wa*zZYNr=5&CLPeg!E^atZr$UqGND(8{``o!4fthN? zt4bOl=Tq62R2Gi+9?AXVa-=7u3(jXs^sk-l8L-%?V9yiz88m^?YKJ>HzETv~l2zw3 zmzSN`3Q>~t8wkn!e1cY}J^IEJaxA;dP~|=aV~px?dhH_)?t8!AWrf@&;7oGbY`R5F z|32|PKkwHc9BMQEURiPL#y-eaOtUTGLq*@^HF_@sKo!PKSvy*c7#i%?Wx0sjbebW& zIRQG3{!B_& zVYuv~(sRyLGQwspOQ}#jfg$ZY$!_V4&92EBa}4}$9GxptL+9U0-W~3L)E<&i;$_)^ zKn^5gJ0*4;RozT2I`bhg%g`0YEs#k5HS1@Nm8oTCp z%E#=HrEG<6@NEfJC9xa}Hk1Q~FQIaGno5;6VlTY&&*fog1Ox=Ll50fz-@v`Y*VFI*RBX(`(}iciQfh=;Em~51 z07P{o6%6HgwE7}8xH3JLi zgbp@C2&kB-d2olFUj;iHU~pj|La%7)Q;j-=PV}JgVQZHby1_ssO-%^PR-au>OOmMx zeyjnMRHLEE%5^CWh}{m~BWemb_btPF=gUQy2@HqtJ21GPi7+5F(6VB2RUF-Rm`ZK0 zzgG~Il?#|+*OCzNn2PvEbGKM35BWf(H6DoI4(lv&YxvIg)so|Kqy?l8_H*Gdz_Plvh4@}x1A}H$+tQ{To!nhkq@E!?~9+z?oiIaWyHyOZ~3}YN#B;-mpdXAhn8ZA0c3)>X7o606i*eV#t~9HOF*bY zHTKQ&5p*;2-%LxN_vh1g4Ge!Gc>j^u2l*ncNJUa>lh@U0oMq^H(zb9|rVHHUg}Aen zUq-YsCi%k#!Dyaw{3r5mwW5$uX0O{2R z>JNO~ObnY;xn+4&(fOh(CR&NekXGa@UIOuwTbxq}KouB=opS|Qp-0>VVmz^}^-Gex zzKSk+B4n2SnJ^WF;`svqWu5ovCL)b`kE-(^Dj?Q22JS#hL#nozaAG(%JmFX>9dBx^ z-F>Iz2p&+QA+RtO$^Yf(`+8T#_in__!lVP0$pJ{a1|);rzsh6Vgs*ma57_FkW}_@t3 ze}{Q{srSRS2dtSXqcVvccrZJ6B&eG0r&k{bhz9#J5)2s~vi)urLec65Tg*-+#G-Yf zqU@z)<`G9GeZ&cs_`~C2%Q6?3>O$T2=Y@==%J(M7b%<3P>BX08u8q80f$UdM7qz93hsT!j4L{dHxS#y zt2+lQ!ZC15F!9y_kpZu^xA_mme~%>oYkNai zEWJDd>YslVY8UgP@c#8F`W60z0@89#q|*k2DT_9ryt7M162tnHtkW1qLHqxBIClye zjOOq*KRKh<#({E7A3}bHMIJ0M#X8x~KFDSNA=RyRcj|{!H*oGW3LLl$9}lCXhQau@ zOhkR~i#p&NbO|81%f}h@5%G7|sK>=-g_SLIQlA+?|68_B8##`|etTaD%C`!CH_8by z0Z3V@Vq*5fJ~u2t0PiALfq;KKYyh=$blpQae!|s zo%1C910e6$vIc+zppwr$5zE40BWeq-t;39YA*YE~dtBi&3i5&(iC(hOSUl6;L1>1r zYn?I`K)+=SSGWMH))oT>g!hlf5aFv;<)l?iVZ;Wcj8!m0p$yn)`HEjzI^INIqIG3wr1A}1)2e)+xvWHoAY>1%`>X?OUkR;PR zX9(FI=UX)Vy&Dt_$pvw!W(Xt%t%6umQ^D@K-hBQ!SZo#?GcsX0nQ#H24q>=E#I*nv zNj4CnqM50V^o4B0TCyyfd37`V9z>F5yE-s|G2xNV#h?UgSLeCsd#HeXIO(CDu@(aH z&fQc_8p*xHUgUvfpwUH4kwjlzuoa9mBs0x&j?9g4&}ewQQkaN=$UqnJa=#V`5AZ5USKlY*Hu;EwBWQwE772$O zq<8L=)B;pP1!iRgtvV*AP#d|_XizzjaQSj9fr@`|iDz8{%dEECwb*4`4v;j`p$O*! znbMvS-TJ4dK;2@uMU`5Jxabv(8U^3tK@o?a{QLR_dd;Y0vquD2RK$#ss8vo*ODKi1 zhVuNfu3NMj55Rz8nJ!`>JA@lKD{f6;g$p5_d9`!6u?j_nA>KO9C8q#|pRknbaMna6 zh-jnBR0T*EA_p`{T!I^bGvbmUaNaK7+J2H0(oS*N@Jnrv31HGil?>l0r+#?N5=Edt zs9Gb?qCmNvk+@Tb59Im*eiL-9G0C=S^mLC{t-@KPRbi7yP(qXkR(z=0QPm2ji;eQH ztmMD%Xy|m?)g6@UG8=Iy#{qBH0vwSy#a^2@_0iHJgs$nJ{Kcc#C$5~6 z#J=B8#h=000Y6S1BKc_Y(zq+@z6Hpl8VH=WLpgEFfaeoS@D)`8L&(3bS*cw2F!=$? zAdBGGH$a;dL}k8l9`g6x)DU67p`Z@r+9a7-g;hda?XnTQ22W|g$lOn?`B4gtoFAI| zJSGF!CY;V0ZmnU(t1lbAxX47UUQ$d( zoGq4w_&iV+XjI>9G*AM+!V`x4hX>yStV*9XgtuT5#bmMaWxE4XGtuqE)z{6@3KaGR zi!b4VY?jM`p;|vKD_c}@eIRLYzZM+p99lAXamT1Nc&w+Eq&Icg;Vw|h{!SFy&ZTN8 zhhfTa#ycUNurA3U%M615BxY)00(=0L#I;>w<%MAkB*gFoV_(62e{OHY|H) z#lw1AB-{K*+%2wFVl9KDYnopL7sG^*UP7w1P6f`8%$z9~C={1BfsjjomVuw2pP;h$5MuRDVun4}GrvO=ibw35 z+?&=NRS?Yg&@A>@-%7mkfdVErC+%i15>_)J)ZkkFr9SYOqVYIzZQEb(ww^Zu08|6> z{Htt7sL@vC3W)t2v^#D_%}^_pr5{h;cg19hZV?|;3IgLg%Z{=({g_7+Rqge)d}?~- z*WML7<5*&z;4jQ7=FhxxIf^oh>vg&-{I{$d!w_$kjUpzUOaY(p_@8_KiR*ZBv~-%5|&&WIgaAMMytzQ{2)Rw$QR54RmM?lJ`lwd%Mu1H*il=?bR0U-5NTm7 z;pjNI;6IZ2iScyb#1aN(L@ctPtQZ_ZqsCheO92ozRY7Q{5{}?HyCh6@)U=CJ;sZq@ zVtz~+P}nWZjAF>zMi7I6gJC8r&g$<9g-_yKE&jv0!AoXVM{W?@2V5OOVeVrM9RAgtU~@f2$W zo-5+%JKEe;0#|t^?A26jB+Lzu(UO_T!UF=wrC#_i;;sBZR*wP<8JFL|kV&?`-l@@q zHz%Z|a3Z>=*rxmw<-$AVhR`obwGQE?*NT!RP-`LQWZ}vFX^!&dAb&dpDuD+n^i3Jp zCy{G?70vhte8l9S(VSq<{3VO_#*~D!%*sjAvy7Ps+Y;sqkkqTd;(m(;JKt{$;2@D) zaOumt0N?=oZrMfUd~Pq}UMx*CWw}Ah$k=ex)wfnTJ2n=Gy7+|%F=68uB|@0WBWj_( z;6@l395yz+Q5nenLAGPb5d!B$Xf?7tppT(HdYZP~_T+?{U0P3%R}YoAE=t%y*QIcH zGF~H8s$2(fHvwj#@NQMrki3Ex%jBG)J$Nn;8LP)P()Kq55V!6tP>_;vl)y|1CH76B zp=pb7kYEUcI)-ff&o5fvEDb{u#XTf3PgjcwjD{|OhYZkk&m_o@>Ms#P5~zH{(0>#X z6jzF48VE4ds-OMQj7b^;-{8cEg5bKut>llOx&C1x;$$UoKGUkeiOk2sI4H8yxmb(f z=#b-$v+$5zLg0`?=6XT|wI5XECp@M}?vKY1=NL6QN~*_{C=Z!mur1}mLsOY|mW@vi zItUal0K=e|#1biNnK|zh%qt-+nKFfmHhZW2xf4VXf-)BXn!8|TftrcQXd&!s z5<&oaf^q?o#kUrs2X;ab01zxPLUE&aOy1DMhs}x!@eVAUmqN{~yaMvl6X?v@Iq++U zavPb`LY6FRd@V`G;61%4DF|?_bpbQNG)%x2#02xnOJE}^$J(g0%FL>XO`3|4UO}xe zEQ!MFlzB~`%LKht7qwb)DMA5It(A!#dm| zoDr^&AR=Ik0BUzw7Q~~?sX;BtU73dme|A~$H1_M5z_ZDpCU+q4U+ZJQ=ka1&rWvZ4O>lc(UqS5ThKWCM9!}eH zT7h1}&Ae+7Q$U~HJ7Z!rWYPhJDculi1k8DpNj|7pypNA2KVAwjHs^pGnTTeaooC-a zGR5_E-ruFHb5NKSlLjkvNJC@O6uqaoKWAKFf2-RBQnt0ynGXroGmOZ}Up-PPgWTSmkJ`kv zx+-N)d^=$X*wb)sA+j$WxH;`&+)`-rbN6Yq|38z+wF` zz;iG#dd^(FAF+J3+)##k9mX&^0uF+g&U0uWwhN~^_KJ&iy0x`CZ)6r(b z6>3fLI^);MRK%7Y!UbJcDBLj+*NB8fiC0h6(W>F0_Bj5r!$aM?v@+mWxgDJs7I-HB zj1-16Yhqv>2rIeqBz(0{AGaIv_YmHPc;{%{!|gLn3QB-k(kg4?BM|ZAJj01vy&(nZ!1v<)}pwa|x5$hxP9dXl)&TPt|T z_jLSnW3CrX;F{E|Ly@xp#BXwv$_Oa={-{dbrY%gQ6<|4nG&Meu#vdS0En_<6@nrrW z)|@qg&RoQNv0K^{kI2m<+d&2&1#`+wAd*PzIUoDZ@irD*_C}D!M&L~sM1`XHQe5${ zoS(0=jk3gT-=Hs?PfU0V>t(uf>enqgBhV83V-&)ODV;`zQ2fC{KGJgTc&4SUigedo zSZp};TC9ZtPWFt;$MpSm(CJ;)YiA>9C)qgMkKn%g3qb}L8>*rHp2iXG8r)3~soxYY zG=f#y_mR(3?|b~i9-YAoH<4d1F21jnWO*^n%bE82`Lu+ znsA``22hVF9bF|-x3x35g%a_s2v0@fRv~zag0Lwg&CAaAyUT#F)eC@~t>;r5tQL)e zzXv}b?WgYq{;hWbMIGOe!z9Gn z3L#cG9O3GRj?;P9X+}ngUd;RdIx5P!^0!jYg7vE4&7U39w!e%$s;ifaZWtBC&Wb2% zRy2+M#5S=TC1XosUZ>E4nJ{i+vnUi7)w<2#3@V|qQ$T)jnH+oaVu}`4NvCuozl4MA zTJ^s8q>Kbv@%-kj=k zlD8=ZZL1KP;$VO0(06uI7#ahD@p!Z8dC|9nLG4GUZQH~~jw)#S0}t(K0=p`m#sqCn zMdt8v_KJ=3TIv&eIQJ&vG?f?|10fH26+81aWNwQM5kg<$=)~Xzn)p@$DsGMsxAGhq_k%*ksV&<6tBf=+nF3-nD*CRNpt*>2awAF8;3I;@Y zB{ky(ioQ9_se%mWopkl0BNZ2w0^{L%2q)A{hKa8!@o#K8$$>Q4&PM8OK(WB@U=$22 zzf&_g8xEEWf<>-_LJBm^A+W#bvw2jBeSC(y+pj~bOir+nk~Eh3AxOgY&!#z6YF9Lq zZ|ojO^<_)hFkltiq)nYu+9rgLSwS&!xE%hmWM-ff# zdj?XonmrgW$vxfBw>+bZ(q;W81`rRcY@I5Ori^SSG`Oai@+f9v10+0kfsB5r9E7r$ zCZQaCR;EQkdxY7!{1fP_uPU0w=omG>wMI@z3N8sApPq~Xcvgoh*~$T)qrAWIbXxTQ zQw^{`YLdBGG8OqT1e;W(b$QmpVt}oeh2`LTg03Rc0B+gCqgO`?0h0kH(sq89FojWYLh46Qq-HZQKdBUGDjICxC?r* z|FLDt0v#+&63o-+vIu9*{>arwm4rX^BsLWwtW&R*eT3#(KVKm_Cj8N0`DeyzGK zsmfO|bYVc9|Dk*<>apXPSugi95t;WE`nj99rMB<;K58p2u>`&6Eb&ozdyd%#x0AO} zd5S7(EiZy2zE!Y>=A{sSO&KGr)M|;UF?qM8+GZ7sLn{isu8P>|N*m}X$UcO~(6*%; zbABX_qKN|fCr5b_f$c|iv>ub8%~!)Offt1xV7kLIi*Vg9W`boFl+tMY8|ab)7z`u;uuQxH4*# z`VH;$3sBFe0e@q4&&-Hg~um|l4@iV zpcN`(<43<9t~?R;^bB~W7;46`Er+FEP?Y3Vb_-F8_=C3x!XJ?Xbp47#Q`TD^R@Dp2 z6-Txz3Es<#Gj0{G=O>X@L~lCMECERLTB=DCK&Wh@fVfYtOne*5ep-fi1&IUWP7|Wq zt`<`h*F7dV7K{wEbilSWa&b}sdYYao2&+(nPa6rMh!>?K8)#dB(i_Gu{+L%@&acjM zK$jWVgUAa)WwA|c9VJ;ITpcp424kriYe&OSD1l=98_j8TP*MgldGcai{^Y@4tocbk z*qy~a{}+jY5OlfL)kn>@zTRiAyYwK%LRm%CrQ)7?Kf~}O-fD}<0+bzG z2>h$4`*)Htj~pSgoMr9BVS4cI2og>vZvzLd{cDU-G#_lklvIVXmP!bF_8RpJ(sf^` zf_Tq*{L_{*$ADj%IFAbtI++_cdg?HeGDM|Td9r6-X&Z=g3?Oky4XG?SskNC)j4qdd zWsX8&;NE;ZX*}*Zqr)MVyO|M_SYaEzBQdlzw@U;s@!})`wGZK$O_@G;zF~PX+z!EO zSnm&KdzfUcB4%WVFJYtUD$H9L0cTB2#^3|`ZKgNsW^Ix6fiEq1nKfGtqLQ{ixf zc=e4gzg)?B@;ja;rx8%*4o`w41h%i3O(d1(YsV_jc8?SA85rUD>5k;wsG$(B7%?yW zb9et;>^Sd6vtj3soYzh^uMf# z+obbvM!OfT70kL0mPzswbHf+KY?N@0(-zerxW4tJ*KD0E@LXG|KF~;X3>)h33VN}M z34;uR@C?7l&V~Xs@gh*LJ^e(J!Fwa5zqw#R3HTk{mQNQ_|Mp%UGkh}?;ag-aGAx4v z4Osj>Vvpb3V#EKP8~CUE*zZg|+vEOwYUi0c&>7_B{7~dCB8zgG4})N;!FH0yAs{i4(Xe=p6a&L!(Qr^OoP^Tgx;*XS(yB2B`y2{i+U z|8Z!G7Pj_znJEME5Ps2N)DAKuDb;fJMm{^ZWwlh994zHlW8Zxz18d z{xYd*j*@dEP&T?0U_1zB(?jctxfQ5B;+pjOTKhVv*~VeK0eww6oU$wQi0XX@W;b&0 z>U_5-D_btY4VKj`Arh(#Yiopw=BbIzaBFmglPn_lX5+!ub;P1Fw^NwW-ll|T;gG10 z1(7JQAI$tCL!9hrMuDlH7qt0=0@jv2VWd)S6It)q3M3Bfs+v3S%*6Fb2HVgmf?&Nm zOY9R3@(2Yy8}0;BX87<844$s{0R(c(CRY26KPuNl_~(`td9nI{AeBBWJa*6xYf^y~ znb|FkylBRTnE$KcM&g@Gb7U7=6@w4qjag|4{De``;E&;A{@|-9KQcaxRb;GYhjJt2>C4*LGky*VP_vYQRsr$wQ;3_fkUp?%jsJ$a^(R0Or!K|g5v?rr})98d%O8k?U}QWA==lp0yd zK%WNQAnK0s*v`kA8CQec7$yPYBj@F1CqfFxn8Yq2`v+3Uh9viK6GwdV=on`Zm&P=f z8(xMvt2eiu@SnxW8(KXK)-W~TAeKra-jj^ybB|VZvR4fwS?iRw2~s&72d-=1n8?D< zSwqN{xaqe3cVKxg@fP$hSD(y4dl~t2Hvdw2GPGf(^7rA-Q??y{^zw|G_Q^-%yVt*) zAK4A?d+{h2FZ^@Os4}V>vY>Sj!0Y$8t^of-J{!z`?Dam52vJb=Ah;I!YWhP5BqFC? zD7mCEbupY?@D8z2e-{ni-}|j_vr0VPN0buj@a&UOU{D>L93L-dFV0S$u8wS7T%F() zJNdfNDb~}$jeC2PyMNnDxa`kcw^IgAG`V%=3|}e8{*oKN4<2KxmQV3v$HDEYcG#TI zM`_z|jPf#mHsF zAGZ7fv5jWzijVzckk|9$`0}((ZYeqI{7NSuq_HL-#O;UNM zee#{1nAOWyRP{;AGFd0mf)oGoi;6FstP zBPlZ0GGQ%o_|M=&=QDeyx{C}G8hVe_4fY^7sT;c0r`#S}O?0d$`f8_|m%$b(lSl(W zXM+3yy`%l&(KyS&n75DfY~nDFrImNzL!7)w#pjR(*vPBwAXu%vFa?_kTXgs5Nz zktbWK!AfVq+c%@RdgfyzC6Kpllx;i1?6~N$k;)oTOp(u0oq#9M)FZ`t%H(GyCtC*x zLM82W$O+{{`Hl{Pry;G|otSB(b&@@Uk1@|b<)Tt4LBj9(& z&tZI>Q=!DV|M}|re9vmub6M>$UU@#>jj@?iS#!K4)uI!kb9>Zz0DXS+rO{m|PvX%M z(N)FiRI&E$%Y}qO2yVx}D=vv{<4|o1i2sRn3CuOgX1(vmq*&zp!>ml#AVj&aW~@?G zZ5vIvX~TNVypFP*b$7O*6u|M)CA?a`iZ-Gd8)n zy#v`Q#0eRpEOW%tMhxVZWnpo2%h(8Y635Ac$?-_P^xgv2ANhKLZ;H7CSMXno`G>cg z@#*I2#o61**V}ci361AgAu=^Ic**q`=Sjo<^m6@Wqhb}NhanZ+Zja*Vp+{O=FAcFq zqVOXt79SW;`Z-ALdhdBU7y{*{h)w0l*cowoUd$o$bUKgo-4+6>>Iq7IuA3O zUPaYKy*gHsx!Zqa!iMWt_AJr`c4AJ3S0``3#@)88?aZi(mFk!Dh-|0_N4k|LiDTAz zFeW{sZsDsmY0FU)$;{#oO-^yCR^UC_(8fO=)$2Pl^*>(6NvLu3^8CmO^$?93!GIa_ zvSKT!vl@LQpbHA4_5;?=v1rL!X{lQKPBAIUEr8pD|QQEK@4_c z%We^ZSr-A17eZO6N#i1{<=K&VD9eH@78Z6TK>=qRg@m$#KkwoDw)1 z-n}|5*Ir*ZjG@$bm8O;3t27ciBHHF(&*wJ9Y3R?o!^^!&@0M(7|Fp9~P3j6O$+nfN z3b{@~8wamuNzBKm{4W-**{e`CoOOahzmnplO%aHP`EaO;)hZ>vbi)HY94E z^9k%6bbbNRIMcpIoG=5w0RSU!dEtzR$;)D&x;K(*ScMYf>g1mq#<aKOr?!cuE^r|x%@P=<#)K?jYaxZ0Qj2eq@}ui0$@ z%P^1{PP~PWa=cfZCJ_O}Gt)ohvJbLYNdV2?ZLS|+cAS&!&0{FkmE@P&;pm8exaHBa zj4UU-g=Y3Ot9WAa?#K9qv|c}DHgigZ)jH{dY2>!y#K@R)$u4f(2-}{h8@w+O6rXw( zSyO5ZuIujzl?V>v)Oe0{f70Txhp9u6$7Uiwb2qg2I_D=243q zh%9inTH#dArlvlk!*yNnAW-?vg6o>q^afak)XEx!XL6?gdbB`3+KKq=%Wd^QMiU!+ zgu&;Oc-l*6${uUur6kF;oa$G#-X0eL^Gb=;2-~`+yrZw8qMaM{LNc*kliSn}%NQ4$ zk9Ln;EAn|A)PXajQ>xlv=&a?sW(65oJ=z&c++(~y(g@jy3xNCFEEZhccWv~zNzlet zq_GMMMmXrH5D@MXky1hIqFz*yrO8E$ritvhsd5z2!|z&Bc<9E!Ml9;{BWR5>*UKs* zjiNvjFBz6A<9Vx-l|kUc?NHqu0YTS%F+~QD+ zh?3_6d}#qM8PZ*qZz#zuKI#KA^*qxicuWX*ccMo+A5F9mBptNrg;!Q$)~6^ot-pRG zStooLDO;aVjK&vLOIF7}cD6__UK0pDxgxM3LWdYx;Qoh*ey@2=lj~r4xU@B1UtS&o zs}@tb-8>W}{6$bH8|+~1cAM76zW(u|zd!QCK99N)z9se_@t;4CFF~BZXcqas#+ccY zT4sN9-FKN?^;VRH+S*~ifKK(Hsw|k_()1gu(ww;ZuO}4kIMMQOx(9)_R^F+8-^#P) z4FYQ^HU+l;-(#~Bu&D3&5^Wb9U>D1?@V;;(@%5{RyNNT$F{tV*Puo}=`w}7Lcs7+H zWi&3-Q(5VkF`w9tD_sxz-y3jSq`enED&K36-XPQv2&b+_Z{lN&X#1IVd|5L3Z<6nO z`Q`e9jHPLm{QC60@6a7nGup0_j63_MI%N-Z)c+S_?-V3T*ldZmZQHhO?zU~)wr%aU zZQHhO+jjTtebV-vh4)sN**uPIkZI|uc+*0*UBjaXIp}SloZF7g|>C04cf^-;V z9f8}v1>=_O^Q&|5E}yAIu_m#3?BMzbO=_)#2@t zP0)T_8ztNhOIl@=B#fFnLpFvkJt(W)BA!BJ6iFd5gc0Dq3X8-Mtwg1uRTbi7{uB}j z1@A2<;+-eR^UxkdyqYBwTZmGD+tdcRpO%AGJK_y4bB-M1h`;v0$~0(bcC}-RbEVH* zwcdX3c=g_Pzxvpna@w+`W8;bG0?`BaJ@O#@__^He^=EUt(dl$JTU%Riceps6&d}1* z;$mQ!+u7|lm`K^#(f|2o%r$}lpeRGZ1A+0sU&=dt2QFbA)jjV1n2wR@Z97%-y5)Wh z`#Z6}Og)OX!F_)Qk{jN#M(v^nW>jsr<90Zcz+0K^^GyHq9s>UB?t0yy^ogfw{~f#E zd#&en^`kb*_q|Xk<{UWZKy*59Sdbw_=9Q)e>qetfWb$qkO zPBZ$NWnV!IS9*jGV~@($-9@(_B;-J(!LRq%sGIhmu+?ijHg0sM!zz}wJ_feXggl?vrx4Ii z59h<6Z`JzSf><`7#hd4N<(=TP5d+$|D8xT*dn)myBpFx;71teyYwy9Dh*rnusp;S| zGI=R4K>mFR1#5MyN!}?a#Nd3 z<6ovCS#_>8#4}#NFrdU^uX&-$2tRX0c8O%47@G=!8;hAWbNu%ztuL z1aU^6g1{TmCG5Ce6Zj<<=qlC$s;_QY7I)8ERW&ptRnDNoDPIko&BE5zy-=V87!kGt zc!M;D3FD8QPS9tER>~MXs5M_?-P>46HPl{=A~8al`tJ23g+d}0%?t6WSk!0x5ZPa5 z5@K3?v>@wEO_kXFLjy3Pv^J4&VlZx20C8tslxM>;AVZLwViKpU7G4%IVhJ4i?>$?X zn36t-0_4q?UH_0U^&lLDy+dQ+IrGaQR8t{nfc+)KygB?AkaKr+SY`iVL2w`(VjR#< zp1rPo8znC!3bFci48eqIOJV>^KI@|X<}^ZC&8$#I0M256MX(kzL@)qq0ErGDQ>GNs zV*X<=5UT?Sl97qM41)y5t3=wpcz`?6JV1WPko7HRN0xn2KtcLHTJ~{`kV_0%U;vuo zyLm1zM5|=}s0E7OMWhhGu|gCwdA^{!!4@I@AbLnB5gr{?F&wxAT|#Kvl40|rav&IU zB4HJvo#TZkQ2AAhr7`ky6?ptE?8zmj`x4ysePIqLM^N$%O0g&h-aPq~R(%>ek$M}Z z*4RWKZnR!2Alqng0giJL02iKlK4^TN0Re%=!k4WaLE^^oD+Kn77qTFvpf~Ci;#TE? zLJQ7f<(GG%1a}E&%8iUPNrwzj9_a$0jGOY&ajSu`hRM(MPmFzQlzzC5qyUs@?#-K= zaaQ{0#~d*Ay&#Zu+>s0@R;(?~O8^6ar1OfU$juEg?Lb*?|LyimN@ohm<@Y>1&b&)~3q zC+Qe1Q|otMqMoT*rSt?p*U<*7*X6p}G;Y9e&Wi@JhCFcE$3g2M=CctukTlPyQk_cS zfqt3TgZX6suiT(_11C#qHl@7*U9ZgO_j2zQcg7r*@pKRXm@!^Pww+);VGl4-+Vdt`r;H3;6t_VCXk8gAevX=DE?8{cT#|XIcIhQueKSXNAE<3Rv*UVV$$m4D zlu0cDE$dcB3$AZN2S5y(7BM+Z6!-f6osi{GOf$LoT5p%1%=u#E;m9-n+u?IrZP=hX-EdZarSzt5g8BmbHS%8|pq=yKLEH=*V^s>DvMtR|lXxYm_yiIBsyAtU>PeGC~ zH~~ZN#35$*xZk;z&aK}WobPlyP`yVlqMJ!BI;}Rqy-YmS*{`FCtFqHA@PZ23!`o&=R%WT7Uq zNkZjRV_|*6n~6w;wb-fVU3V)koV<=D3JkCdJIbl;JY_Qqplg2w%}s$meqnm9R9jl) z@(=M}lpCMt7@vxwN5dT@G{obZn$3()vEU(YVY0YCjg~>=tS3*eSx(&ikTmkTiq=Mc zPc7cMK`XHGSbxnAa$Z7jA~3VfLx3kc8Pfi2+|&=W^|`{Hd_jyhNqupJHsn*_NCB9G z+I&Nx4FT}+VpHXs0pm;p01Dar1|{_&js#YQplCTO;OUG(z+#rxV`J|%F_j~$IuB@+ z*l>C7@f?-@;ZQL{vE&MF2ak3ATW-WTGm7=P1oVys&{aO3P;5hpMZ86b078)5oo;3| zODTZa6k2H_{!FYb=(jv-FLt09B$!wfypPm;=muSS!D8T%p)GlGaiK(0s6nQ^(l4+q zan;7au@;gJSc7Zobc?G2_uFgD>r{HxB$7nW*~Q=!Eqx|kT3nIY+r7}`T(#*2su@U{ z3l@A1_0j5e@x9G2xgC~UX4i8lIlV+V=%28|t;GS=s8-T4YqV@&1-a!=|e5Z~R=eQwG6rSm5WzKUbnX z)6k`It(}dYhi=SFeoxoi^~zBG%bd3c<;wA0`^7NO*&WyK#?~ylB^x*1);H<-*w&lh z?`&jd$(pT)lLx2a?bhD6)RfcOj+4{D+^YA3i)=eN@1M1POcRQ#U@b(@XCmp*J8EV-cLZ!WxiVqDV3)gdM;t zfw&38iqgA*$%sio3j)`?tWf18y~y&Wu#O@nN~S+y;UWSR9(sSKEaeqSiI3dj0+Y2& z%i(&xE_$6~GI~>G=IwRs_1c|EmQM{+Q;?N~_wcau`+4a0``Xhf`4?4F8y~rSC=-AI z26%4QZYG!i_viC=*I^V_j`w+KlD_wAP8fdMagvr`KX;#=1kfMksDM5ki~#dlVEmFd z1pW7p?vTYsuhqbA`X?xpu177?>m*_N6rZ2tObn01Ia}(ert16fEmaH5FKh9c!Qq3Hlp22rIS3Zx^D&ptUdSgF zUhK~W<4GFv`b&^W%_V;ow97?psksq_yiPy<&1Abv9!Kf%$jt12Sm)6_F zS_w(MhTncGQ8|RTB&jDeNz(lQ@7k!9ak-8WvN0B`uxQ#%tzj~TG?}*PKH)scbCyKW zmyOjbR?=#bZg?8yMm-~i}{AMYK6gmORZfQ3Z&`0`Yi9l zd}dQ%oT5f~%h1qL7D-Pei>@NniT04S(J&Rl&1Z>4#UF+KOU{i>m8R1iU)3rYpROQR zw&vy7=PaM6{>CC2%GOCnEoXFAzAgK+1MWumfL3|TtUk*}hi%P{U1_f?`FgFWj=_27 zskXk=$INMbS`eCVy1`M{@K?zlY4~$4pOpq@B{i*f#k-0M$}+sMgaNDKEKBJlzmF%4 zz`tm7Q<+<=D~%o*t|Sot8OLUq%hfjN;G}>P9ZVHTPW|MA@#j%Y>7>|698nTWpsbF^ z5vZ)k%FF=NT`fr>4pz(yHWl!Ej6J3mu0=}1BNk_{d8&DMP)%c77g!ZLPKC&4nUGeDcZAJUpv@0e9~U46bJZ5c7P4yC_~p|r5Vz5R z8_Jb{8FI^KuJf1cUOM+6E?2YKnFkU z2l1UcIQa}cR16TO)8wjO@<0fy+kguI0#!-;ZsKQcb41ZBfUAC5P0EORNt{2?=u|V? zi@-)|Ss4mlTy?i0CCn9ZVaR>AI;;<+gO`|W@Ji~Z01#6Td4p%;8?&zV$+#?7Fo9rB6=83KR0^dOI4k3!Oj zj2L*k8NOSul@KV$uj6knWt{Jy{e1U14?m~A_dwq@SM?%e8{@&|;yy;G`s=~J9~c|e z*pUC`1PrCri!Wgw1)W^VzgZ3Cw7Y&CYe#9!L?z9zc!(G*7m?|awVvXD^9QH^W7T;PDzj(Ea709fq<-@tBd!#IArBiWh7 zgLAKyRHJPmNkI_><-4c4PFwmO32=Clye=gG3mtv$c8RW-Jm(!Hfp4MKEw-qo=!?>9 z3W3Dfz{Z4H$FPLOQpxSE`6SgYWQPD-vMgd(e-Y>ni;Z8KMT4zPArwQwz6cL#SDC}i zxFw%lS<}$#4C}@EZjYW3I&wn_2B8VXaf7aWGp5xEOoH#0>rUPhdX}f!$3s}QfN6qT zh8C#uUo_^h#DQHB-_25EldP3I`)Y{HF&=gi^HI?URbZB;hj1^gC z0A(m=N2uz}*$D77VPKmk!K4Zx!Qk>w_F*0!z%1#H!ai${(5xLldXv83ULJ7?Am(5b znzSE-NoGI}ve1}?Yc{ z>!3iqd7?UkQ7DdajmP%Hwh($-4GB~fwbk`O^@rk4Ii88oMssS2Hz`KTKWoi@rQq9h zT=sJ5*iyj~O6(~BGpwQI35Jsdj0#KrMHMccKG`SP4`-h@9^O+t?LxK#=xtm*0@Cu* zvRby0kHNiI*~Pp~_3Arn21*g@(n#v+v;SOD~C;O_Zp72YMJ+$$9Rp5Sh%PAAo^o zhNmWD))r#NY^lmac)0N#M#uPadF%1IZPuy%4tReN{kZrP)}DM_Qy*w+Ldn{<7oIqZ zdF2L@n}SE`GPp1ay~S~7;`iO-Ca+1Yza*mQ+dgv$_2OGM`c`0`sc1*ZR53GA#jALE zl}289sH2IGAZXk^UKvIugG0&-4saQv!aB_-`R4`bF39tO*fGLD(_N6>laom@S}`M& zI;vvPw;E1cw+-FwkNI;MB_Yk{rz8Xo;_X89))s)!eK-9u)Nvroe{o6+N=b0j3Rz8g zIEhE_m!FJ!KHuQO?7OR&0CdPZW6oLm(8~XeMl4BPg8F;ArtODoc(4}b3)U$>IvN`^ z$b4Ei(P-*)E;$^tb_=W!&1}qpVCq?&`1O&V>8dsywk`YBnXi2);ErcBhKjsErN)`vE9e3c8q2yQv!lr{FZQ`^4qdKSWp>r@*q1C$oj{Y? zs0^`#&k!@jkL@Z4)X)=ssNL1)neNSqO-1iT@JBLXQ@f)EX7f(JFtZ~ai;&-jnLBcI zQ?D-b&)(A9arugwlSF(;uL{*3GBXzT#rusThh{ABX)&MA3mzPv>>d3Qn-}@Z6VCZ9 zxD*W4n0X1kT{_cnh8Q{)L|kg#5s8R>ld9};OP<1}&jcCWHyOhKEj5`(J8YIK>)?Fv zd)e+9jKa*L0t=vEF&B?0#9(oK1#^oSQ86=A{mtmwcVwPTq9KP=5XgY#W_y8!#9U1|1vc`Mjf zGs1#m(FpbGI&)MF8D#mC5;KyKb@zkC zp|s~;1r$(f0s}|_-zmBLfdlKI-&tY~qqg_39eV?GDiap&ORO(>u(-YJi-^@t`HUUW zqo2HHpYgQBaBi<({Hi@aRcdQzI!8z(G!LbHpxGe);soKy#i`6|;&M&Rff%6`_ozTpuCeWN%Xw zWakdqx#75f>-f*s@mDqt*?;>U;Q;tx%ToldJ=O%rN&XszXf(NwN(E(Gk^;IW$k;6O zMN^8R$w>hG^-3|%thrXSQe*NTu zUBkn@|Lv)8FVQ9k#KVV#n5zT>6rirEK7K*LPmo*@T|3k$*4Rjpbw*-uSH$YG^N#fj zp$%nv1IC|QMqkpHi(ww$ye-)HSOU0a9(Tc#$fMWi$iJ}$evF&X$|P)6d@)|PNeG|~ z#&MbGL+PvvxPH5m&vd_3YQ?r;zNl;WQwz0M}vV3+*?xRC+(zMA_?Y?Hi zMmIg>kcnOA4L9Er$Mg6_m#qx}*peno8Y26Nffr)35mz!*z{Sko$7SE_D-fV^w&_ef z9cSEO!7_S%;HEeTjc;FjuqlU}Gq%?N6k^Q(R}0?H zyc+UI+%l<94OZ=pIb4pJ?lm-D2l90H2$w~-0MQB+gVPwMm@LJ z>ra$K$)B_2{9n1@>s;Q)iQe5D>r>~e%#zpvTpg{~?ibnhW`kL6Uca2K2QTCwthLzp zfVbFO0N=keyybn!eN#j~_q}pMPVF)ZS+r46MDGKv2!1w+rRlxb_m@8wC!PpC<683; zZ3Ed*Ar2wj$YV!D{_B5Ti^ zdhpGTCTg}AJ`1Q`6}D}HR}YOAFE-GKj{G<9j)%o{9({rEf4ZpSro1{9FXEj)aFR71nTN4_l}50~yUOpk{-Yl4sH^T+jUd zb`a*AY@%Eny7cxzvp1(MBJ?`t59sh{4_`nHZN)ZY^kBIu_R{B@)#ZY)K_Xwq^ww}k zCda6<@-N|j72o!)cY{;u7n+e=QzyNvNOgd+0eJn{bx-D89J^czht2nQ{5mCK_3Ki1 z)k7&%x2|0}=Pt3dnUz5+^SAm6;EO<;HZ4Hv=7}PsB18D(RFJ?sc+F$T4_Dn^Ymg|V zEckfwI_uiT;RG_l19dvuQWf2o-cW(V>l#G*YEZRVd~+#x91KZI+Kn_9Kcm5{a&ptk z7t8_nTkA<$pDtGTBI4+9wI`OQ+_3;60W8g1Ij$y3Nt+kgCv!}R15y(I`C_y@XgSEO z@e=R)>n`iR+hW#L(P;}V16Wb27_rvMvjCT7do||wtux*7;*qt^<|ab(90LegUrhD4 z2gc#G7>z0S@SRS#K#>D(kZhHYWUt9nr}jFlL!+x%TcbsTToQ{r%H7k;=*Uv-F}9NB%is^M|D z?WLCXxF38k7$VVp=>6B;T(NLL_{G1y0z`xW0C@jB1MOsQU~BV#Z_RCMz$+`O;Q8{H z>SLH%2Qr!>IE{cBM927L$l6ddH&w$;AQg4Sgv^~KA_e5Vo6+c-VytG+(g;i=hQ+Ge z#bPFg#4Jh7j*;Q0jm`$hD>+}V^ygqljy*@uaRIAhlW8UX|X`%8d zG9*L&1YjhGD7etN_cHn4W*AEt&LdJPGx6RA^TEOOsO4_7)izr1<@KffIrk~`(r`YF zM|&dK@w;4Z+fP^1yG~YK;rYB@8mF)E@pszZPPViCd^{ex;c+iNzs~+NNzRK}vw0@VDUSeapT~#S#I8NnuJIHC=F5gu(->(b19o6bJ zd$+9=yXTK17RwfZB{dTs~@C1%0Cm=3#KV!~ z%A`t?!zfb{DrK&fpMT#Fh9zjN1gEkFm_)!_%Dvt^rg@?6xzg`b04<)vPZ=7is=eJB z1o1!zF6H_tn3j5w04;?D2+38_)QE~)#<0w1_?MPQ2pCVhGu`pv3}?a|OrJ>SxPdK( zbS}tN=DgS|-NF(p3EwY$qN4gXCkdET_Jk0?ArBP;=|tIBYuNnjtcR!;$#L;Ce!<%DW1gB!o673&)`mlIevH7biKq z-oTny!A2Kn=ZFIF3jx^;JmCXTk>=<6LNRItjP@!zTnU?3fxOEislQN^U#}nTf~%WQvgC0jtCv<482X9 zLo}ms1S=@HE5BLVbBkp|J1WRH)&m#166#16Pzw;jlPi<|VO3vO#p0bdpNp8~|E$Eu1)dpExT~Wx9^7qW0}zzDn)Q#<>U;-DyO8 zWm!B-qe?iaEv*kiz9onLbziw_3o9NLeUFzhGtNPfBeG8qZ*6eYoua`LhXyJ)k6=he zJj|l$G4q|u#8zA})qw7RkE|QAeHTkZCh}O4$V@VNFe9*gk7?XrnJRwqAgY@kQgNMF zC~%hwJm(p10ne8^p#WUx7%*N+72Iy!g)BL7VQ^cgpL#?n<`1XR(V!^|X;~eYbyIhB z0{#?vz@W5Z5fvSc9Fjq-D%=GcBD@QnVEVNUd>Eu^-fORxZ;-A0G$aIrU zRk@ehV19Eentj$2bAK62HTwypmLzB;0Ua&7!vfW~%C~VvFQZ5azZwsU;OY#wC1i+f1N@TYwnnya z4Qkb#&!R3c1m3d-^?|HPxj;;=qE&C4j6do-L^N^|&`rkxlL`l)G`C_Ij}~uW1581$ zSX6p}&lR1|A}C98B z4Uk}yYNwb=yj3o5)wE?P%r9JIT^+zdSaP?{j+_mX1hxV9IJw9 zuh*O;t{p38nbV39PFTuA4M^g~?_-Y^%ZVK_IPw8`rxL;gooZbJ>V#bq4OUQ0D)m3E zWRtw%gKUsM3(L(Ql9^qC8Ea|}EMtdNTL-Ano9-S4S^E0f!6O4Z5d$tZtR7pc0?ZwJ z@*bv_x0$I1rkqS%+C*t0pl?=&J)GH7?9xNM93fo8%t#a_=gesv4~D_F2mW zg$g@g-rq|3W0}B2)}wr!R*%G^4}43g zw~y?YQ|A=O62t-3qlR;xqpwnXiU*HpMXKhqTs)Q+9HWdGsIs2P4i?w{p&ty2d@aMbnU5s8&y1uQ0WzXcA6=RL9u#``Z5mCvEbL!9-tj;)GnyWuyW-TxVYW4#t zMj|Hc)Hqh{<)i8rVK7>;5Ya>rnUzbW>+pva_G%fYa zv7~%#4fU~X^L*w{jR)nMg+IGNtE)p(5h-!ogw1BFr8Hy%WARV4jaTBIH-P2Ot4rqQ zTSvyy*PtwOoR3qGN`+dkepE?&(xmQyonSPNruN35#K)_Sl*A7@K2M1*<6=GZt8!JN z4jxql8d~to&QQ#4S-86G+5JY5S~k8Ev&g(41mvwvW7=~gPbqYTt0^7?6sN24c#-*u zBCwkk`c2XdxoMQe58!?W{=&3Gi`z(yP7hX-i4&_skv%w$jtV-f=4k~3+W9Nmck6AP zmbVTB`}@PsXu+N3Gs~BBwHO)S_W=@9Rqr0zcm5sa5nkt!Tg?8nS&2sa9W*t`yOS7X z0_9C10yfrVV(^*~lDb1SW83pf$rfR+_j#5N~rV zTu^`TNUis-$8SaGJ!dj}(npUk|uiabvewmT4 z2)Dzy*M|q6oKv5j)74Xto#Eo)5H4}f6?j=-fkYC4OEtAxU7beL>1a%5G&*hfm#g)` zFnGJ&9-q}3o$c*y{iWOwDI8#baK|~YaR3g=m=rvCbY1>mE{oMJc^xNnpMO68x_*Ux zrvrau)N;8wzYYzUkjm)CB|bf>q-e0OJYO+?PiQCaHfvPLu}o#(ytTbV`wX ze@2yW!AWiS|Hu-Vqm3Jz5Z)f8jqJzJp?`6RUvIV+I4EVJMf^EFw-k!2hPJ~_Co?qW z`w>0x$vTi+f)5i{HGit8+C!%^vsG3ozT-lf#bO98r=NdQ^yjkwDBVv84(F4s2njym zt8Tm1Vz~q-Z|PZ8Po+}JclspQuYilRfPzPA;mDhMO&l>FAH=4!Df?XhQ{VtMZ5%Ez zpiT1Va>0YNJ;#WnE2+l~s<^_cr2PmXaxN-_U+BR;e7Xyfi@4C*`PUo=Zb4cCgCtsr zwwe75_!O3>mzd`P_rq20tK5O(%Oyj?BrN#sWM>)WQv5@M+A1g?IeKcq4QTg;iA=mfjElEnDeGhv2W}9kiWJ7M%5qVuEkp+$ycD9bHS2z z7Daf(nh2#<+l^&uu`$URGoOgah@pwdM!2r@R6t;2%SGiuj{9u4dtgD90oBf3D;HLD z%Jt2dXL|zxMHSindg?Hf)T z=A0p~K>3voE=puZ%9W3RfxIX94dczd-FprWJ!giX>H&+B)UcQt za)s4t7*>_=RIGlxwKj`Q=1&8yVVorc!EuUyW0n|_QnNCIKN_8TkW@#GIj^`zV>FZv zxJjg*ykfrO*d7rVb-~3s6eI@~nAjb9_r#HtzjP3gcM^uRie9p%qGmNWH>+tH38=sX zm{l>5=k)k6HNLHh^jjv$T*S6vn26OAWH%^)v73R+j~Wk`k$AwcHldy}VG?{~G2=0X z#ui!#i~Z-iaz%^$OSRa-yz&>ljNORkEE8m}W!SH9^(2q!EpD4*7W( zGST!I_Hx0fE%R(jS{mwc_jx*nF4TIdyHLmUb|+5cZ!7weXU1kJ?RMGz;K$p|kWNN< zp#&ZqtU1_YdC;(;@d}hGv{en-oZqX(_E+j#1rJ`<#I$0ALw@g(KcDd8!DR>884m&# z6draH6l$XLqv=hw#uNrESfeWpMJF=A^vYLL?iYQBS?TS8uPL2{_O}U>p`SBCJLimG z6HzV$;&At)4e@RsFsQ?4#7YyvwiJeZ*|qnnEh{e35wT$b^@pce?*vIUUD}Nj6*>qh zyPODnma811lr_vbk!rHGWdXwfp82y2el&)@U?#!1x1-&x)e)No@57)GC>0OhB^rfCq;W!9>tU?LP5R5PZUPvZ| z%m@;g)w^+1NsGEt{d62o-Nk6Trg(FW`|_7nLFsD2;{?n9&V#l$dt~M&v{?#Jrf0o?AG`lFFnhjuDRvl6yqH~?rK#tEjx1=GS>aFTe09rBe}Y`{4beKkMhvDkBLY! zguK>He`t_kGna)@81oT50)Z&sEq(DTZ&*kD3BtmnDJRzDBqwbeFx8rnz6@Cn+B$-p zDUAeaiX^0Ezi%F*o1JoI%!CIq(5oMt~CoCT=yki}qoAtJ%D? zZI<$f0&l=^;nt)7h{0If2P$5_H(`b0GQGzC4(yxxEtBVjJry!}{z-@Q;bexki7^0rlAnu1 zMfT|C1C(b)7vRcq0e%>~&!$7iI(aVysnZ* zIj2gl21d9zZVmB)dme`z@MS~sumH+FKM__eFBpM_0YQuxGxH0tjW*|dy36>|_q$n| z0lF!d><6_+#O@2@G5KdAyeK9)NsZzjBam=?&Qy7^=`-xneZJ8x(|ta)2V^4+x!Kz~ zx=cpfON1slf@3RY}JG zLWt%V$kT*=T7hrb=!maACQ-Tmd;4pD(@XMKgO*wlUv2w@)A}`Pp2-*LLzTPS$%}~Q zsA&1BzwXRVYZL9u_Wfe=K37}I<1C5V?(6%!QjctmY>;(#BGB%N^4t9On0EKFjDsw} zK>w%rf5U8NaC?Hk7ytm4-v3sm{U0zJt+R=fGb5d|g^h_5owK|1|CjhEMu)qBv_0n8 z4D~qLD+u5%r4n{59h8E_L|Vix+OT6}?j}W=X&jhr?$!fUB}JM9@?g)+-tT+%mY@IW z{j_%X_h-}Y_cKl|)(ol(S=eqajUz7i9mH*D6eC3d_YE(-_t~M2U_3~c&(qSV`&#!Y=_GNSQF>&S5fZy-? z+S8{|ZJG$5NS}K8V7nLD#jdn+Q}1FRx>zl)T$DT);^^%iIdnRh|| z3Xu!u{yWz7tDBRo&MOUv{(oK{o+JE(SAXsR>*_zZzx`%Tjn+o>1j4dc;aS2Bd+=KL z&CEW-SnZa%dO;piPp*E|3B(o=tT_no;q=!YEq4wepjpHN!R4i$B9VqHr5Ip6jjZ4i z5WA=u(Esd91>I-|Zst`=nP(cQ1x7%$s3rB46Uo8b2Fc<>{^bOdI?)?~gw&|AnexKU zBp#?cO@*)ukosNGf!NDX5l7BJrRZ(l|Jbxk8`#WQES&+pq2@r}>sdn!z_H>`Lm1>H zaF$~&xr0V>_ZT}DmI`;zX3@4BrI;dpamy1@7{$_p;uOedd8BydbF8^=00I3dvMguD zP??$8>{K`fg<7(^_txbDtjY-g{s5#h-VObJrdjv(W50;b19)w}VLlpq`2?q65r(Dr z642}I)p9w%d-vwQzD4gl!nk^cS2j1i?zQ$BQpozg70X6gMno<2@+YTK{+K9RJ;)MZ zzu1D`e1Lw#7N0|Jb0$b5L&b$|AZ?5J@Hvm+1{j+fZwE$31z5X73Lr%=gSRc5K{!Xa z=~o4=nW25#gQO62eA;U{hba%F7T6@ijLjz%MR7$+gC zKf#nG+#>2O-yexQ7K3~w60%0xi$1m;N*lDLk3NRDFBoFF1wQbnkh6k;*7IVfZ!L5o z=CcvxlKYtANa(L&ku8Q@%0@()ydYmfs>Z}74Wqy0QXDbWou~F@a6@&0NW<<9KddqLo}d5I6$z__np>qY%;{-*~RJf*JH?Q5xiuU|0M`jb+>II=@euhw%L z68h@rqA$O?%j-As(pX6*bOe6>+10-<{6NU8TBZe9oah7qteS{fEl}4#oUq4svCt@u z#!v_{&lwm1g;2dF0d9HVk>@;>_kbrb;e5HH#`jnI1k)}T_3^)j8eeZ-~kmcOu zeS=6JElruN&STY)hA1tW?w_xjCWZDNDD;C4<$vlp?2>~rXD<8xmdQPHiT?y(&8Q3E zO`8E56o{`(&?@vhVq2yY#T>i$RbAKobXC41kVCi?D(GlZAX{%1i&< z?VSvRr2i0@O^mS*md@qBFBaPZ(yCFr&F&*@2n-3J-mr!wtvv?Trr0Z=gJz)}F26b! z?=F86QV52OUSI%HhJQW+Itm3-nWM_~^Xou>KwcNEl7t!ZDkjl z*M*r4pdeLT7cs^d!6uauoMf$aTV&n8hhYjx`F0R2pzZi_Q!=$J|YC{8FV`oQA3eCvNZwJC}NXSKGg; z;Y?sV5+-{0X|!eYuijbwoJ)*WZ2_^k!dZN(M?!4crJ;VkDCf?x05~}c_@#Qo z_lxbel-p7c1d=Yih2X@r@AsH^g2wHDaqxsGN(`Kh#wkRAx59bT-|N@cQ$l~HrROG9=h<_okQragcz)svy2+?X$OAU(Pwbt1sT{lS-OT`xwsSiS5B^gSU zuPkeyx1F}eeC0))+&Lg&&4}mjPXV_FxXH;A#Ia{k>D+bi;dLE9JHH(2I3PU4#KCcW z00Msu3*Ruq;zXazV--&&q-w@|LWOB%@1cb;RhN&W(l4x$u6UmE_nJMxNA;ze$~_!+ zIa-M4A~~_w(%rlp-%RYuJSz{Z#tG^<7<}@5^-j6*`=?X8?wK*DQ8D>cA{GD`f9PrF zURSCCwCxhKQ(x&rkj@SgQ0Sdf1vprrIv99vobwkDp+V^WL&8C7u1_g)m@^0v!PQN1 z5>9Lxn1JcUEx=`Zn0FYNU_lq4%Bl}yWIY%XVe{JLEE2F)E#qIX`cs6;5H0Vk;qta! zdudFIE?L!2{u?heba>GR3Qo}_O9>0Vq8PaQ9+aFrz9G2&!YY9%EQCZREKqpSe^PN- zwDut!f*X39X}KPPbB=SWYQZo{2)`#uwkt@wucZ(EL!Betyju)zOymodWQIvD#4_j> z>rS8HM2i!ydJI6O+f5Vfw4iwnIRP3VcQCKgUt=Zf=@`mi;T2o z)3WP}p6qt09~x<|lF%LbXA=@}nPN04GJ+S-HhgWzEMO-*l+;4CxXV>YgcYk;c{IDl z_S!$ZjZ4~6&k|CeU=yp5w$DEti{>$sTRzeWgk7X)I~k#miKQuytHh2zx=akZac056 zQ8qvG%}}-Y))kmL+?+nzpG>WxT-8o3!W~wx~jsAs)2SS2yt5AYKebhDEwt0yo=5i@;i_REXOOvev@pJC0Z28 zlP-R1Joa^G2SY(^P&`ULbE<+^?e(-3T}*k($v=e@ypoRFpI}~<+VBE&7?cs>uOxNN zDXXLi@wD*7qdX|7_b)7R*Fvm%qNOBZa*7zFSjgtVC&EQg@!hN!@%$;r7}^guSq+#{Sr|T<0ID$oEoORwzcUJc4&9*Tg#t9u*Axgw$edUXN}z zAZjNnDrGZ9ODt;?5ao1bWd#Y`kunL8#(NPBE4fgwknm)1>Cqq|3gjTBDbMGdJCizR zgpB{e+*by*^>y!J!3i4N-QBIYyIXN9?oNR~fd(yB+})wLH9?BIQ`}3@QYcz3zrWm> z`{BJG-cN5PYs*Py&Y6=r`^kEqwby!$4<})?l?uU#fgj>Idn&}FV=qic|Jq_x(XZ^Q z@{^nu!sBVfN9C71#;X2Fd??r84ZG@aCZv~>QzoV++a`UZ0%EVChb@Dnn2bjGZi81E z)#jT$9^pl?WS;gaGX+yYDxvx1Y=)@;e!t>C52Nm7?V(E&LMr@bXUKrto9Ak)n@OFK zWZ<~^VzTqE#KQ=j!jXs^(p>IHeyi+$^e0{%JjfQDnvZ4d*&**C7(xe4pz#z?&^tbN z96_5+Lny|Vt>t9uk4D%KRYvjbBD?IuyyM*Y#A#N=NK}k3pE9f4;99{pm_X}#Q+SI` z7=e?CuOp2=`;m53Vg4421{u;)rYWHuts^(_Xm}xR@4DVn5I>2Puc1cHqJT54B!HKG zUy-Ux@tDr*L2r%5B+MJXkJnINH2z&z&}^{?Liep#X%GRS62QNBB1e~(=2ZMa0keaX zIF?e%E2Y{FBsZ(z;jb^4Os~nIfP`l#x(7j=>4iRN`8NC*{N%EZ3p-qkOnWLe&^7+} zky&E=Hbm{)67EK}3RjTtHw`<~isHSO`8bP7v7;s4Q^o4BE%f}+01w-FKC}}!N!7>6 z=EEEh-UP!TJ^YdZnfm-GUsAli?GT!>x`=&h)9e1hxxLSMJP1bmw*~<6x zX4z^+lL1Wpu{cOP*d)qw?S5M$+e_UoBzXCFHL}zaGN|oUEyR7r#h0(u!Kyi=tWLy1 zln;=X_rG!>(ufS}<%h_16mCP=<}3&`>5w6%`pIAaX0kCedWlyv4I44gcEhWjL~ZDt zqVigm)={XF1V`OzTJ8^xPASQlQR!ZqX8W_^E7-P@-~wDgD#UzLvxjk6Z!H&I3&Vp* z&d(FYh4F+E&B8dvD28I;eas(--k9Rr@{sJ(j>2XV<05st{F{=IM8;UJHN2>mc}Wd@ zj^e88=cVWR)+IL4C_va!AF{l?Y>AazLh*W2tMH4(n69dBakv>K077AHf^do95yY?cHP9;S|x6RFh&!!5>@B ziBcMjZxE_TkbW1t&pS~uxmZxEi|Fg)in6SWd6Ge`Y!^$7Ar(Y)z3GNj(Q>w)MEdrs zn_1!kDGBT$PpO{jT#P~&8prHfjc1*lP<(sE4?+m=(~>=0W!jin4znuzd^}|e)G2# zWXHj}d~5{E;kyw`leKmw)kK=%IWD+_#5jA*><0?XQxk*un$?$Xy zLY6Gqcmt#FY(tpTdaN(BuY2NCf2rF7b#YHUg+roJe}}eXk{WZ?s#m=JG|gsKO=Gd) zwkG-?`+}Bj5L5)6$H5F8$4WeKc1iR_k2!vXD?>}EPkDtjiIzf5ng(=panGR-l-#KO3+qk>g!74f&|`DrWOF*6l83Jvf2a_tE*5W$5(078m8qeo#xV82^!Z zCOA4$xCbrs_ilo&>5d5(^g^t7#3+RF6hj+&A1Q*fVn^O1n-!a4@I}*Z0?y#=om(Qc zO?ulQ*l~bqGyIe&@~Nvq^Xvoddv(x;1uXwQ7gxn3IU3Vs%xID_P*-4*qv1ky}C-B&Qy|`f$Z#CDeB}}m?-f<&kqqF ze=kH%nLcHv>T5I>K{oOu%TAf~cJk+%CoU?~QQ-X85P#jdP1VgX~h zW)h2dWif4t50vtNwcSTK7W?iFWrCmNk>9iZR5DMPEhRbjI~ zDMJay=Hy`v$dnMFREqd!%T9#E)q72wkHJNYdjRK+X{zJ>HqzgQD2$>UTJ_LGMBKA_ zNlgMr?u=T{KP7TQ=x`;Q;4xVHr`(Vr0v2l}*p}LfRT)zO@``ScEUmAMpoTfWxw-CjR+{ zU~2zTTCof!OK960WzoFfzkB!;LJ>1WnBqSVezLYyiE2t0qhW>Y)O%Mm$@ap@ZVaUD zZp@JSu`F)w?EJT})XM59;_R_XlzU4;sD^&L# zkM;O7;_I#b5~_cJOh5|z-#8`G$NkE$ZQ_J!{^~*f*^Fq+3a?}-v8PuO!^SlwiW#Yu zVTRlG)|k?4b%LZi{u8}3qjuFMuDY4>%0ZGJa}dWscF$A`o?_IViL!tpWoJduHbh-Q zLAA1XFA}zSof2%%U7{TGW4u2f(?&^!f7J6>R^Oe<&207e-mJsdcD!qgIdYl@Qh*rl zY-unbZ)KmyfpJ7SVmiU9?w*Q-r@R_+eD>1`rO0 zttiXc!V<%%*3(3;IZZI6guH|~`p;za<_ER+QYzR%iP+clX zu_ARv^4qmU(U{x1fOA@1*eYIJ#T=7FC zonNW-`%jGyKPcp89#eF(@VPMZmeb0=bD1(l_7H{c!{G?GWf`%0O$^Q|?rwDYMytS@ z3N!=Eu#o%BuV00S*tC{uu#s*Mi_JB?l9-LORKbN(Ip_70=ehi!9tWjRRg>sTUPr8- zO~NupIsK_f7EMzC>tvz5NDab}BvPuQ4n)}4*AlGxwEk2S3w4!vx9FwWG36*GOlh_! zKaJb+zcb1o8dj{aQ%kGAYX*4ji0sg_96ZuUe+h8n@w8)OYNNG5ukBp+iDDDu!{zho z_~S%vX5kwU1{GYiU#pS~#?B~;kefL*7%c!zW%69LKp4W7*PVXbx0N+IsR%qyd)>!n- z(FaBskmFS<;#pPeE_ARgiQhv4rMZ77P1Wb43f0g2E&GgYrl~WKBT#<{OKUK~m#0Zi z)~29wGpmYAhAB_GOF6aB4qd_08%EHT+i(PgW!5o=8goN9xmybPPPh4++wr|`8+g)^ zZdSni6vOITJ?$P!+B84rRELOJ0!(>40nt8S0fr>gekRkt3b{XU?6Cw!%7IyNFC(aC>92YqOFxf}ZIt~Bsr*GDd&P7M6|3?viE9WVz$SU`#? zAKBvHqX>!$R&@1qjrF+LQ==HvR9X}-T%mtex*ojy?rNk&ALBRbz813nMriQ^OQV|p zd?&=;^%jn(4KGSx{Vvb`cmKLuYo+&#QK z?7VC|e7)^#IQ?FAmj8;B@#f^==H=(K4t$khI6d4P{(sWTM=cFSEOgR;PLHLmB&P!h z2M>KUE%<*f2TnLO@3ocikvHg%5u_r0l8;6)9&8|35F$* zYCN;Op?e2cw^R!(>De zw?w$}xi|#jZP|jlmRC)+N zza7!2Gh~dVTWL2#2y$);eevexAC2Y@v zU`RG5K5eM|v=qO+so(M#h$IW9a8SF-IKaOv=aX#jr?0fk7){v+LohiHq*J&w*D~7| zNB_`~FF150iUV)aC2BnAiV}{fq=>EswJdNWTRMgjJe}0yf?GS4*82rQT{9k6zC9g> z8$p{I{=9AZ-qtt5(PQzPy?nmxga8rWl16Qm?*dd^>0K@r&;GYu>;EYj#2D!a9BI| zM?!vfEj2?P9&<qTQAn{n@hE&Cd}BEFF|m(Y^^j{X8?LRt@?&%;-B7=rJRwrC{= zcRXA|It7WmiF&w|g*^B#Jj}95CK1S&#S{wnXu&)e$r^<`7nU*It1yRl?kW-~4}{e# zeS9CCbsni72%EdCV0c!}<5I^>;0ZuusfO{Gz}$u{+tmk>0&mEJf-WljS3|>)fRUL3 zdZR)BqS$Z8RhwbRPeojXa5g165vnjRBAxdaWOt zng%5uatNtJXHEn*aXY3`6M$;Gp%LplLY$vvD$i2LV^t7Bj0veQBn7+WBDULd=CN6J zIMq?!>C{Pta<=FUrcZU%U1`iW;-#JXmVtPym~ak=wnJ4J_(r*jScBY3Rr53~ti{&h zhpg3FX&DX$SeRE*21U&5TWe6tB{lsLqn1E2;v%ywj6&vbZ54G`@lC2VTJe<-YPtK8 zykcQY>ukH)ZG7gi4H{OU%j^DX>j+*VDeb`qdiyA5c%CRnPxww1ErLk3*_IHt%>4wX ztcte;i&|_#YfKUH@^+M3AQVA&pJ`hyLeAtGM0xGRKFX$4Sl$(WplLRyLfmLQa5V&3 zm03kUiJxSV>3KiQge>XAS6zO~x(~$$rYCbmj^*boZNQ&e@7=7*rDNgqTJ0pYw8ry? zL|ke?#06ue2b~pT81N>O`mx}PXDWuI-uwrGKEX{-M!Qjk5?GFPUCjT+^NXLO%R0b-PgdCWEdJZWMWEk zEbF8_DpNHAy`(ACJ!GnkB_yUHmQaJ$PgFxx(YfE$o+ubB4x{=->u)H*+EE#Aza-?8 z745$5T^-W>8dS-wBk#NHV#9r!i`$VNp?nk%<@jRwCwkk&U@`P`QNOmc0`|9girhxO zo$R9EAUEO*g3YRQyT~Y_24YD#;I{Yppdg`jS|WP)y2A8D@_?DL^7|W#JIogmDx7B;^yfW@Z~j9_PlvKbWa3uOU}2V+sC$Q9T^ni(~*94(=b5{&!KGSNJ~= z)TRFi)N|FH$rOo)_0`Z?=pW#GS8ce;hP6hde`D}7?Z~Pw>L!JDuDGf7vP2vbhJ{Oo zaNNRTwD6KsKaNVr;Ds>Lq-`h071DG#Qh>Xg%Qh3>@b{qQHS{iuEE z@Ti+>=PFONm3lo=^CjQHFAfTf1byw?uY0h7-wQU&4q7$sG|U{X{thZMeS7mYnsCbx z!5y2h_aG?_It081bR37$Kq+6~=>t|DUFbivK!^hWbo)8ib@i@CAI0NFq4$Hky`w&w;UPy*y=SEt(PU7uuP;H5cBPhkoyjFGgO2dhoE396>=vo z+2dsa#I!tra}y-4Xes_4#U~k^TEU!Z=tvqyWn*D5HT- z(deA%NYUP;n7HR91O?i#a^y&JV@uUY33gOu%rOKi=b2&fM0o7mHkz3Ma4z~L_x4JC zD10TpOegzH0B`{O%`l5~i&vTmBU`*HmWSH7n#TSz6LTR{BiW1p6Sm+q`l;2o16$v1 z>AcHvME{bvKSxY3J4nt_gOPAXw!4e~9=)lq_{I8CY&wJCS6#B;c(`gEyG%rUz-Am? zfCrySha5LSVdzUH++)CHr%En2KQRMBk9C?BU_gsHrb9X%`2z{f0s=jW-S)f29x*~{7M;E(e3Y~r(;q$Qy?pfCj|C=v^5=7I=YyY zjB-?|8hVs|d+e287CD!4xzVY`seyPrm7uR^5SbQi754BPcYdRCWBVdQhwvHCGUyt0 zD-a2r0%o{gHvpkK)hSyW2OJQ%Glh3*N`c^$&^<88eGL}1U)V9v46S~{1)-APiXfvr zA7fG#^8AweG%WX%m?V|#FxggsE9%Ku1Re8m5Cc4>JN2bAuVej@L)OP6hg-kGf4q}{^G`^9Opgy-I{&2Ep-2ftR)|a+~4aeP5(1; zKiAOuOcx#S>l!$RZd;c%AlcU+*O5apsgd9YwMPyj(?{2GlU3 z==jW7p_9Z(N`IuyBn*;c%NFT;cFWiH`3PyG{3pT%pEX;YHW8b&4 zU!`g!69~kLTV;W1fBm*Xhm2s|zGMD12dcZTVnN2L-kn9jjVg3w$j%rp=~6`;N@+FX zFVTyW=d0O!Crx9wYy)f4Pej~rn7kIRkOm~3$l(;`zm)-KP})KW+Y*B$HUO^K`qf*e zt;13yiEA!f$v?F{W($Fut)g{5aZdYJYsVb6F`r(-%@iX#^e%^RsOsVA~{|rTR73MhALZH{#B8eLVDm4=x8; z@1J&5XCnzFVB=((al-MglMec~S;?oYO04esNQAGEo!d61`E~z3{52Fx7ZJ)7aBu2- zMi*0fx14(TMw1yr@qVvDBcX6*$Hnt=Ds*WQdlmvH3c0jkm~Yi8Np~Om*XWrr%{fO4 zc-?0HYI6TBdh+pb3-SKv0Vq=8{{ZOvtkZV`VmQkr9j|3^sLXE!n|3z(97-$q#vWLk znU4m3H2McnkoFs?qUep<6{5c54~W&?%$+m(m-3cYQTs@k7^am6ItC1FzJK#AGWJ)L z^$OlhWi9677n5Uz9=-Vb(5p75BjBjQq!3>$R&2a<+UyvTK{R2{b4$;U&;w0I@l@oF zg6f;lJbMs~8b%eNg1x{TT@dTptMbW2}7xXW0MH73HyV4dW8LMI^bJ zo^9^0|p!_QvMkztDsqy#P)q1FeAbSpvRIMUrDNpy0y>A$$9G~nI-I->!Rnh!} zf+GwO?lehuyJfEQ5_7l~3PZe6&0=sozb4`?E_*t^^KSj{6BXi78j`QY9->U<)gMNT zEn?R}i7leAcB_k#S)L<7 zmqdH7WfPD=>f`i38;=5XX|a7|b1Z40!QL#wrq5(b z7K$@KS6Tw`H_0KcfHkX6sDQv)rT`%fyK93FTI_I8&8i$AM z>kH#zUe?SCm}O#}katBsG{RJ=Bk@u56h8!ZUaIKDm{e%Ro+w8W73Fq%MQv&MI~{$U z=Olx@@lQb}X;Gjq*JC!)PGjz+w_c#m{k?~5x91;&Gf!MfP-^j_v5bp+(;>YYfcFW& zt+scP!rzfnUqT^eSnk>Mor{b81G|RJZc2Y*-EV#wFHkt{qKd~`rQWvej~ipJ_r6C` zFWAS4wTkx)H}nj5xWK*VK30XyOH?-TT~cK;O$ENTova2^@mO^3Tv4QUQU5LR2lNe5 zbO4>q2eaYr{mw+#s5iw{BL0ymusb!nhuiCKoi_DwW_rg0@-k7ej&_J}%Ol?Xg?{+h z{MbF-1CGl{IzveWmXhkN*`;ezE6Tcc-!3t&_}_1Cmu4!2a5BXR z|7`t$ng_WnJ^bBlNMjJoB5i0pCx#bOCTMv9*4O3gI4w`%|2?Al!GYWJR}1ad@Q zX_#ohO3w*uCP20T>CxbBy58_%jaKd{c=)+d_T$Q7Qke7is94vj_wT&$e&>gjkze7< zzj;FSww(r_5xZ#p>-Bl=iZp}hm9PBAWdGguS&&coKasRd|6l(`+Id}pU|8tR(vkWR zeyx~GE8CeGt9U<|OZ!A~CPV7ud`BH-#9an?5N5)Usv(RGSs<`>?;UA>J{Vh~l%bZ% ziiT0}tt)rJX*&OW*6f4{TS95pQ375JMeV53tow_*{btW>yn&mRrPBnIi<;?LIHk?A!MP3Z#d{{F&y z0G->Y@Xvrbla#8z#3^8rBxr7xEyI=%{?64>!7X>D!I04aTbowLp{{P4Qno;Y}Q4s#>; zE+vq72+Tf!F{F~Wi=2l(1-8yr^?E|L(SGIrmn+l_pCVGZi_g4LMR6)4Z6bDugI>HQ zjR|OweVtU^kh{P+g|_Col&nT39HJsAIK*Hzpf4`G zCTJdM|FA+s_6F7M8eT)`9qO4+>BKzT@An2r9E-?vPl0k|`RhVltNzO^CqxOop7+Hx zv7KXPC$fS)Iv%QLChhOq%-Q6>KO?wQh5l0I|DJ*ZpU_&3mnL@owUKVmp`rwN%tmp$ z+6WLb%Ip6N{N~VFNU=&^%8(V0k;txor9|%MPp1tUXlCcl`@i7RD*ntCC#6xq;Dlz$ov~L-hq|~YerGBuAz<23U;nA7FNvfj{C8bOehBs@G zhjXPzTG8C))S!6kFz5SUM&=5V9J1^S)1{VXuyhkuigSOZA!W z5YQ=uSP3Db*$KdW1+0cVgeo55;PDEn=`mxohh9%CI33E1&k{HztZPW%D;!jvH90Ad z4mc#^N+eE1F2+I!EVlr756|9|{4v+L2)NMTXxbUR8KQ)3?1%0w@%GFe`Lc~x) z%MD?er}X7KN+m6h-cO*jRvm%{TxPAP%s%p)A#s2dqK;{_GpeYk~#q>7a{ytPn5&wSi8b z8Vt6S$5_rvvA#;2%F$_wg`dwJ>spbKuJJ!_y(9I=IvdZYv!XcOp@ z86fi;Tr0Y8bn!n20$^UJIf2;dV3771q{B~M*C8*z_y>xb=B!V^Ys25H@j8-n0;!WS zV+W-H*QDg1BimSUt_qx#^Jtw5ehu>n;lzay6*H5z+F@10nM$7!q&BH7vBOF>Eo3tw zdq4eEgBY;OV-%Ge90}&#%*nfcQIB?Y^rf?YvtdpYP=706`Os^Ul37FIppOgpkxKh) zbaOTw|K)-SXIIu$=uB;qhe<8qO6CiIm{9_cG5T`g@&}?aJCm~3iVa~Bruv53U+MS# zeA0}{Ym0?X1|O5~-qR!KI7g`=HuHNVEjLc~57gVy6P>Y|y)3tX`5uTTJ;5jE94N8? z58f7X7$qcdLEHi|rn>*lDJxBsN*2|^Nzot=_$C-da4)+jT< z_0yk$xOv_Os=8aF@+35?C>Fx@8_3nk`9g+Y>oLOh)0f~_=Z7{ebr3q{xtF~8+CF3* z(FXXwBkx9Z0_3VEeqU z9=;msDYF*;6z+<0`^guc0M)Fuqq?9}({pa_t}%3!^#zoT)PI~N&g4QG>>PRAM$Gt7 z9Ac5H@vmL&lD=>dE=qs%H_^<%%NsI8qC#Ql@faa;#74SiEr?C$dHW^OVfvlkn%2*M zjmbCojnewBc>It3yE-B-H~)Vk5;kaZ2KJ2+v)%>@im^aq;nB(?o!P8?ErCBF%gBpD9Prp-BSa z%a2dD-Besyk(;DqCU~JP7&U!&0~XF&waQlaU=Cp@IGrDHnw)r2z@P?x76QcEcUb|K z`Jq?e$=E5(mDlWWA9gvh67B;D$qjeDBEh4BRv zzRoZ>j6`ngbl^4()E5m8Ntg>pAxu15gz;;+GVk1n-Urh#J^^2we&kJ5q~}Y$B@9T2 zB%VZTB-tb~Kn?ZPAVV4q_r@?tESus)&HSN(62IBcDyc3Fr7wh@FTl)^@rXw%fPdow z%E)sp5d;|Z_JyHxoW{N;mggc;+<){Rwce{(ZYn;;nl+!aK*bN?VC%xSMNetaC(jkd z{S^HQz4*dNV;>BOFeKpeS+(5j)JzHI7 zHNO3Z5>LD-?_?|#)0HW|S-;bjUntzKNk763m%hzXE{=K#JW*aCV0kT4YO!K!x14B3 z#?4Wx8~{~CK}5$6mys{Man0smla}E zH08x|WRga!pI(bU;BIsAKElJFkH?R3nd1->e~#Jd*fv9oLm&zqU(p7cB8w8w%6zbj z3p*iBe9*MLtplDLvLVTg zC=ZBqR*F|F%)5ilaD+shhQD1|U)Hn4#vS&?Kjtu3SJ_D-E1SXSnRWLskBgUvOTRu0 zn&3a9_;llKf<}aeT6tAV{+P)UAsts(ZnRikM*a#~%*FI}_55JwKxNV}@|pu%XK5jT zXnWOb)dBuiwYu0E9gkZ$=FFy8sfk*PXUiWBTe;;e9AV4wmfGvAa9T7RA`&Yp1;=`* zNC-U(0V043tU>Nppg>@d5l(rf1P}pX)?iUeltR8P>3C8=O&hT;a6Wt8e0E&=Cr%;s z294PyCR~L|B9`{Z{jYFsXg$IjtD%(XPrb)uE9uwx6>!F!expmC<3PZj)p5z^r;IH@ zJquxR+!sN1DE)IfhVtyBee&Q}$Eu;yyFd9id(3AXn2;7~Gp0@f5fml5Qp0)`j0b$5 z&NY@coSH}>19}l+#gUT^_Vw(tLNWLut@%2AdXmf#Ld%@Fx8e1~`WF`OWNn?Q-}0W- ziD&6M7;Q|!=p*%cIUUQY&sANTA^fQvjGFEQ8a%vg&7?z5I^lT;nIwAh?zyzXtayCP zd2=n_%HPrSvo7_1#PPZwocN8P@@XL)SBPse$*RmScv=D#IRLg-`K_1Jh1fK7~uauNn=w zZ^V*4nWx{PyXb@AZ<5RlA**mG5q*MAQiVoWcm&J_JzWp`hr_S`#EYoYNp^H!!CV@A zEaXr^!5%<#@8{u@Frd4xNIycs9;?EqNlHC& zM@2{j!DyA6ayshiR4kXBwN*Lqbg5K4G6j73;FB0CpBzl>!HuYB>_@~U&TCdAt-6=r&S`}S3=|!5d6<$K#^-ZQNAG5|W>phk6AW%-+9UqAgs9fQvk*g$*O*E(Dcy^ttHRA7yl3sGWY&TXdn^Cz z{AbVV*SUJ}>->Fn8G&y#tuyXhPg@(tHOLcsIsGgl-#xUS``*_J8eVdt&1{5X)j#mS zG#A{r40HBN{sN}ar^4vFL%+82ihU1-Pjbt1gZkt3{dMpg6@ayc+lAT8cJCIT(D>U5 zg&-9KkNYRs)poxHY&?Kof*nWIhq3)FVWtmrNJMM>h90m-16bb^?$d1|Khkqxp)B^^1;p%EDrbt&e{d z*}{^&fSIV6DoZYjM7P7?x7T}eg%%>eiyvFii%R=F7(d)zmn3#fejuAoBt~4DP9kk9 zrud9ml9!Bu4QeT%5(p{v4+3L;*hD+VrK=ogQqqzU<#fCxC6Yn56KEXzKt|G%Pql?N zk^TvpCUWU|FTf)Q!#mwZ;*ADo9}UdR+eaCPH(;BWhGW;D*$K--3G6&7Dq>}wKtn$h zl&!kWx(UFs^dXuVlP5@vO-}!WK5x>R@5A4NvD!!tYb9^VLtsR4Rcwyd?BvE?nejs> zmVEQ8=!{`*zwj)a99sss1{`UkPCUd!ml^ykS6B-N%$W6(B6M!WTN#lZhp!rEWVEtOW$2LEfG9n69RpPBE$%HLxfB#%L&#=ob#xV2I!UBE)kPCf__MvoK zm|L`e|MG;k+`GQbf}bQRBG#egvjgk+&cq0%5yETYus3_&>kN0n^5m+Nu zD7%W1)a*P2&N*!F$hW!vI2r);zr1(xD!arHRWL-~!H63sBJGmB6k5iE(A;&ef;4M0 z6>g>xen%HhVpbKo-|rwqt>3WX+8d56#JU{Q`@?6jgc3sQ$R%sN$4A^0DJQo4lP&*p zZd1hEKLYWh#;n}nBar7AFkn$!XH)<=53w~gG`AZ|=Yo z@0#^Fd?LJpAGUV;5^dCFG)ksfR6UFpaz1>_N*=xlxXKt`o_J-D-__)aj3hcf^E+DO zzH?4Wja4#jVOQWk>VO*xz)kHIL`d6{KgHmsuah98dq}}_73+_U&F2{gD4EExE2MoR zC!&6brp>@ZEJN&_3spdXKx`H-=3dsuH35$NimmTV zR4E)!itQ9w)J7v%kJVAMk!uN-G&T6YaO7IEq8!h&`3Ac zsfMbVt%iznt%eF)A1N$1k;o*&U0f%JnZ4sMZrw{2Nf*{)8oUljX2i9gTa|>$@^`)k znx43_BdPBYC}`~}NHJIdeKV7vCs#e%YYTE`z!p}Ws+B}W|uK^T8Xv3vu>PspBD zrW6p!aQ-kq+fJz$CSeCMoJ-(b8HOW7!SaYt!p;_rhZNDZG{1CZ*xpF?Yh*9B68A}0 zK2FQ7vzOz#S5NYVIM2gk-N>~!CqB=rvN1)Hp)I7R!V*I2&dWU*Mo%c0POv6AOSX4X z)_zzUP_=D-&FA}|57YATSR)reqy!))0kHG7hp6h(r^yutzf!qBJ!axJaWp(HxN+0A zl^Lz1u&;FeWf3W+(Z_y4#BpvM42!JV{?|aA;+F7o`l?j^WB)E2&c`bx_#fzc1DyVs z4WIrmHoQHvc}6zG9peE-B^awze)unj1i>vfGYwi=y|Yj{4bIl7Y*Nuxlf3CkBsQ7W z8SJi5_p&Ia4e7$g$k9=)4y!!9*JSc%yn%^o_XE#$G3%xrwjc4u$(OA__sw|zFDYc< zEecpm+ib`jf4hYD06YOZaPfu@4uXgVNbiR&`k0`XSPhSLHp=07>JA~xWGgw#efN0z zlmY_O{#8SLFV7E+a6YDuM---<#@_`hy-ylJ7c=%k!LQFAmC(o?{zaxsa%(-0N6`3; zZxY9?zk5IhoJ+fS(aPpd;l-&p6$Nnf)Ylk3V2i{ejHgj3h^jq7w!139eT#JE^fhri zKh*@U=yf~$h!4H6gFwK6R9ie?7D9@Ldf)hP2~X$(6qCf4Hxcd>N$8#H7bTAZuQN!GC3atnFo(>6ASaUN zTLC@})FDXn+*S=tBb#B^pS>pTMb$)JS6ej^eJxWg9XH!-dquRUR_+5mkQIlTh;O4t zCuuG0^}UQ!YUDwN(UweIBK!8E&7@aiuCjzp)H>1vlA%1oGFpU)NZ(DBefoIj&uUK$Vn^SKDW4?n|f2Rl6>J4bx9mz@v?!I$ch3OGp{B+vQes} z1i690(NY==U?KErEQ|xd2lqbk8jjqlI-k13uWWBi|8BrOhzA<3-^(&USAB=k?vPKF z!oSpn`+A}*rSK{}SfCCSWQ59J^11HrU2e#5x1C?^^pJ!uEtd-w+lPCgB|c0V{5IB_ zJ}Ec$AlBVE!8)VgGZz)=jDT(`zh6HQ$_OZIhW^L^NMwGbk4W{j5#b<7*-i=?ga3P0 zMv?iGRH&)o`khG$vB#`7YX@ZnRawNkUv$E1y|P?-*&QBn-bFT2W~$BSx3V^t3lt8k z)N0*~!~*mr`bgAVf)bOl!%p&2169 z$@gM}i|Y|&U$#4>F(M=IT-n5eRFQ?p$lGb`fosnRsR7!#E4;j4nVt0w0OzC>*JUIvB09P zE$VwnfJT_s%Uyu@niCFXOjLwQ9}Hl~%SHKbQya|%C*-<#xE*j}j478#=s1@x%wCaW zAe*W%Cxg1Pc#;)A*e+pmvpTsRF2E*U1N224Y_o-vbKc>Rk905a&wnT@SL7SA7!A}H z&lTX2=dPzDhE45Hhbe{Y5g@S!3hT*&kC_}+aS7L@B`GFSH2;pT4l2^4k`fNC^hel4 z5^>3K2uo9bl-c7lbWzjMri)Sxn_%k`cCm~p9Nvo7eGS>i8?un5lE61D!j@NGzF&@W z@5PCsFvYEu&D3Tp=BAz506~h|xCrEt9}s@~%W@0L1JprpSfIaJs`4tUf)U6ya@Npb z81TsV-qes=y(@UGpxrtP{vyXH$ZzR&MF-Mc)fotsTKIDzD9I@d-A!JdBDT^ElHn}( zbObaPAySuUB;xXRYGh6RRFo3#H!d2R4cUUzY zfhNoSNo=uH@E)Sw5JJssP${r<_P{pnZ^6F?8poGfp2b&h@E`kkDPDeVk^exK5JmU@ zQoPROLd3&DNGGyIl5I07BDXqg-pZqtzev>FZ-hq18T|J6S&>e1p5bM>hr_W(X=0Fa z{;qkFOf1eG_8FHR?Pm9NV;LhTiUPF>7bP=Xc2Y6|`a1(tr|{~|zb z;)raS_2s`&7mgf-my}`IGJt(MQ-OGX_WLU{4+OD<9YRF;zD-|Am5G zpE<*bKLAF!UJjNOgx?b5&aaO*Ku7^e(4xNYKD5^*sT?LM0*a4!odfCWf7a?qUsi5c zqPpYzaHDYlJrxeSPJ`<|8@|y}#CQukpX7Gr9531=*~fsbnJGR@;tFy1ut+Ott@jiW zY>WpS-A#V^ULC)Udb>J|_RS(x*}HS)MZ{Oc;WFgJtG>|RyxYv*&dzQTE$YLk( z##hAOW7iAcw1}{+JcoYpV=0CGZ zI97V4PhmF*JwE0%_2hw1}1iDUgVsTBQ_YrP(z6rto2=Y@rny?6j!XFYI^@Le+= zf3w4yGwU5!4FUk@rzjyw22gN)3SvOzo}3r-1$_Tvs;FdXcAa1Kg&DpGGi^Xg>ob#W zlL5Tfj13d7$B&QadMv12sXl$2+L($Fo)m;sx>5l%RwH*d@O|0+qAI>5MY<^agnHUF zV+(TD0mMyki#WVyN?1#Z;I;R|P$Rv_7cE$u5O?!;@J3zLD(usYnQ6KSQeL*ht$Liv zWbIdX(QxwoMHHwAo7T6^@7Ui;LKho1(P&YB#-sX`AKdARcT#SMsl`o^_m(q0t(O_3 z56$Sh<3elMP@M*U%D863o$%(?fOgObswH=0haaLmvX|nF zCXDEoObLycK4L|>(Y>#0Pe;op`jkGCjZxRRU$9CslrWiKIy8sBTtw>c?})yyD#%%6 z!X4+0$Z`5`6<}NW;pfE^Uqt~_5yvE|T8cOHiddV?O*QpT+LrPTSAaM1PeNq5trN?Pqs0L|O7Zx~ ze@6mp&bHCSfJi{}Y>*~4lX8z(NXD7xYlCH6f9GLuk8F9N7@SPBH8nADavith+RRo4 zVQGkwn0-6h@bfGt0H94^G_@-}l?Q^`6VQ_^9ZAvUPY!;^#-^3lWFCGOs#tbCr_`v& zlY=FvU_0;CXav}p#=9o(r;1T0{L8 zwCi--jkU5Wk`vx<>xlQvlOh6QFbOQgTe)=kE&Zg18owUfK@`}d8KWZZaByyz-j+Mw z^0owOC0p_Ay(i+-<+ny#0B9%M@GO>iV8~m=mTX`G0EGB~E)guGO$huH1TDrG87$4T z#A|G8J*AOsl24;|T0WajIJdEo(CDvT-kI}L(rmr6eckO~rtL>$bl+|6462wQx#Xwu z)qqHJbGpBx!jf3$8EKzT!HNKuTUdkyBX)zH(lqF|szLq}_QJPPEt=M5NH8x>mE-qG zf(8HBx1gXB;7O`mNre;JZ){NYvfVG%#ZXXPYes~xl7vb_zA-ZLa(XfPhBjmjkq)4+ ztlK#LrS{~{M)`GZy}fa79n>#>agku%u<*9P*Ee$<#3kFT_rWw@$F{1t!zE*OnymtE znODnD1HL}1wJSYx+}NO9zmBsiHyH19a$HK$&bRk|CvXahoQU|kjZ|=40jh1ep9;+< zl6d*j`Be9Rn0u?Rw!W=>lmrRx?pBJsTM1q?xI=*A?%EPui&Lb}L1WAyj(@nRk_AK-X5rwS7kzQY>`kHht+<>HBG<5*wcHJk6fYyQGf z>*?I9*h*dU1zd<*1>1G&g#@Y}6WHqNgUOJd1b_o`6LlSc=q;TrBu|B}xH`GP_N1BAc zWnI4+nuz?`LKf%vYL$wVFh=@|LnCO(GOT#YClkgKsY)s6)y?`>suV<&%&jVb^r}@L@ zEK!#;hMW<<>xtlzq^?HzPFY^dZkw@9KtMnwlJpB#kqUZkV0vNbuh5a#oXsQ1>CNlb zC+j$Vp{on2+610xrioY!V^p54DwE?>sm`l;gH&HoFMbH`YcLIG!Z<;xlEO`=YM`%_ zLHE+2k@#Gu&>Tl%9u7|t7fIuv!jJU&6qKx#g3KaNXx=E%B|Fo;dslo$Ek}OkAh6D^ z77l)R7kY0A7Xw|joi8F^wYej;i!h;<8rOEgj-O~I#PGM=OutNn7G0B%lMm`x*;l>;PfM?GAWl1vl)6v|Iv{kmW%`+ zwtvs>do}i7>bu4cJ z^HzgMAKeRR@E|mxLNx2rX=- z>k$QbT%XNXZ`B3l;PoBWS=oQdNQP8nkx0ApinIbd!U9skD462UNO_>{V3|lOa;SYp zIyS^nQP8IyR*gXD$09GNR6);8#E=NIDO7ZucO*o+0rP4W@h8NgP$jh$jG80`q{n?8 zZ0GFL+cq`bWJafXWBh_ut#q)NgCV052GN)%Dm6B$`5p9nG336E>Ns-nfKA5G1P`)N)mcAjJ(HCxs#V1kV7a?XH86Y@YU`5 z@3eQ{r_wnMAoY{p?ztWz)6V5z_$_~Le_x+NdLa*VfA+V&2{{t7X}5fS=mNzS7`}B7 zhIhPIaea92Z<0u0jeTUm>L1Dy^c?4sRQ^b{l98H$FP$c7s_Ai7=g)!AcHm$OJ)mTG z*#17Hyn_BVs@y{3kND#OvZS{zRu?@I^%Xe-8&bAHSyZ`Pq~nRw{0lydBxEZ0b}l$NMmLX{rq}69VK*6U4)+qn20?eL z_?{jp)KfKIr~S)vTow6RSEt~;fkeev&Yp3oUvQ4C#aBNAoD8H^L5!o!lgc%RkGYwc zeVw^FPjCA*90%Jv1!FM#A_zwYl9A_6-YV&;pxuQ&0Za%Ro_9}%cK=x$7MF#{`#x*J zzasTtMl}om14EjTum7bCS0>a}7c30 z^dQ$$&#*!5X(WDt)bH)enQj{Q5+H~rBjKT4j~}&1@Z*cp3-GcI^;R&>`{MP-;LaPN zA`N@Ik3oK2K^@%}c3fYfk19y4wzSb1 zhSG;nFXl7!lMdKDW0nm$A!+xEeo{99I}`+-M{$OVujLEE$0W|iN8IMj(gWZvyu25oNurBjWiI(41-Uin2r@zzR5$l&1qQvwUYAF5nQPX;I zYZJAxS%_<(blTWcnObj?JF#pAu*f}DBTg37atuFqzuy*V5kca2%(n(m3(`Xq@OXa# zG1m#Ae!I=!Iy0V96W6d@bB5=Vcc=5b>9D_{46E!O%;V$xK7fmX$bKoqSfsB=FN3NV zUPDJ{)1Yt8^qJ18_f|(aES!$`Jg5dwC4NdMdM5d9Y%N)lX!3C1?QiyeHok@WE;%3L}df_IBjQkpVG3Xn+*k{HN`U ziP^#(1D{2E<0#A7aCe&#tIZg}KtOg#aiPvc$V4?moqUS@h21$5?uY6ZSKWN{F ze)Ipr&`R4N02+9&`wiorD{bxoy5bv>s0o(sSfHR4NnD%IVAqOm-v^FG zvj&hgS4Z@SZS%)P$@e0~`^P6(*Qn`i8NgAUubow4JwAZfGI2{X@z%ppa=v$G3mbU| z6n+cEDf&D^DN{;!cjfqlF*Ms0Agzmd;Su^BgM1n29YDLsH?PFBhk;7BASvJ>8|pca(jp=v2-~Pu77kNdZhYfD_SU z=kMYs<{FVHsQh^Tm5M$u#&e9AcO2+KpR3zCB-;PGV9H>E8|DYwmN6)9Lufhd!gK`mvz zcGmhobInh@3hwbXsE?D0Jo_BfZeJwjL3CZEHu7eUN^a)&y;O^r;TDbeSb|o+zU8%; zZseSPWBKLfNlc%!2*;z(_vTC>TP3l4m1EoF)J>QDyIH#yypQ6@t8>Sd6aMzq0qq6i z+9S#ByN~_9lpP`)%r$2$I&H#@nYyEOpTkM-(20^6lw?s`HSnKP!?T3vT)RVR#Dp{J zRt{N-LS(}mbbWImd1zAacF4sf=%p5Zt2TX`W7iN~X;kqdSf?=`tgx=+bv@iA;;}t$ zh0w_cF7-xjTCQ|91vErjB7sTmxR|y-cgnMg)CBFOf8sX2QC1^VIy4=^I=u3iL6x54 z5}AsETq&zj62H)c1Bq*4T(q-guCeHP(TNTb?AyK~zNIMv?t`wutfeqy_VpcDU^Mv| z8c~ybBrB2h$tfLC{d3A?xKA0bd*t@;Q0JgoM4@HyxCmFzi7m*dTF#uIS)CI*81t** zFQB%)Y+gKGnSm3~?Uf)gNU~UZkjfreB_dI%w=k1<%8*o%hG84qihg@(Q|df`ZIDVg zDlx@Dzy}q>)06O26C93CMr5yDrj`FXT&mr)eUOOv&-C9UO92s2#m7s!y~0A@H6BFi z6W8Dq1Bv|ZWr9R?$!bxoZX{2_1*R^5)=MpoKo9k2zKXv*=AyOG@XuUKD#A-pWJr( zhP^-9#86~SAaot9Tuw4_Q29=%zkhQ@AKhon9rp|>f{tawi$!@<--)*s7}q{1(DLDw z^w6h}X23Ei-V`yA??>0Kn47J=L0sczBDg#7avs5#FcRDw+IxTGH)D-?Z@Fzeot$^9 zn&#U(6?fr`@3BmgpA#nIhw^|Zug;xEa^D66*xm!Vv=OAeIq|Afz4mA{$~<>H^jTUIX5ACY_NXrh=DjsgHFWa`b$6b`pbA_<>Cx^!eChI;@_AbrQ`9PxYLIOqB^ z#_xJ}3R;1Z$8qkJeQn2jM{~zci#2}svEiF)_;Rlc=we^!siAR-G#ZzYwdhNDXcKU? zo#biu;KyasN_w;qlfWm-(J{$Y3pdxsoCBE=6U?`tdYt@j!~AkE39!{y34RaJ!4xab}!@dRyAz7u~#m08a-N0ks2m*Vgh;pf~au2bUM&Bu2|@m49x$ zm$^H;_All&-|8Z+t|BII)~sExeEj}EyWZ!R!=P?-qH03%IiPm53mf#~k>rthbcSld zrG-xi%hxNx#>BXDX@}O)H}1(EJ~L14Ca``*%%0o%W%BGJ+sOvd#q!TX$i;(?i(H|; z1=u^1WuXb#LlD_ag!|K+H5;IssPY4Cb2j?8H6imB1_4Dy1!rVW)Svo_CR%N$E)B9r zWn6Pq?!Ya2314eKcRyD=SHqot?aky(mKXKG6s^f6`9`N()-oz zVzYvYA)o0Ft9w~sRt#pSs{uKZdwa&_{f?P~8eawv=N^O8zHgpCtX?sGxg=ulN7 zZl(44Y7{suugk@%U@s3$&QdVHivmAICV!&=Y!rUkRm==zy5!OiIc36E5#N)< zR|&j|=GcEJmIVD~-)V!+YoH#hY{@ocp`(-p5DjKOQ#@CetVeT;Q52Db! z(pMs`M%9KMIFOdRg(JHzfkw4)wu4HBG^Ox;FoafF_vl2%WmZIE-9C_Ho!2YuYn|4( zoDX13yG|K|GchgBTZU>!5%A{JwzLE>#q=0E*xYX+WnGkUgWdyOk{YX~7`j^&OCLL6 zO+31g#2l*+ldkr4RB|mPM8a-ozC`?ijE{Jm?|MHIEdD__d}eL^LH`YCk}K!Y6AGW| z{;3X%2*a5#c<#GfdxX~XVQaBtYG|koaGJgn+Iw5D$WA%x2SA@KCvwVAnc@@;K)%Td zV>f|3L?L{AP*DB@&1lJ2oL*vMD&M$_ka+3`j69T3bJ?b(pIzy+Ia|_^7G0fer?2M@ zJ5QisYL}lUX$`y%=;SL#uZ21Z%;=aQFTOOT8#B>^b4p(!jZ=hl4`hvdE!jrbNWN%D9{hAvB92X3HU+_{tC@M6p^YjB6*buNVLg`+)(#f_OVS%nemWEA|g$=z%Db#erzx8aN5+zLxZMN*e@(M(PmD zPOjGJiZv*!`{GvK$_7Ufuylzv#U#RdiDg+!N<%l`JXI+l#SYI1X9TmhEXk<~)63oS z{#;-u!*<76yXLmovYscGP+0~Y!47hkHdG%A+&)o!EU0UUSDjig7$~tls(NXVq-LC? zYW$oT%9^;uDoUVNbifI(MYxim?^8|6 zGoDpTTDC%B?xw`^BFx2`_#sdjN+;DVS1t*+Cmb=6#L-->bF{^05$7P6s}o|r45ybf zn}zI!kjuTgC!`z=jXU(aSIpDEEMPz;2&DFGDfyi6xwToTAaa^1@8v|1H}(|EbXim& zk6cW*QR79CT9TX`H{xVEgJ!^0zLqEGF{ucEn3Q7wxz;nr^dVyn0aGp}%~TG>Lx4f< z)%kVN=hk$;Z`mnpB63MH9AuPWMj;`+8J37MmZGT%{z+n30VIKlct$m4sS+FCuH|*+ zPTt_p8Dq4rPy2)(eX40(dYf z)`mS%kao#LbY=*MqvWD6oVo;c)T)GhmHf$1h3=?rGm%U$Sb;}pL6YCb?Lt%6{QL$4 zF>JgVU)g4p!fuS;e7ZX-z@Tf)J=%Y;3|U~?Y&U?MEmD-h|~xr93+BTK4bp1_Z>key=y&neSb@4tkzh>A6pxyG~> zz7B_U`;f=PvT;}l3nZ?}X9#;nB?inO4tcO;2v_0Ky-b*kmdPk+=qZ*i34gTRx7&!F zsx1uvE-zySq6ze}XCw?~aa}w6t=Fjm>6p4|jlFFU6M8_6q2A0UN@sXn!12Dti&B-3 zx)H%ku?Cca&|-0(*zJvjh+(x~Gu|)!7A{A!$fc0O+XNc?|&2fMoNVF85=pR2p0Cb%%U8wP0Qn-#&ytF#lRt^vPmV z5XhR5dfc!jwdF;=)x{`25%%^v)#FHwKQI#oaVhj<5xWZ{P>voa5tf853d;L`&&969 z=C)y`ZoPX@)?seFWqm&B9alDm zx!FI7hfw6K)>lti==@%t%vGq*$DOJX`C15XuMAKgP1aMvFMD3aT}n(N!0^^#o4a&rs#?ICKft(IZRH+j7G%_HQ9;gOX#O zZ_Y&h;IQv?wcCCr43Xsr(AsjOanCnd_K!h;Kt4U1lazP#iXN^-yU1>>j<+j9J*^M? zIV*l5%oAd=B9NScp%O8&-)FF3P1$-og)C^Iha0w?0y*>=R$|3Blf*LG^b?Bc`C`!X z4U@%N+!s_VcZoHea|mKmaonLXGT3IC&X(;p6FgWye{KxoW8T!8)Hkb!_xP|Ik%~zD zwov2_Z8OW0t?C{fr3APq?b#ra=B95_s9!@czbh0Kza*Z3qCt#hoFRFGjmm~EEN?Rk zrIHTukYkMdQhVNk6E?O;&GgodIV3!=@vlR8^Pevxvg)=0eJ%5yRfD0XlYp#@7g@TXT{R zXkYJDS7L~+sX~dKS4I7*$8!NZ=yr*5^0h9Z{cYlllZBUQ-n66})!=uyRDWPWDq%&z-!Z@V}@; zXcO9lZ16!9RHxqkD&i z*ICwl9RIcU;i~xBDZ|8soWis@!DeJ8ebsxRwXdssJ4FEglI@vi$>oKk0JP3uSkQ4b zlDK>Kn!I~l=%6zfoj%7S_qc|OJ;;C7`82$^Zdq79Q~Uu$jnQtRA{@W?pS9s1cHH-6 zs0avuMf`uS4SD~G>JXLb|Bk6~ArvAU(4rHFtQabPIlbMaQcq!$XYLR3=<%OV$xWKAK&& z?UA#g;Cg;|IqrNLT<9DtfD}n$Flj!c<@1r%aG1px9q8C7-i5q@=3H|ha{QxC-bx&i zCaU9sLOQTL@ddVc;*wU-!hkC8<)hZmN7(l8zdRCZDP3!o$h`x23 zl0gytlES>U9q773x~&Yhaie{Ep~1(!l1O_2IjR|m8T;KV@b&DE>576as_t+kf_%q% z6rO5fd4v4OaT9ZGkU#?^`pLUTA~e$x_R>%~@lVm~n1FF(Wp> zwCq+NW{4Ud+nv!UN1qp}*9+qO!i`DY**%xv@)b(c1Vr|on0*XZ=sVe~mS0zE2?DvO z!D2?u30%vL5)Abnfa02LO%$-ScUa`Gxqa(TUFMCu#j6fK(HnK zdm-Ij40jN>JzbtFf&vhr8qFV4BKsl#gtz*fV@z&~Nlr^LEx84HE(3&5>hC$;W= zgoFUwh!gecme!D=*seexkZ^DY;wPz5fb%c046ebq;0=sTbyG?y#-t%xpA{7PXca;k ziYUfu1lAE_#w4b`iybBza6!V`W{9JQF`ld3&L&qD%zeO34Idf{VF#hUjSwY9`@*@n z%$d~^%9<|*M>xM#|KR@vFyE*{UU`DhQ|2z9JC86LqJsCFUI*kXfHKi1cd9?vjmV+0 zV{H^dMoBDx3Scg&v*&u1ELmWqkQB_QI|ktV{z>?`wA`EIZK*(WHB?20@ z%|T4#gx4V<9~*~uag=crwl@!i_G})^&ff@~&+lrrIBppEMA?YlE?*NKAw1O7++Qv8 z>P02nd{qkUl_4R|;bh@(t*?nxBkCW;H=>sm6u>2U0V<6Xl!KUV8N52|MTN^6Gf-Da zlzt@A6`GP)g4cW!G0N5Y(8u^1eX2bq<3?6=%3i{xJF&`8?66F``1Ja=g-4OMQL9fpbTH8kCodMJ{Zg_%;n(T%xZ1R2qe1oXpnk`${N(NY0 zXK-on1Yju-6vJ4Aas|Ftqql`FdYSc_Rr@WcBIP5qV@Eiy{Ezau6gt%L_WJ%b%Nj$T> zE&8mkqeyn2{{|+_m3H0ZQ1W_Gb*HGb;+pQ<@s;AGiA*az~=| zG2qI_j60xh-^1H@68v?|H(pX~?Hah_ba?v^KFkW=(kuSS3I`cqA-@fx5-04(%zJTI z_|oJud?$4I`!N~o>LII<9q^_JKqMY-E9ujtrk_4GT(X1nbQYV?FXkB0sOnH;#!bpoY`LBE0GwZ)dvc zNUHdJGPo2_-}I#Iui;$#i}duQ9h1^{T-xbJ+VLjj^KiRRk-d*jg#YXLjs-wQIt9Um zRD?f^-Z!>@sr3AA(a=+oqL>lQGmRQwTB5cA-bZyZ$A}h-W@HvprCNeeH=1-Snx3kJ z!qDaf7X;z};}AcZNOx^eTLAZ`R{ED|LQHg7DfTpMg`&c#g`xrRT``n%<>i6e?H9i2 zkFUD6>%TUz3MC_xd!R%n2X}CDn48UN@BR`rXy&*P}?die4oJu)EM)_=Yw z0ek09=o5l#aGA29n*7KA59_Eu{L|92Z{V-|7uJ#BKhZh@{oCLCam;yH9(OvPIMW|=y49Z$ue5&!$dxMpsD+ZeA3c?`0+Q@|aY@lDu zpz1>jrCfgz%P*ZEjRuc&SxYl*GQHNb2?%n67)Zf?nTz%-PQiec7_^u=$Co>~$seY>^I*{d88aM)oIh zR0iSG*OPl8L8M(}9ea3vrL3G;(*fco9b-(|#R^)wb3O5PoO^Cy4Uv5h@D97TMV@;Y zfADaPI1fYwB?BIX!73mm0&xX*x8*zkCWLmPrAw)lHY=K*_a0j{n|`x3(m!0 zecB>VEktZI)Uh20776$~SCLUL^dL4Uwz(9{gM^%A$V}*2Qn0gi>8^l;sg2xFW0l$fC&&LiN6-Ss6(un_{>KC{^>ak;Iz$%0EHj(hNYdEviQ^#G{Xdsx)5 zeTA86EVG+~qFDxYQoJ8Rh;*E>h;^I=Uh0M13%J|MrR8GHo+MlC;;pN4q6+4%he!gJ z_(5n(ZyNPY0i>ythVymLi8)pET_M99HdOq!7wV-&=Saq10T>pIH;OQCFZQw($;!az z`;p4!iV(V48Xa0cT!~ z-sKRTN*HcG;)=fKmRLwtQ;s{L2^8sK&tq{&s;5;3bM3owUMrPchihOGo=TAd^ZZ{6I;+M8^jK_f45UpRK_}#}j0(F!|&SDpRwl`_6ulMfD5Dtu$v?9w)Z3pU= z!IWU}+rjl`zU{ig0(WfmH=I)CO&aaYEx^p>ffNes(xN$Wza{N{e@)^$Fkjn))Ub|u zmwWI5)!6KI8Ac^+4?6`k)JmkXYgK7sKbE^+5AH% z*#1D-h3tWo*&N(*Dcn@pQzg^n=5L(F(7etpQ3FkVA2?1w(QhdK%T|&()O*4=r(cE> z)H_Sf|Lb)nLci9tNdZHw@c^I9biFlOMk>NO97J*hb|Z>h=OPyBs2ppM6okvcj2^|| zF$m4?v1s~*-U*142JTCJi2}7z(KMaWB7>TV?@pT#Lj}=gAD-=xKE&pOtpjVs4YOK) zTT2$|s9YrW4KR9yFg8}fbHor9jK*?j72fb`>X70nXoG?MxLt~4Gx(+&RPe_ZHOH7L z!Z0Z6dtbikK*QH5hX5*>_K@P=%}|rx(4XnBeA6Lu$zH=tZtaCr+Cb#;0iDZR_KRC$ ziKYae#|eoAbiRZQ!6IlBlnrG|w8ny}$D9h}vL)I9vh_p?F`)XLF_+TLd1>=`W99T3 zQ#O5SxwNG!htgb^gwwA!!XP_)tbW*ez~l4@jj3n#M3kD5k7t7XhyhW;?1u4U_m&XW z=jDq%;?B0|cF@ds;;OElfdwPeKRYhr*R7vjFlTCtRiHP3Eez-bo`s-#OFqdcYKyJCE+J2^;u-U`PTOKgiMzk zL;yM77O2==PngZ*x&0G^RK^iaG^EnMdq&#SX+%RSU4ty$oI}MzDVMUdxmqhtp|$OJ zqM_e$#TWeie~?u*(Fr2~bPaRXQ%{kWF*?>SchO#or3K%};cPn@XhwF81|DSL61@Tc5<2xhFBa zg0_d_P;Fyxq?>613yjaeQ9~ss*Xea>f6XUI7VSt4pV1C_ZLZl~{CW9OlVp)Z7{Cb!$vaNE?-7aF41=fK3WaqiLSQ_t|FjZlJ5>$3ZT9`m;gYJgVqHo zjm_E^Ud)Td`Z#AL1(Y1MufVfIIVh$6pzey-9tUL5%;e;b&ysrljGPdnd9-byzhkWD?3=AthR9 zFGas+io-syE6CtpBUvFk-cBtn6M~oN@tT6o-79Ojg`9ig1_{~X6H@-cPyLtfHB1$l z^t*_|HTqxMl3`WdI#EX=rPaHR#R$2Rd1abmCgig>3WUlhwrj4ca2Sw)F^36k_sLVh zvgXpD%%gb zxQhPlxXp@pvm%AY09DO&)a%RXey6y&T2>8#fSAKl`7EJh1x$xZBR`;D{Xq3GgS~!Vr(R4_RA|#_TalwrJ{6S-6_Vs;TS^#q!wiCF@oQGd=N3-O}^?JJI}v28|ZN%-_2% z&KZcZ^6uIvHSWOq%EQ!@TZO!;PhE&<)}5oA^w`ofAk` zM#q>2wXuH_m09 z5O&-i_m?&!Ty+(oF~Jr>1LZo(vui2nR-lJg^hjDf8suOCVDn83(V$s(ZNtz25rjQW zhWdU07~>-Z#G*ch6@x*_XRx3Nb95X{Zt>*hUna0M*Y!3|z8hB4x8W5NZdpXDebdzO zjzF9R8%*ClXB2AVVPmHsUH;Q^Y`#}072d>?bFupOZ?K^FIOF0#&nt@>Uy#w1jGlQC z_?A?&PeeN~kwO>;H z3hIGzUzqL|Z|RNkGj!DFe}FW?GVr$}9o+6yKT zXD!+N&^>BTyrVBRct>xY7EAL9C+c2SURb8k96NIiSQ5NnUVz8bJYb9jS0A1*wz~dj zJ7-JQ24wkc=HvS!_uj=wQ$O5XT^HD2BOI>zIeZN|kz8vQdKtj&g zaEI&5Ut>q*1$KK94b1Q+;tjTIux!Sgu!`ZYyNYamCYuG8Iv;O*D`PZsXwSrPEr}2X}OJI=HR`E@!P&^CD`v zvY5bUUXAYGRTG^94{T$)4KWH2Y(u)JPx#l<7A|-^gyXY_`Ckru^AyftKet8h59|=a z#$Fw`={|iMH+2nSh+lF*2v|+5k*(eVOnkg~fPU+uOJZm`u5HMXOI^Ob(B4t88<}r; z@8WMj0gk(^7fhO?qnn?k-*%$hMl3nOxzK${0N{4nqD3IKQVOyaecPYx-iCT)#;JuJ z`jZ{_Ih7?6y#L-i+Vxr~$Nl%1^+gFa_Tl2q9&cD0@6Ke@q%{K9D~NffyD(*7z1GKR zx!K}R+@kgk2%o#Oaedi-%L8dgI;IeW=jl$%>-+Hf^SRN&Z{>P{`PAqJ%={+y?;+Is zyPvQC2V_3o>Z9KFUI=A|v56WKf#!T~<5>JsC7o5oLic8Q>lD2G&EF8758s ze3r7GX9de%C6TGD;e?$|qF#|D_I$uQc$G#4Rnk}xR4|sN%V3yC%zw9<++#MHSdf@S zC+0sm3Tb;8sV76%5#TwhA>*;T->^cbw+5IsH85FS)y| zfXl?Bh~*kJ3gp%w1uor=1)7o)<6#5p3}9r=Hp(bbDhm#-7tMLjj5OGW@{!(Bq7s=n z5v_pCo-2s$A>|KPphB%>aBI@hY~@B`j_{k8*jG6G2?X{i+xbvYJaV2U@R*{cbs5=^ zvy&{e?oCJ*z)x8JD|iexx;z+99q%9RuVBn89q24@uOKeL{vomS4dYW+pt&(V66Y4) zMUceY@#u2Yp1rnrf>4+{dj;Y&@VC{?K3#?a2=NEZ(-+=B0=$s+MC6U^CFNm5E!vGD z495)r@=zYXO?f?rM~2Qoh;Idk`4x{|C{P}_c;dvD8aC%hm~v0hTqUmUF=`88klvuB z+^D3w3OnSWI9uXfW%Eh?8aAQ<`RGOnT0fK!@Agri<p-%~- z<7G0@FVJgxb>g9y!a?YBsqW*bmY#h!n!AYMOD~2c2VNUgIJ&wBW=S}$T8e0R-jGy*bZB00j$FMjR{>wq_ zwbOY0oUGD0EasvLn%qR5Kc)ZyNt9fRUPrSue4V(w(zdKV(u13sUoUq-Is%T+` zHG9^)HcEb9W%n9>AH3eal27lyl1!!1nTs?YLW&kkU3+erX#@|%Otb3K?bL}RN41UABT@>geW*PGvYgSVYXru{lJEVe&YT+d4q!$!$#$(_^2j;2FhZeotc_Hxw zk9PwEYa0Q-A2j=Jfp;+o$15xw>lOxc_fGGOb>~I`4+W?jXV!Jv;Wv^SDJ^~-+;^zH zI$Uw|tGm_v7Zu&2!M8kwczS-lpu#9F-(Kw8EVG9wxV3l;sS6ljiETtSy3{;e|0Gjr zYk5xZutfpe;oNbZ?Wg-S*QJINF_V7VzR}2{IB{l6qwDWgI}+e^!X7NJS~)XQXo@A7 zQ2GqvT#T%GhjQ8GAbwm=q}b=1S;36H-QoRtwK)3loy1=VdOrP$&$x9!VPvaw(R!sl z2WX(n77JIvI1TIBkX~`>Iyz9cS!e;7V2gcZqrC2%QJJcZvKdObUK)L{X=~RN<=b14 zk90pjrJ;Y9XKp}xQTU$?8*2Cv;_9@KlF>+iQR4Ad>|)o?dv&1&A==v<>Gh zFdvVfNhJBZXnRT8GJOs+*hE@ToR&JFFVO9D#YDQFXjJJ z^xZupAgsNIo$GMokP%lOlEe^>^l2E?l0{4nLC$5 z#*w3M?L8_nEbg-VLI$-@Fm-hTH^tg9NcFX`Lehk6lAs)6hG2gU#KYfqr6yP=(v*)$_v`p$jY|CHCvs)#Y z6))>VtBv^@xlSXB&T%e-VYjjb#ce{U>&G+?hZK)hXGgnrifcBM^dgiGfd7y~bcE`tNqfEZxY^`injca{B@sV&1f5UeGqQ!Q8D zh^9-`Ri^DAtbrFccJ6V^fCcR@36nG=DH<0r?3J`bcoSfMdIW)hFv1T|0({EmO7y)&sy($faeZ`)KzJKAxb-+G8yRe-w%egAB zwJ!4OGS762S|B`lSxa#Z{}PN0?{M0iC~lcYz<&w^XX#OCZkONI&A@4KBEGSrq2|D;iiK+T%3Z!&y?f#3b+5Q4EgunK{my+06GByWW zqGYKWSM$z)!EXUc+@YIT-YF97S7V|GrLsYo4M$jW>=vHPYgD=3R5FsYdc!?S9fa1P zyXh1Np}G9`VDc~n8EC=#fq8cF@LW(YOVmDw=~36{9m2@l7DcYYCwN^{S$puYMV*qk zagVhQBt5y^q-!l>s-h%cbunJiV{)}7?Fi8FqSj-w*fj#uG`{9(>353Wyi+Av(n(xV!$5AJg8q&Xb;q5sya^MwS}#88-k72MxBJui-K#yi8^> zY@|YY~7$+6_BDbnVKJ{oJpl$>n5eg6Bm!e{Sw2#`?y@jh!a0Yl(MW(-%HW*D6NF}LXlGmghqxjHP)HEgQkNbChgYM4vy)m51v2oC^9Ra) z4g>8s?Xt1t-|!MB@-)~ZhVUWA*!bGtD*;(jUm@aA7oga{JjRmC$C|4+ z0BSoJkX$23C{JbIoMI#jPY(=+e-0T3<~>et0>xs=EM!}(zEjHB`TK{LdHDsgWR$2P z@r4=@?B?iuJ+O*{=1LK5-M-&Jo%=EE#n8dmM8;zyF}~=40Gn0YRMD zlJde(LoaOnLnQg7?~Js2X}QXp>1jep^ZC>vDv53_<{op(_Cq46x9`(7)F%qA#{O^# zpC4-{8(KS)*{=W=zg)GzzmKalHXbZaQBL}Gs=7?1j#vWx`(b+HGirSJ-8;8`d0gmU zJPJH52`(EibeVYcsi0Uv<^LRm?=Zyutz>O!AW2zM{9Q1iTJTN--u#Y!$puSv{x)%pT zTNIErl5a5=+-Fpx3`9kO)ixb{MGZXgA+-f1`M9``u|lHk_($C@TC#EM=?+Lux!a0t!w%P*X%FLRSQ_Wym+n59a0T6Y4q+~Zx`Dxkj_uxkT zi82^2s9PNYa%=j*tHfPo1>Bn2=OHSnNBhE*s{kMeh|471l_B`WA*cFMKq2iNI?rzRk7}|}FMXd7;1DEk?pSVuXXAba&LuFQ=&pME3 zEOw32koKAeyLBww^#CGJNRKl(T%Y~XCc$u(nZ3`$!~-^2(f0eX#!0Jl-6O6Zs^me|`@Ru;++ zn+s;rv3ORegV9`FjI(*)5;r~4Vwuk<2$M>o*@3^9bak{9s||dvk<^)O5!JKTxxHQn zaMlBd-_ohx)^Rk0l;0j6CZpJvRdl}$`3U_2mgufr0}hNpWcYnAAdocy!ZnRD;MI6i zZiy#gp49HAEV!p1)4AC-lEW9f+RJ=?h;SOT@3Sd_0%c5kQs)opqNy{OD%Z_s0@ z(Pk869?fwHcMvvY6i2X=8&SWlm%lS+-27@X3NosRslR6tWqw=#qu=(silxYwa zCk|6^yKlDpRD3A?-~m~)Z=JDd#ygQ-)Y?&m$HT9QJF476N?Nm3c<=W87}wDG-bTP zy*iK%f^yW>b44pr2JSO*@lNrRPw|+f6QgrPcBL!pL-Ig#^6MM4I(mwkk^RRlD4z7*oyE`P)UFKCknh@T4U<^%T0$%9bgvSnF-B{NazVYVTF zBP4vWCK?mvcSV@QeizS{4~w5B_!7G(eqX=+JB-+}rI=ctV51eAs!z^o4pBA9bRPX{kEP+{y)!J|>aM-qx}eyPTsTgE+_5?_~so@MvAPS^~MP zN`MXRsM~5xK~YVVfTOqO`qt~Vk5>@_9iJF8{5k}69S+j6RbS6Kb<$yI-5VY0*a=2u z$rUZ9XGU|d-WMWI)ltT~G^`;A*0P?ZMpJ0*hWRC7 zVxp)PJzw--Am}<1Rofq<=$s&P4i-O zeq(Du05xAk;{;BH7=d(ip7w$RlN)`nqsIrky0wT2-fRUR$yp$FLBUfEXbEq7xdMQ0 z5V9gRvy3MAh6#v{%7m)%AfJ`3|81=l#x>k+#$qMC)Z2U!UjH?u&>vYv_;T5ZmxaqhQv z*7T>YM#TsCZ4Te++z$A!Kn#MzC%73f40c?}I#r)WIweQKU10C9OAt&GX=Do-G+DlD zmYsMvB|{rW(vtW_JhlWy3ZGGyE;ty=)Q`gI|Al7~J1t(X!Lqr4=+b>PRd@~fwWC-g z2JQy~p(yvecbNm?hS2TX$ zrBcF&?f@|m7arv}UK9Zqhg`pe+iuWR!}QifQ$tL}r2;ua60iUv7VdZ59P@nTh&)J_q}ohoj8V09{0Wn6 zJ-Gx?&GS3|;Du@ihLcZ1S8{NOc)MQ2HMeI*e|p8gHF2r2_wmOudCi8pvhLMdUmmnd zN1yh2#a~)a_tlNK`n$$A)%*^RYa29{WwiW&~#* z2;Jirglg>|2Ct1Wu$2LW4n!PhF!8WC`a9vh;XQHm#}=e5mYt66?Kv~m>&YP42qeZx zA8z>C2ekS|VVCJP1fb6Dil?qabHVF#3@_Bu-Pl$4-L-hZ&7rpa1U?-E!MRD$riEg= zH~na-Gq*Kj2NT2+Oq_ixre>k1FUSN{`@j(9s-AZQ6~lMDdn_1{uyY;hrdUxjewBn6 zT?SlSwUm?foA40w@kl;t6B0Hw`O7u&S=VE5x8WeLssKNB5^3QxV;~A|dhSB@w}YSv z4@|a29B&OruC#AG7=H7eq_JV>mwk+uguM?cvoW{+am_{oqY3dc4~Z~WZSx|!F4=9oJH^LaqgCr;u~+KvK|~ zcm1 z@iV<&r+J~Vh&PxS2+o4U+zolpv%Lc4gAHZO;B}3*B+a!toX)&OD)><0)_4D{Sx+#R z(7Hvay$QFR5+%oWuszKWC3y?+J7mR8`cP0s1TdEV^Yao6f4YJhsY zux@BG$1wd+H0gN@JU#NgU6)W}U+6WIB(TGVZoPfTz@)_{qCO#HJEHV8mmY;KTTIBv zF_)&e%zrrtIxuKnlgQD}9I}J1<>h7|QEt&Fr;!1L5AvxBoPgO8BRyZ+A&_9N>0go{ zhh^zsHR1?qI=JKqUpiPZ_mcu2bdV9I`9ha_=^Ulz@7ZY})px=p@u{n0X>@NM&#thn z;jFkk+XqJfege7Uqa_MA8O3N5#%kL7$7+&PMx_et=27|yG<6S>E^nsL;b6zdSuaEK z?E{<$7RGAadv5>T?io_E5(ry*XT!s&5*q2sr*G$DlRwmj^+W1>3en;*SHIe zrNhI>*G4;t$}je2#MH-t#KeiNihYF1jeLKQAcfq8)Ls9EXz9g8k`m?+oJSR1!G}Yu zZHUK#tDlmGa23Th^2L!lZQ+|3CkI_8l=O}f{P#(#1x^ZPM5*%W2P-V)Al*QcEsiaV zdBtWn|2jC#PGrN3(;~in!BaR*-Q4}=J2>nkycNBppdiGpy_D{pU9da2LZnO~(f$4& z&_f}LC%4c)+98752K7CJowHsN6c{H7B{;AE;}eBa7^;Y^E6>xt)38LZdTM z<3@PD_EyAywo25*=IvSte z`*PLp>AR%{0*+S$f?%yddg~4dk>a~=i+e8X1Cou3b3q#bUmM$F3T4|e7gX{CCGc|=vP%kxmdUr%$nj=1%{IUv5gVNC)io5pj=GYOBg%vyI5S$}YptjvwZ4(IT|r@V7L;tF7^U0pn&0 z0c-kvEAv#lYdFN_#YAcDzviu*fe#0UPRIz;+$sLJYTW11rNNwm^%chmYa$~P7$UoT zAHrRxUlbsf^nWm|`9Xw$(^1BFt3r8$%?R@GR)(8_{%BF^E)M5nE(DnHV9L;jg^b~t z_)dkJW}|&4+^9sHPN;#D>noCx)ysE%d1jQ9mkhTba4g%NW4ulWOBDe<%Ax4YyY z`|tAy_WzOm;q-sGOl)vj{w)fnkk02z{sP&;mPg^SPgm07dkbm%oz^(VN-Qc^(tJ1q z+>0OE6!Q2Rg+&^!?4LMPphV*a=gfDgo+Z7cpnddwa&P5st$T=70*o}N?q>OJk`KBT=v z8a{e;kr*&?XXTc>FHE+{YVXB812EZ|-Hu|WJ31vdx{sucRX-6Ol)2HpY)yn^Vo22A~CAcCb^7l6=r?JwA&bBUpP zV3dqkoPY+nt&%$-kx-|sf!OL^R zXZNF9kV)5om2wQX9YwFdRm}raSln8fn3gXQ~Oxj+u=Bwv&s+>@5modjZA2SL_S4 zW;~5q(a7OOFK)FRAQz*~j}DXOujES&c%QWorWmv6#D+`D>tMB)>Q%=m-^rmE`@%BC z$)^}QbE)VhZ1nZ~YnH-q47}8W2+~`N%p8&jBo;}t3;MI&*SYSBzN=9l*)oS{Y}|v& zN6r#g>iZ|S>zO#eP{L9`ux@2HrzN4PfIHZBIGUmH^d+tVr@dhg?-=+pG&l{qAH^6R zzgG=DDQ3J}421vQi`<|wAyjs-|EY8gAcE{X$C)=!-w?9#ZU@Ai&WJ1qtEY{@+$Nc0 z!*fxKKqklfjiN^szC=TP5Hl57s<`F^zKh#yIOSgueu4r9!fSeF@j2RZfMnbX(8-WV6XqE4+4+q zSwEQ%#(TAnAHbSkE}oiXdT~-(Ezr9>P{#JJBh*Pm29nlH%=K%r#Y#jg+Y_JMat?QltTftZUCrIPs+&43Wcf}lz+~iF4S4!>R07xjuor+ z-aho?xVyPia0cAgVJk&%pcS$)2E;1Td8|m*;sQ^GzZet8p3~Z)%^0gaA80kNG4VL1T|W#;At_yY zZtHqhw*Jmy3LxiWN4}LBV|&u7RQ7H|U9Z19t~8`UIpm;mM$jxGu67ZU=7kAt(4eHQ zR)T`&Ctq@>I?H0!a=Fy-UDD+!|Aois9cHt7WrL)PMkc0!wmJ<=qX+@V6bBXEcd8Ax zTn#4yBpISp5w@i5ZO#ihpS}WYGk$vBt^6g-q4fi6Vxa%Zg@p~hB*=T`D?I==#Qy|C z5_sF2JViX%_br!DlZ5g36=zC^ZZgEr^fDw-i@&E@B3_FhY8eh(=)3w_pY`iZl5>ck z{!2cD4)gb?gKkG))yA0sH&;k2R64L~0T7$r?vKyyB@n+G0gPRa3QK1!OI=dn;U7{$ zE^YLey1vs_^loY-Kq{C&<*A^)d^-aW9`%E~C3irSQRw@$=GZSm-h(;j;PG3RY9Cn2 zx_Y7yk7*wt?feW>i3m`0GTSNGJL10GBmqZu3e|dN(ux<%GxOui?VZr{A&K?Tz|x%= z6q~*B_cMyBL`Xb-!gkPTK4SnEx!QoUp+qLI#e6A-RbQ|OB+WfSf<2Td28m(z%^d?z z_?qcLC}RWMT$K_TLBNF*(8OqGOHXOFt-s+=5DuPuyMgC3 zs*aS)EB}xDVZb-zfdZEe=&|UhcEc@!)2>x?b8XIRLduKBv7g|FbM8Js9HwhRy>_eRE*(3G`s z(_;f|z(bI?b}|fxTQ_Rv$a6 zE6FyV7))!o+}>7I4r+~##?3L>v0oS4?HDkOY8`b&)1IJ{l^8!t3UA}+UzE^lvn}eFBv3JV4EW+B zJ4c{S)jfe~=gaaPWu6qZn>vB>Avmx#sbA}~ZYT3~_Nh==;Psfuod5~%A zA%e}Y^bo}OMfZwi^a(I9&&=VM>Rz!@8Cvk z;&lOTH~A9w`QMR#8zrUur`MRnH`@6B`R;PC)w8zxuYs1Hltl2SNAlhAl4Y=qEJ74u zNWf{)H`4@YP(urXlBAWmBvXjDy)fx8&M7WEX>-5^DO{*=xW+flLC^*$O^(!gh+J1Z zn38UUK~kdb*hWJnF617046LCLBc!jbHqwFH> z9upZC5MgQwckM&|?||gb`-0AX1Jdyg2+@BI$iJ%|{$FiAIUd+PdcgV}75*g4em|{# z1|FEe`T$Xy3M#dgI4sPmPqSJ6@~`AQT9>N>l)Xs-4_Gc7xpXvhL>ClCCkEP*ha|;D zfn_#j55?ivq~3+pMM_a42=tAWrdWbk%>ZrrBvk#qG-klHBIF(PA2PGkS-M#4XgIskh3DMcka3jbY18y4*jl3n-;%c? z{Fj}bgZJ0lMd7pU*NytRx0{ET6K#`wK<~oAM|64r?G0QsDJ(iM5p==YSUP4-?8O7+H`RM3lIfX`B?u=6@|EaL-r;~hvsHa>V zpjnAwrnD>=^oSs0RR9g5jc8Ih{PUBN|jE{ffs3T_*+0_XYpjd#J_2v>)RL&au` z)v)T0Dk_}W)>qdi{eEk@?9&6Tqw7(ZCaX~IDpLt5u@Qyw@)L=s5h!)&SAX==%CzJ$ z1ifhH^7@JgH8Z|mEdr~H6DJ}@3~7rc3@NF~M0B8vxMFK%oH~(eCk9haq|+3o!o!~k zSWD|C#XIKaf?Lo;6#l%xwWH{8+#RsizVAd%VCa`+12#{k++dbOs4enz-H=M-qKing z$?mJ9j4H&{V}8L9iKx%#rSzCm(9zkK1TWXM$;;q1%u`EMGF}^=hA&u|Dw&XaPoXlD zCNRqNDBtxEy573j31|s!ZOn; z5!m1yZwGG$r7$PjfTt0;IWVB7CEVX4K2L7&yC3+gj_SPMb*^86hL5I9OAHj@BLAg&$p2h8wufWP# zt<<*4@ut`Z0fQoa^@0H2{(zT@Czs}eUGKEsRrOw!<*^`=EVgc6%K$_a~ zfs}dHWtu&*T(974HiSXX`M?l;5aC(|Ma18w!=DHed!~WoSoT11m=>eOJ82}0bcrXL zv~cC`>BhAPq}1IqM`7;2&Ey$z8W2O7+9s5QZ?1abGc0|`51(6BMN$p`g8W!O%7fbn zq#CntuEhktjuHhXZ;cWIR0j3C0gi5Ow(-|cqrPg z9Y5rtB1aC;G=qUDE<5+#nhH}?l*dlp6r*5PEEU41txfMPHy07CLs~6Gtaw$+Gk`vt$t4A zWs!E=HLqk?NHE{VdJR|G3wvye)WE)Yl zU#d!%!2JOKJ>e-vhI^g`(~C8D{F(;qYEC6APc#0ey^tBbcGW_ekQxmj`>DilsEfL9 zLehYiL&sDl<>CPeRBo>LT;BibSyTgWvU)`BZWulgOZ_d;aR!mkj|8Io?QjPUV$X*W z$pHpZRLogDH*i+*?XTm%{#(c*1V7wz{6K6kT9twG=URNlz`H*Yh*2mXRi_&D4>`w*S8=m^YZF~XU{3e>J6tQ*(xC})`7%# zJU}Qpr2gzI{jUD4JY5!1CHs<&?`vwMk%>~hcz{kAiz*$ku=BY&^C!RmV=q9cwv%o% z+NDjWc4w4D#cHlHD>1@k9lnNDs#M=PMtIZEKtx@ia!&*v*aWJwHgBY^HInfnZ_V_+ zRV%OZ#^vFMy^hzby~_)m2rsv{+r7CBBFbKMG#?QYF;TInDIU;=u?>PAWpZmOm`d#N z-!id^h|y7^ZdB)hxC(!7?f19x=r5C5pZ?vBCNwBu?ftOERtY0B#oN1GuXk7HHlo}=@>Me}flo>S)s;etW?aUVBchSxXa&UH0x(d9 zK)#xTjTfxT?W0!BrL~b1v%x$MnJWi|p|Mr~9bgZ))M&k#`7X(m!P+Dc?(p0mGRp^(|QuM+6_ zj&j+ut9-tGv2~8-?%alWIz4$zz6KjpCt$Y^UikED>_Ayez7hmI^gsN4BUoB-V$f1q z=;1NDl~JtcTvWrgC3be|eUTdE9wg-JE;?Co=c#FJ^)EMJY{rw5QcM9u>~TKHj=f@r zdMnkw^-|8!6{EDAY9I%}C`l})RF7(%{weEurY(7Q%&BFFX@zy0fiRVam`%5pX^lLN zIDv<@=#*p~X{dk!cEm6~_a^{kechIw9Vg5#fIO-Nd~==^p)kk%)$vb&orPl)Gi94z zYcME>`PyiC*sDrzo&R*2Mz6{*%rN$A9$6;xB@if4~Wz$1+zul?mBIY6gv=scpa#!b}P?CBw_S?&=pS&spOApQmkDIan^aIP>v6F-T zmH|efTTbHr%!1BdE0)bedv4cg=_QYR5+^%XGLnBxV|3lQFTJq2D@bYYhq4+|q?MX? z`fJ@OX#jHMc@4^L#PNgPIe;BXQBf1MEx6`4MA$f9NzV^i|7HXO5mL1I%KB1zCCl8_ zBV65XokImqVVst$^FAg9c?aIl*j8z9vd8zKNuTq;?Tw9ovBkNUictdjd6Lo0vMm36 zD6HWc@4p7tcGtH?Uy0Api~cctT!ry)YrWUYxFWm*T&^z@K5`f=;hmEvAKkh;Ss@-| zI%9#+{nsjxofV7h&>w+Ljz5h<-A56O4zx%aOEp4^Ik|l?UsH) z3Wuqdq+OqDDaOGkWAmqeRgic?_8|R1!^d`4}VvuDT@cn?NZXR4WRug^QF@@{3*ES^Y2z$5U$HoxS ztXN(_lYRG9JCskB1b5X(d<&J$v?$wp$iBq26lMB>JssR(@$4FWV*s)^`hp7Jl7#fC z!lF;}ObMQyPap}pP-8AWOi>Gl{QHO12-IpA++J9dUl@Ug!;U9liw_1AH2d#4dnzJk z%@y8LR#WLu<~w|*nM5;59S`)ypPkw^)Y7)Yc_cdmq9DhRPXRNrqK^Ywmc;$F;LZ4I*gygy~RX!|Pjfr1gEd#g^Jp54v~Ax#z+`P74-^$M>LpA~2McT0%N z=jl!3okT6pBiu|L>i+SBlqjBg&7=J8xxWl5%*s0`Mg9Y|B64jIdLdp6^Q@#!jj6-f z7@KUxvdLxi*Blc9;|QXLJh0Tw)mH9eL8A5I5H%Ev zS|TO!y0Svwx)nY|7B5YyQk;cIXx45StfTfX?TT)X?$l3a?eD`tpE4%c?**_Hb2cSK zBg`gVWJc3LJjGY1yVRcdTgu=S$m6HgPCG-Ee8q5Mc$%Ef<1soS44c0R{ z$V(A~JHz~*hJ2(yZqzWfNHp5zz@YXHQ)JT&nSUKL;Gw&$$!uWK&kedplc zGAI*qfLeBa>p{C?^vZB)HS~$~qX7<#3(QL$;PA7im_ci7ot`Iu_N@IEN@9suY5Iz8j#rD!23yJCwbv~roBNr zA0h_OwWRW5d+gQc@u`gH8V9$tS_G}|?7<>~lg-}lFQ=HeoS6qgro`Z=erMZKR=9c3 zAJjukMc%5s?G^KUI0;4Q9+(h6^E}oj+hjG6 zZkM>fCbm5dBucP^CC@$GXXi^Kz}t}KoNw~DX07PlUoOq>f+_+L`&~O^(5x5`2Xnfw zjC`K-wO$lWJsez=B2#ZMxK?J4tPgjp5rf`v(kw>vQYQn|4EKmdh?Yh*+BL&coH5k~ z(v~&Vw>m{n=TWDQD~O?8m`)}e3+Y^UF{^T^wQAI>4mp|ZSS!_)(~gyG>EMM9p<3wmNb_ElR6l@Ic(RGBJ)6QDbSJ6JT9&fSg=nKtm9m9)$6FF#SM}KzdOBaO z&9&c!6nI2+<@&GE)G|z7s`H}oUdN+EZo8DP3wOhPY<$tq;aXgZrTHVtl$z`hpLrJa zX7<_G@%UV4$?V!H@I>#?WXGM1MSvlBsA zh1EIatM;1qOV&j&H)b!3axp#Wbr#WhD8KGP z=vKd1?EKk4rQ=;jK-V~FNjaFkk1n>5Xh9~JKc@;|dQ6K$1zUml`Kj*EYE)72+8=k$37&#zg;J^G%2cy>GQ0)+J z=oG0Rb^d&G#`j~8y@l*PUTWi>UtHvx=3kyEO)h=7KjLbOJ@rTe5*c!B`BJa z6vSG`pdcY310$0Z2(+~e6yOv{au&36Os#HR;q1LTO=6iub#7?rS8;4Txm~_>9j4uB z35q!9WgxJ_~zAgQ~CZ3P1S?O_8Sx29z{?ET!5zld`)+&utN% zlB1HWhdJtZ!Mr-Y1pjz(lgFs7Wn-JXySZKN%)L=&zR1>Q*CnNmWiC-sN`3B}Ae$j= ztVWNI^bo??I9V*`?P&k9-O`r7SG}xM|8Btd&$BHkIqjQG~5}TYH67nLUlFZ*M5m&N}kp-KV9TVlJXKLh6*)pgt zd%03S9uVEIY@+r`>Uz8@99Yu~fv=dI*?P#|9<;bKGovBU?SiqoeWbXs@Z{q1quWPT zsq5=>feHWs1g4~GpyBEpk#_6Er?$SFj9Qx;85!B%;?PyUPE1TB06?))dkFYS-bwrV z`;?a!tx-@FEJdDYs`QC;g0tAgMKs#SLnVI;_HAu_-R}!aYG};w75KP5Q_xH)n4Ne$ zU3Rv7U2OL-{2l*$aeuAzJXb6mYx4PWBwIvw18rxw>R!)fQ9WSgqMnzZPw`TbtkO}> z#DpB$0H-jymVFdRQtQ>pu9aN1Y+F+spRh&ag5l)o*deFnH87m~yzCzlEUK=Zr6nh) zp{c2<^7J?8jK<-P%U0V~vs$N~&($}2WMWL;?OCqA*P?CK+Ak%grJOI|7jnc*?y#SN65S$3+8BNpR2j$|ZRQ>R#GIkS1c@ZMtfs3VdejFk+ra+JxA ziQe|^HVFeAy{Je+BImSMysS)gXsECExU{S(B>@VCSEyr3PU8F*QdMacuLeO=XxI!j z?V*3G&+Y!GM7Fkv3)|o#FPwf30h~Sz_M*Iqh=`1`va*cKb+K$osCRt;pW1l0_eUS` zvToFIi>!aW^NVD*gPj@0ebx5Bv#Z=6Uh%_2j>zM0*+&U z|D-UAoTi!zO9umSG`^ji#qmgzwrW@dkh??+Y+uO{Hapa)sr!N+w2ozT8-Qnov+oG}=0FaF&(G^X= zmuH}fUQop9(iM4oC*-jblfnJOMed(Dp}(X{dZq;7_ZI>Am6Xp!se}|RznYGcmeyLu zgbbv&D66`nVtsRF$GHak^Tyx}5qNWPagpDDZZr(~RYTcb=}{6KUXWhW>&9QzHm5zq z;Cy}1v6^vyemx^v=8Ljivb}wmu4&5W<yFgyVtiT^Kwa=C6^w&wN;eSmS9PvcITPW$@o z`cTnO5^Woq@0xN(Xn%G8T{Ac{c=khd0g3v+RxVuO{k!l{{d zeJ!o3)K(McJoH$Akod5Y9&-CM_4>|*#v%_5N2?EyUH;#Mz~fzb;u!@-s9kEl z@0Uscd*&hjuC?pEWBS*U<>lojcW`VGh-NHL)4#KuF0Og~$)Ag4*C~kh68Ygz<9Wgv z8S!7@Aeg^uro@f1c?`A@;?BQ9IXDi2L9`8w zl#bfCph$5|HS|Vtp18Ht)j0(Q=D^kpEhe28ZY;_3tD7dlb^43@Ln8wB_wO&UGEk9O zTB|WM`mZ!renZ$VE@~VNuR#SSEe?!?s!K>n_wdhUR02LO7YecLluw;{?vAEB zJUr-VX_2m`CP8LrG3DcRI@}NFydC<+h4D)?Z$s zxmNgWaZ9|xcK@ccd3vI)3D&d9BO}|{*$IJyj;5xT24?s2lyO*pKPPH~S4_h$ZJ-oT_-c?g49RdGhUEjdF!4qw3tg;|$hsDRoS65fR zySoDc0kKt;mzOUqEAtCvu5@Us5^R&rZgOG(2P0nmSq#UpS$nD54T;P^*Xnu zW4bCPE%Uh{YRFA-vii4iww=Q_Ga@qGqkCo;aUBKQ*47rO!Ljtr!^WnjpukYux+*_D zz9uH7njj=OfOJ*T=pZuylqfp>@d>@&>5}T}^9IW$Zh2*eXh2tAN}B2PG!Xe}&{RP3 zI^+|fqwxqq-6?59WFcuMBcg-I&O_1I>7q`w?~V`P}$w9l}G8y&DzXNO+zIl zB>GEH;*>S3q3F;xu^*;Ic3A`dF?Lg%#m&u4F1K9LMXhZcU9KWJyUdFuj)L3>Po9y?C~0zP7-4IZAiw>-zqUk3*VeV6#eq^mhsC|NI4&NaKx z({v&r67ICotYoIJyVv`$1f9%Wbm~yR{;!5 zO-&3kG8VMNWA;L^j*eL!ukVc^^j6~JSOg0tZET*)wdDP>r;g8}h$=YP)YNEZVTx<` zkeZNkCnwA+OF)0O@73?75yXPhCm6vkK#1KpF?9HRjU>bJVT8`5W($vQv0u!GLki+8 ztuN*UAu@Hae`;<)gv{-!Rcd2-ZnGcZirB@ILVI+wgX}E)g>*~c4y0rmJvyEC!(#s~ zBDd%a1|yhln29}23qr)0TRp7Ggfb4|rwI1+JBPU&ii!=7Q8r(7Ro5w!@^YKoWo|@g z%6@Y5Nhz1puXI0(O`Gsyt0}39$nY}NlHRKMX6VLU4t+W1NB(q-ry=-v2`W<38mi=+ zEyHPiVq)UM!^7ZU*q|UTe_D+(waratV`Jka1D`1b7Y7!M-?z7yzZJS&Kita>_46W7 z|6a||7!Sf{)}EYj&Q0?|{Xkos>p0XIuBNRe>;Y6~U&ae{rJJ^RBTD0p7G1j4DJW`N z^JMV6?}Bfk3JAc#eR+1uIf5Y)=twIq^wHKlyH93&lk#& z?h+N2kPE)4j4dd^z&yE3SHcxuIKYLP2?`3%=Bk_u359%#q5)EDwzr>so`D2z&(Gna z5OCOBE%iab85kIdh=^)igw@sEmA>2MUIm5)J=l1CFc4(FwYyAZ|33itKnTA*Q;L5Q zB1VgM!s6y?33EMO=YBj{VFPp!E|Y_4WMF`bNK(FEU+>iw^)=&&6P*j~S`&B(}baWiGkDlB|o1A{@g1ih}ouJ-i54f;bt;entar6vST2n76g z^HMKf43M&^rDZgn7BuM>jfK*Po}8bfA=CqJJ6DVf6V9 zHwaQp^Bca$H!m(P!}ZW)LaECt5;Ia$(GZokbEqzTpyCnCO3Sum!^5f$%iTdiK_*4f zmuS&k#>LUm8i~IcWC++;S?k{&e(EqnM@PrLaigWBg)Rq>;L+{R87t0knxJ<;Xi(-Z zE-p{v;q3c<2%sTc_ZU&KYTb{wz`!!n(?|ZO00ll%R_^cX+ZMcDBPdVH$dGyZ^eQR7 z8RMa-)tz#->FAdV`aGH z4>h!}xgXrb@#o^ay}$G3Vy4c0w%$|F`^wkp-$~@VwS-e|`OJQ-jRqw0W(k_-$r{c+M=Y$1`(sLSbTcbns7;?vp%saJc32 z0LNboWCG9|_=|y_9vuTCQONBjXs#(Ujfe-hQ@p5m{f7@yrlu=D1RNL{8Bx*Ds_M= zGIYw*K5mPB{175;a4ZsR8_ktk$K&aq#%Xpxz)>hLXb|=?Edu&HL&>(CFOC!$k^EGe6ci) zTW{}?==A#Qa?A0r_vGHbeG7U`gdO5Jk}_as9XD9(=KOE8K-B%n(%3jXDoSnp?fAIn z=H@0kD&%f;*^aBr^RS)<5n}AKX^?xq$MKoT$jr760SLZ-J=)`beQjf9m6wx4Dd^0O z5PSBlV`#_$&KQCev>6<-qod==*>t|`Go}zo$79#GN{}l!w~1K1FaGh1u?P4wV@117-yCitRqgu?OC>7< zJEP^VZ*7@y#ekMm@>-r0giH3@Sd8U+{uv(L+^~$1UvBcNKZJ-@lC!+LY&BVa`0yq< zIrMgh@_k6~*G@L=3Zi;?vk>^KCQ8j4pHNe8jgOBrDB z$SWCZtF$+R9*pMu7iq8y2vk7_uC1*dSsO@)bxg}eu>%E|_F+=<+tPAyaEOY|4h_B1 z)O2e!?1_G4IGnAj!s>LoM`|-$|C9g=K^xK0mvB$FftrPl?Yt#|_~y;zp*0?gy9i}X z&1Xyz0#v=G)j~%Zxw%v%Br4k4HINSUJ+;o{o;_=svu$r1o0-8x{Ix{{Ng0%k^HY6k zoG~5FVhxNyx|o0s_?3)x9r839--c z@mEsmp;@45+rHc-Bp~qGrFZN6#sb)mK%AZ?#>T~=p?+D|bwwcJpu>8ZB04O2&!=l# zAUj=BYJ-G;@=)Bl16J45*LQuiSp!HUdZi)gwEm~B4HE3jSFgq`kM>vkoE#k?Q9$4w z$)lc`sd=r#2WfyHaAGz0-=VE8BIRTtCguA!1QzBXU=FOY( zOhb*0I|HdQ08k<#?)LWfSt_wWEcUc84Yjqk+@`&X(VSj0LN%L{6Pg5{YU1g}6OH6Q`CnQrH5szC?AYl}pC%O28fw5evQ;xKNu_7NhwkrhWF5$K#gH zFJ8Qmlw^okRFad6<1)r^0lAz5xpLV$;Np%uI6I^y!ExGORscSLS*)zGf=+%kgwk{1jS(iykTx@LE$+%^CZ0tIiF$9VqKYm=yx8RcC7#kTmUSA1E zPtmP%*Soaq5r*c8i~G#pLH7}pm6KZ#`7B~J@kg`7#4eEouuRd!gsGw!RIKi@b|#MR z@#Dzv-<4vx?g&E3*mxJR#sLtqFz!=rEJgv z-dCs<$m^j6+f5)pVPVRwk!LH3|BQ`|`w~S9va_o_PWPZ1$vM96y6(cC097WvrHkdt zw}O5+j#?rKJeOPsPVFsRLPA<_H9gpZcgMjE5}aAfOSb zk!fFf0=OVZhfD~Cv8m}K)aAEt2kXNYh(?gsrKP2r25%)=9ux%o1Jl*jRYoQzRTUKk z;&VtF$f19r%%71FR0PlC$2vOKzYU5I?@jxNp*4PmI80UA0hY~Q8B0n?2nq^bUpUmI zq=008PfJT1$=C7AwX(MU5)=eP2zBmkZ$F=)C@wB;wn~aXkOh|&#e_^fEy&OR5)zV^ zpa1C5qXbcJuWM6=falWECQqLVQ0ym|a^d zMEe(gPfQeDyg#)0T!*ef98AE{lKuDrmpAratVHtb8t0Ijw}WZVZZXN9#Ci^zl|l_x z*0_6|9hi51>qwOjq4@P4LbRyIiCF3j)9ylWB6BON1zY~TJ$p%4Y&b45*Ci1Is4{m+ zhkE{NCkKau%*-FWn~5=5cKkmgBM+McLoY4~!5huZJgmMfudF0KGHgwGirXOadB)*A z-p`tvNr-p@1G^We4usUd&rddXkB;g+PG71HH(+{S$LgRUL_E)a$8Tc$Cf&qmI!1w@ z8$x5_D?hY8Urcf5<87ZNeMcv!D0a;hC>I-1rRUH0{<#E8B!|5rX^@5zmz8ZN&v_~% z6ZqjnzE;`#TyvmOqR0(g+&JDIdXX!-3P>ka-q%-Pn)Q`zWWl7w#J}Q+(EjJe^j-k+ zgfqy9dR?5f#I|EM=I48}vap~ac3f*g9lqT4wqt{;-5OtLHt}|QxCSg97%1Z*^M?ri zQbOPUS{G9L{_^;2rQQD4bPWYXYN5u|H+&z zv$C?ln{+Cy;{gPp2LIUK+e0AGQQusii9!mI$`~rrn1T*MK|mbR)txagnAc#30J;FN z^ihmF0>L#>71%cN^(*m~b$on$c+tkKTeqO;fUh3v5ey6rJb3tUYh%OFX}ZvId=Kh6 zIz|Bqg7v@4|H;Y8IqEeKjo7uzJ&r6XpTsL>3~kTU0j-6$%o`aQU0z<+R9AbA1mcMI zyDZp_&6ZTw)OfE@dyONnD5U8W8`!g%6%DBq}(@*#1OQ4xL z+c^n>K!s#Sa#B)-Se_ffEo3Alr4)08illce8<3XKY!kWadmKT;HTmZkrsAr zSAt+6C&$LP$Q3>|C8&t%6BZqfjnF7IdZwvqE+cb(cK8n;4=+2LRZ#F54EhTd6?P5| z!=h+a)yS)>E5v*7DHV0~qVZgAQ^inf;U}QzNlE%Z#NcaK1RJJB(al#brvq~D-n~;% zSu6}hA+PjUK`oeSxJyGbo2|;mXE}yIfTC79{WCF`FIinZ|M~N0qKN0as|z;>ZML?B zF)`zRvR)0Cm8PWl*3}8SIM^Y#N4Fw&Z{taei=za$(5uh-`uf87{Q4yUM4<;h(AL)4 zD(rD$JNnQDQ2FW87O)u**LXn}YQ+2IxudOV_x+9fdGbNWNe>Se*T=5kMFx;2Am9d)vK&OO$56q zy9@+@5m8aC4+Nan(*go8k2kwxxF4{y4-O5Xp(<8ZSAV%H$P4LxLnBq>yvd-5S@8z~ zQ47txyYQj7c(3Wp$jA~`|CbHaOgC_@S64QsM6BM=o4E$q%qLqkIl=zho=B9VMh zaCC8s>*5j$gV>WOniv{Ni1_n2To$tIA{pCDiPQml`g}CR)>PG9O3Jo80Fcd%4S59x zU||6&#l%bK;)~M^w#etxb?z0Fl_#cO?$gtMYM!&6u6{~O6h=%C=&--sv$chyi0+%D z2d3d?Z(I2N+qcglAwbkn1qcLhoB|^;hi>f&^a&irLH^XxzDp`jT#w?jXR0q=6qT31 zR8@V<&E3`A-PzIcrbq)1(@%a26A>oMh~xh?GID%oCjaM89OQ*0b~0QA6Y2U%Y z0lRMP?cf#|f@O$~P`<;%k3~d83=C2b2m&msCyVMD8XqlN42ncNPLy?ZMcnp`NY?eL z;yR1~-Rs=;A#@k$H7afAQv7kri#2lB*I5yby9+215)u>?6o9=~SAoycde6?D z;P^|>5)n}G|6O0t{wdRm(el6d0{mpUcdy5!1O_z|pxi=mbZBTF0*jYd;Kc<23PLUa zwYjk|20|?PeOA_5wrUO-Bfu(j+Cp0>@DlhaofX$@Jhj)aFNQLFA(X~MM`vbbK}Y=% zbRh_BV^HG7z{Gr@QP?=+m5`YUkzGz+eq()ItL*J?k)h0J!8P}zM>p4OQj?Q!(p)2| z+z{gZ1%yn;eMKcDU47Rld&bZ0_kw#Bi4jPdBOo|}?CzN#JUvzZyRA)KMdjnik3w!= zlOW-!03}IlX-%{QH{B=cobf`5SJVU324MgVMnMP*3*WhO2h7*n+InJQqNAh3`(igR zHkJbM*ZUgxrMkLg>cFcEMW7=Xw2ckR?dh5}gQDf$cnd?r=C(F0L^PLiC*&^3U|>LT z5fNyJv3k$Rl&8JVpMR3ohd++DXKUP#X8`#_LPBVST#2YWlB;51c76e~pP!!t4)n$g zk|PS?D^XEVgM(b|?(Xbl7N(}h%RT?xkGEh_DJdu(YM0ADf4-jKbw-5liA56Fe3h{I zKQ}-SsPZtpkdpck+!ag7mlE|rn|G>6Op=y?p(G{6*nRKzt zjm#0C`_it`a8`K>0^r5O0AW{oT~>enI{)DVI`4VSL?tb@Zvakh^4aFe$qAD}><7F7 z3`l%(KI;FE@BQM3CL~Z}`t1%8$RsO=RprpG@}Wcs^5EG!>>C&ugvp?LeVL!12h+08 zc;rKyfE6Janv<2~c6Km6RaFiGzOK`&&&g{&b)Si8#yvbL>Y1$TU=2l#{FhIko`6g@ z`PIk7#GpAZGDmdOIB!C4H!s}F&CR6|`nW=%FhvvC>~?Xo>xX3rx)JgHI~JnftQ00x zv_TR;EFeI4O{c25TKehJGNrJgpPIC(i_A<+$R=+NB%G{phun880PUQR^AB@txVosQ zD1GU(WFUbZ)}sL08O-yleSXNxXnv2t(mVr-EG;cPF3&=elj&U0OOKA6G5vhxy8`b& zcmOn;n2<0tQDy;6i!~)0uQ*%pc@CLfRaG@eY981X(kd!iAEXfH#xqF!5Nf_Z)FHlg zOY%94HX|b=cqu5{ozLE$Y`ZR^7isi~t$o|(B?Y%GU@fH_o9P=JJjK-{_&0Y41E!AO!R!fkgx9dL1NZS8P8!@tE5 z)6eemozZoSJnhG}#>K0+!QtU}(b=qHA&>Cz7wuyW5G7+a)~kJbOx)czH#~PI!J2C9 z7@og+bqkS{o&D})=Zz3G@-n~v5;=#ikms3W?+*dJTXYb8U_uTKub=e`2nawxYcG12 zI%JM~bM@?6G+dUQY|@mM^h04`SY6#E5MWhAju`S5i%Y&?=BH343%jn8l4y%omX;fk z$fZN6>)em2&CTyPIfVd|a>Yz}i-MrI3MHJYsj89&Hs@l0cG0Fqz6dNlBsq_wS!l{1Y85t#=F3 z-(q9mT3Gyx;Wkw((7i`TH}L1r53nv(RsU|icK;Rw6vUl7YqMmS=piIK0j%hi>+6Hh7#8i;9XO#9((bLg$T*jgU#Oad8RDX;>rQfp8kOeaX(u#H&2w zt~0BL?oj|(ef|1}wtZ8a&^O2u!l^iAFeEW-HMxv@|NW~mACiWOLx^pg`#hDBD$=mDv%67|mXX0MDyj$Rzq~`N z7Qeh|Uu5wMePFXm$@nEl-OvzsT3T9IX?vMb$JfkEN@!M0OiVML>ZGK??CildQ$l;b zJs<$Uh%a9VdV6~vpImmwlt5JvkB+Wb>+0!w|82Yy!2%2Bdvqr;CPqL%%#&JgJ*2}( zT1KX(stUg{s>h_QrR5G~oP0DV3QPF6Z&I;;Q4q$)#sHKNOfmNVhRhtF#6vDyY$CuC zuSH>Up*}v^tXW+(BMVm5&>$ftMPBF@aS=>SNr6N&V9F*eTqo#aO(S3rnyvc$d3H(3 zzm4&dsg3cmvD>7i#&4e#<>au@{{7I+FF>8@RB_C{VF6xn@yCJexV zfdSIe0^moO0SiDEXc- zzJ$C`Rpqvwa0u?=D&#fy3q$YZFRj@J$-^uBb9|xy_51!X2)-mZ7;C>iHt*tMW9t`P zpGj|TY(VQuJ?uEQ2|lnQCm|swKFhf2*J1QkmJvpohhlnsyv5+~uGLMyrh~1KU&8|f zMb4XArlu><`VP3`mb{VAH`mrs5J>}OUS2*kZK#O;HAjk&07si`KZ)cIfih#0eG3Fa zjUhXL#93M9gM%-TG^(upckAtN_As33OwFiip*z~0J29lBOLYt%lESfd!7#nNu4Y`G zpPzT%XY;cPZqlz5p5Hw|`Ff(i<9d-GETXHc%Wa~;%6b)V3xpXK*8e{56q|}5uo-_! zgM*Q=)O@HFh2e*=`w`5=`L~tDMd%~fch=W8T|DVlzoXh@N{9}BxUo=ISNBk-T9!WC zYcClLCqd{LB(d}NqNqsYU~^f`kVsZ`SndvwjPyKM4Np(MSJAX6lareZ)jnNrMLGDC z*w>X>eyg98^UeY}4 z;YTJWCa;qnpXNCrmb5WjK;kl(yH2f@|FB_dqa$bK~T@xvOI z?fmR)k3-g;u`zyD)~`)TgtsO2|7v1k1^)Ww3mFw0BwxGYi~JS^yFPu9+jO;)zrTO` zBnXIo8|PmNQ7<8%{*M3x*m~ubns45SzkHdJnz~TqViUeMG7_blqlSS_l`)VBdx4s^tFN(Io;1``!6bUXx?km^sGek~G^&uHk! zopXdJX1qear#tBGC1_0-*ORP#Uxl?y$&brlqRRfB<3P$&vg?Any6J99;=y8Q6tDF^ z&o~O=$;ilHPlB#Hv=JR1R~G`oEpM%@>m62jsY7L$oBcONF3$({_UxZOe?IjK1DEW;dbO{&cVKjs=J8vS zih4K(m*3Cb+%Rt32x3-BKp>bDe~2+f1P5Oy+{5u}qDAv@a&!bSuB@pc6zMP2 z)hTJN|Lza@n3$M!baukI5mc6^r(*=SJk+blL%eS>I5|DlYw((`+3pD@@0gyRzAR`1 z_s2$;fO)7uchk|+8_i$}k#^tt>yw*nxh?SIOa&VsU#HTRZZCLlp)C}FKtuDpN=8L2 zgRvWR%&)FSPfbmI=Xj--tKlP$N=ij#X@uN(##Y{M6ecC<7vd28meaS1(R< z41T&e7@3&py*8NM)I{F*L%_nyDla9)w{79{HIW0Y6cZb}x4SFsaS|raBq+%7*2+rQWlJc03?#hNZU5(tp1TG+nZJaw ziAkPr-Pt}31^O-md1rfPS65e0PsF#24DK5=G>K(ps=(n-pDuY%Kf&_Y$eu5*hxgH=HBp@aD2Km)^^J{}Kpw4U>*J-? zEiEjDhKD!3-L8;tJH5}(-_jTVnUTT9!eSTq3Q7lousli<9=dn$9{B^UQme@k&@Jp6 zHy-oy2Kf8iOjna43auuOK7Yp3)0_SD$zFXF9}hFNue|-664CE{}1A=#~Buey|8OKoQMsY;bXKI(vJg z!otM%OuQ8pzW_%F3x9)6-6RQOgSpsd;&qr)W!yi?8e6IYDJVe27-+s-e}3KrF7T5LQ~fdGo@_spn7D@)R)- zg_Wu4=-62MCWDHq>Ue*@z6o#D^^KV-hc;+9b0wL2!h?f@N>VTpQ5pgCUDoI+Z{Qng z6O)LUS~rJHt=n96P5|xl^3dj%q>+8X91}85PLF-W3d_s4UR^;|j*V$RXdN6JR7wgT~_zo=1;v-n!-B=%`V# zMQCVfC@44yr9=?eW5mV9jpPI{rjlZ=82MIxK>^RRZ*_H^iN7F;!x0^ynkE$#%nnJ; z*^c31UP1%cIByP)j1Umi_nS^C#PQDA@_S!PQW3sl`Zr9{CwM&yPL0~2UcrMIHa1pigFa#(d&LIHGWN!qdSAZ#@a0SIic4I0 zxaNx&^&Y2t$)9fd24Gk^1bSiOVU}2Y=L?dO2uPtKwzs#xmJB;pKQk(*UG4(QOLa9_$wQzb{^}!n=SDdtSA$=kA%? z@87=_6GbB9;^fj_y1V3GC(kro7wR{mE;ilAKJ#o`B)C+$Pm+Cof-Xw3agKeNP|sKO z>i)NslzF-v7`|Q@!^6YPcTv&teYO?0Mn=>)bcJZXDkt^n7ikm~+4?ycAA9A z0oC+c{otmirY35=LUiEZVWTd)y7GU2q9$NAoIytU{=p9c-l;4hTI_Yg@+wJ&?gU|X zuustRl|DWBI9{v4G!*LhzO>lR{vV{N-P}&gEJoRNH(sl$Rl980fBiZratmLA2nd7c zWma}}zDCinE(>Hvg?Ksxsd(z9cs~a^ZOd+Y$RyH=*d%Q%y zQ}yiwT|+`bdght~W8{}1mR+tW`zOt!TSob~MgU*u!}m9Hx$0GExp zlG1i}%n*>f%oi$!=g%p&Y?04n!PJN3Y81`)(~07wuS`|#OBr<82BL|J5+O^8!;EL5 zsi{6KZE?OuUsY8V7Z(>FKV*&o$2R~dj)Bsz$;{ds6Vcw;2?+u01ZtL@o&DZD3Z+`iqud4F(dsKjRW>hE9NX3En7 z{R`;rwos1y_pu2HGnC(5TzEi&+1(}V>U`d@XbnT9J}Np}=l=c2kIzl|mR45KG21hB zlM@rHbaY6p-(ngbe(dB_22H!ehtBf>kaT>xr=+AJ5eu=iGlqk>|KI^Wo>1`XFdSUm z5{(U~e3e&Fk$3m)>|m1xKc0H?1rL(` zWI6Kvprf5Jt(V9*Fzeqi^H4zSM2*3s3PnC@U^!LEA}UG~+``JrYCTq%e9V!Noy}?i zugk{9OG)sI5dR)T=-! zQ4YjyGH=@^h$<^9%dS;=|Ni}*@eP%kJ}4aGpg&_{ zoL(0v$J?{&AVlh;x9{9RMST1n1FW6K@LkA|5Dnl3-QC>!q8}M{d~LZ;(g}nweA%-(>4LmtB_-uG zO!mM49S6tv@84w@%m41q10OXzJz?<8%F6QhfBJH8Kah}y>-OgtsnVWyw>c*W9%yBzr>pAe(GU~E>~GJ{`%0(6xZVGj05%MW&c@36`t@sI z5AR=Y;teUvc+`y>^hf`+Z)B6I%TyXooa1-f;} z7lqNB`-1ITkH_SKeZ~sWe73~2qPlv*AD28kJ3By-3i}LoOp?I&$`33gE;beu6SGJ| z9*Q?j4iEj(_iv;i`X!%-hetxf_JK(@$tfwt?+&x8 ztE(fJm15$Qkhjf6M~~TJVTfP9SKlH!*!&h5NqBe9utdPL_eapDPyZ{(y<=(~5-&|S@xga?m5N*Tz?nz`_~t@Osb3L(ePOR!KA)7K08&Yc)xcV`zTr+9w5 zm(tSjjyA^O?2s=_>C?l-@IIhbR8nnos>8Pu(7vbXSoSd|1NApe6`vCh*N@`4WuB7C%CLt$3KRdfBWss=F=k5Azd3bne zXJ-dzCRsBHJ!{&RpsKD;xM_`oC@U)~Dk>tuF)qY`2?S=6^qSI}9ZZ)4UtgXpdd$O9 zT3=7i0yYksN;%V*bo1@)cU{W&zqLwBSXkf&Hs2&6d8w{`>(;G*8ykQo5)u-CWW~kV zb)N5Ix(hXO^Yb4LK5WwGgleCh(854R2jFdKY0=iw+Hn=a+^^!MkLZBE%QM|_voJDZ zynlbJfg+-VorOi5i%C?p0TA&aH~Yo^-V5-4*y{_N!20@IijaWjIjC%7BO`t)@N<0X zP$hZ!gTq6%2M>DsuJ5z5K4A*jVeSO1n7;TNp8=zNGO)_2dCFr~?>ZLK+b%X=zYOr9|uS z=xEo&^|I(_GkzDggG4+24I2$Ove3JNM|u?oTz9gvSmeGx93CD09u^k%?HlsRzp}EP zjt&CcnxmslZGyn*A<3Z6pQVb?s6)SBc!SsN?d=H&2v8B!TnBfdpNdGz_b<6tL? zkl&gp>!L*1{u}AJB8B8{$4|83B^UymO*mKKf5AX-aByVpS8T_4D2B(!?;!g7mHVc7IXFf;I&M7MLP0^% zU>}*D&MPbPZ+>HHYI=FPl4xRLq9?!A{xv?{pYa&NN<}Hrx%yubjOWRY-uujQv_v4| z^=|t|N97o}WC#SWr^2fAAyi23A)15rTouUVDrv{t|W^znJ8s`=_RO zHWF{VmhRt+n3x*3be59(4GEk{flEQwbz^ank(n6_d0!OF!;2T;AWJqjHZrUWw)~3} zg?xsF3zC5sKr|=_at_@;gM&}p_89k^e|@+iF7ET{r~GNBK4>xm@hT&>!SkH=Nwv*B z1hAzzKASMMV;dNj&84!E%*@qEUI3V>!Z!Lf+WhYH!--zO!eC}(2V<#JkAp)YbfKicg2&M`VP)YZ{ZR8bMQ zx!pf{{>*ACFE0=B@zZ2wXs#E^%Bv+XZO#y>LFk)!Gltg2#|4&`y)$g+=#l~UOH0+K zFv(C*d;kCrub-dbxwwS7Y|qTrdv>)LKPCuVh+<}B1a6Rh{v7sWk894O1#uN*6373g zrsf-)?Y|qf*r#t<*x75H{*eX!$;!-pFTGz?nQKy{K~1flnwpA%fx)DdfV>0Z?7*Cz zO#Ag~kBzb2!9n6jkBWNY`1)eF0}~S)ii#eAy)!cMK&F|gJGZkd!Xi8?FDq+pX?gbi zxvRT7E;jZ70j0l$xw*O3Ol{S%@!g0HkDb5bwziysXj4<=-En-OvWy9WF35*-U%q@f zFfhPKjC|X6uGy6<=Ev8szRhzVrI3%HQBqPuIe~~5=!Hg$cve?bxLlhu;o=56Z=B%z zOH7V+>sH#%K^YCKiWl6-&C7!(gAm8U67;Eh0O)UIgq59reyQx0q@*7ucSHyBhP|aO zIy0VkmuF56%iVW!gP9|rhlF~&?iz6VOAL(C)S32eA@dH?`@~R*WEh7vtWA&c;&jA& zP`uXGRtA|bPXsxxV(z*oh0E#bT{GW1{`T$L{Ja5fu(@Fy1-?cTBqVRTpg%14@3+s{ z8W3@yTg8|&&65SW3`_S zsKW+y8s-_~O|!(L4)Ff+oDgL9@DQJe!fNi9zbBWVdSdvqm#E^bxx) z>Q(FO>swKA45eZ5_ALqm=nD|oV{h@9v@}y-^D{a3GMm|Y7#^VDA3|>H$Sa#%0t^hV zw6)!*tDQW*JWW4xbPD(MI2s!p^Vog0w6cPQT)F{{(FLRgi;x-&$llQrqS(|NH;IT42-xjaGM2Ban6z~3C(8~$Z(dv^H!+DoAQoCfYCKK{y{o5HUc4Yc=yR?@ zZ@`%F^76Ke3s4=k1UCVA@=!QkU7Y^Co}8+w>2P*-hAM)ykbMl9%fZ2cAn@|y)B!vd zCW>|m;%RnH&Qo2vXU`OV@ZWTs{`1F3U;i&?zniwIY8Ir6pFabpxRF=g5RK410#wd+ zb}uX}f3Dy%LPwTlnJ8am-qY-jdR#x6Q-Dh0POGrqlu6|O%Wq*t`D|5P; zI(Kpe!0@e`H^rG;?lFlp8x#%wRFHgY4^e7z5-IKR@sIxwoR?NPe8(k!_}8{FEv=zh ztW`0ypkU#`JFceTI=Q@DjV$;M2?=Dx+{{c36_t-FThq%|s{;%qII1sSey*+ax_p9Y z>;dGs8n_x=Vw;?rt?#L^zjv_m0iC?kqsM-K`MS&{!A^l)2Q4v7jFvW8w&3N{w2vA$ ze@m;!`lg^dr)QDhY{EQhB_(2edXt@&evC*;ES=%0m{{xq{bReg0zU;9V~67jc@;_uwt?*2X{1qCrF>E+H`Gk6gT36A6237*F|{_`6fr8cu7Fwdr@ z8856J1%JZ%_wV2S-kz|KGb-XXUMmD}a~_IwEmAG=oXkvlj|+B{uW{eNj=mmH5=1GLp%`_R4>r=T>rxY)X_)L*BMz3cHSsP6WA>5eN~&5 zW)$66?evfKGBhX0LP24(C74{V!AqEH%I)=QDv&{2I`k)L%J-pPqP~8;$ZcwDyomA0 z=+Jrg><03|vf+V&ChMYLFr1Bh@)uWDDoRSc57(V+cQAkmPEN3hiHS>02?=}s z#b_O!Ou^N*rvE9VzjShP(hMcCv)gTK+&@1$wVbInp5Q54XbYvhb0_3a`oZxrAwGVd zR+;_3kvv0u%%BUGls1FYxVWZ9g!TOKp0TZ+o%k`=y5#Oas!UcEhrGNz4-b#XzbqDd z`eNH;aeaM#&r2*oZ_t926nbYAH47>#s(0_+kw1K`FF;c`G%^w(M%$YpjArhxuU}85 z!djM`OvlR`^*sIT^wcx>VY|^D@?I)Q$qLKyl#Gny2i3O|w|S}xUYol^?g1AjC8^b{ zpPF~zkVzfDCA&CZdtL3=F*!-8b@b`uM^`sD2)ly(x%dS2wo9E$eQ(Emt%reL6NKH5 z=AUXA7|i#^3(7pK1L1%E{8LR$TalrRdagzjw9fiEPP_r zf-LvM1?J@4#3n#T4UdTEs;3+Wm}h4f%5Ffe4=`Jo^D($)du>f%eVJ}?=y!d_*#pi; zkJeUKh1`#RL`5B?JPo+jP?(j~G4AFEq!!L_1<@HSa{=4I&MsxZOk6xUJR`}yueTQ} z-e}s=!GSxi{LD(9^Y--gbb+2}{kucrz~(ocw>>@4gr4p0_%PmIXPW3US%*1 zk&(lNs;83`HV*dorDbJ)zNj2}_1*fM(6rL!w9L$WZhMOmZE8JEiL;Z3){>LoprN6q ze(CJ(g{-;-UJ2eyQ=iT6#JfTHo=(!3mVx#n|Ir-05jy$dQD1 zpJ3OyhA2JnL_VN#6v&4QG{qFL_OB+A9Qa6X73nlD~F%Dx@> z93LC|CtN%iI8U!eRm)$Dd{krtqP1hILLJyZ#!M? z`$&O{$H~sX;Xghzp4hs&>ERspD|bCZpB4iEW*n=a%lq|1o$(P7`v+^U;P*ImYYR(D zCra9e0AkeCqB@MgU?JkBC}$S2OG*z84=>Hnzx&&G1s%1wyX)laobbfyQ($1*z`!nU zYq@dPGPh|j@_o6Q(5pm!&S(|ZNU_FO_esE|l$8+*l@K9@hacP79ha7tGAYC^Zfq}Wu5!6BIC^a4iqaTARs_-hZV;kD(UR(3>^a_E-o&)O(00h`t4iaZq1k=wnX^|p`@b1BP6657RpLZT^KJhTHRji zdT`~A_*_~_uEDM*Eq&I&BS9aom?+|Tv?1W>dAYO0DK0L4-x)hbK0hbN#l^+@c0c%t^dKmJs@N6j}vsshZ>D! z`|j@U9xX2|*&MjIXxiEN9P$40+*3|&mVkgbpv=&`YW|nMJ~sfoK|{WG$?5(IhelFH zR#tLS5)qN@7kQ=-Q3NWAp4ORjAGH#qvC6@;tE=ndZ#t%ko40RQdYsy~^Zv}wKbmWn z5)jZtG#X)qZI z!q?AlT-ef_=dIQRu4J=65E8I_zbV*jk=y=qN{R$ign0T(3Q9_O`Ohc_J{xKHb!QhB zcnK7Q?P|YxJIcvGY9Qc~ZlTzAqtE5dn>Xd6*vZJqW+2medFfhO;vw{R=UWaBozT!K zH#XRLD1>21eSI%lTQT|g)Devd!U>z3R`~cdB&4KORbX>f-Nod;7O=pa=rF!TMM3j1 z`Mfv9zdG8SOi4+3{`@&0uAs+BVO}0SqOqwdxw0~|sHkaVL`_Re3&g$&RT%95{d))3 z3q(Xml5+dgr^pqWz=O@rId)D^p2Q#R83)wX3PED}`#0>{H#{7iw3jTiZHs@kwY!wF zz9l8mK75#eSJ3(M+3@DpmR6BLOO4CY#;gaTvD`{K@Y(z>8q|^s>peEMh=>S>SrHpd zzut#o(b0uY|8{a(IY4~(SNc|#mLkK#?z6B^v)FD;0f{h}QM}QV_Ovs%wCw-$2U5dH z=q4i*6E+S`Z=z^Ji35q!+WPu2cuPNvnUV#l*mY5x-E-M?3`Aq93}J%~d1@4m{sRVD z+P_;{<<`>^|8uh|_ia3MRH(4bd=Y$mY*gf;I~8SRr)Ospfuy9QU%!5B_LV<9IRVKw zg`^I#(p88WXxXAKT14kE0*#h9XlZE)a5F4RPgOOtv=n~-xZ26$0eg2cvxlT4TH43= z53_P}zkU6RT(&1GYy9uuzmQKMAK;R$f`vnKewJmFmXVq=Es(LbwRLoKR7_ys*xr^&e~E&~y|hL30rCHtk%6^IqN=XW#==s>Q^KY`p%}xJ zo}K+tQ`2~aT?f@i|IM4^jEs!jTs#E$(hC(86?OGMF2J(#3l6H>K+v+YZ~QI%nVRb0 z!R-U2dxzV^)wL20GCXFyqW9?@sgKy-g#|+^73g>;C(i%_{9pb3M8Qi+&)-4kdCf_1 zo@b4WjGUaf>ggo{?D!F~99`bz=W`1#>CBRW2K zHPqLi!xkSOFWvJpCoQeiut*t)i^?@9Hc=EPTDf4e5t{^G;_+A76 ztWd5XeMATJ<&Pgf`uUT?Ll51EgBVxSX@VBTQU?-^({}E8j7Q9MscqT%baANEA9h~$ zC;RF1tc2Qiwnqw5ixzsG^N!H5MNQSZISdWzUVNW)adzH2JXDaA1H=>(nxYZ;Q<4a= z_j7vsy`Y28fd>{#B0M~*a+@ENz2M&p`&X$Q*Ui+o1B;J4sFg4C=gQJJN;E3oDdUs&v>MHf>RYZDvddWWKjT^h5jV2~0 zAO^y2d#-8C9(sB-K~nZkP6EhxNINo)Y819$AR+zI$ow72Tb=C=BUmQK;M$U)54^@q z9=-Ve`*&Cvav2X8!LUw$nD^bFTW!e=HPzKBs@HAOPvzy=A&DXT*2kx#qXRNL4;L4t z#~2YE&kIYeR9}hYkv#3Vgaoh4Gkj)dW?7cw)d52{x2hMaMpE=I)YQlZ8nHU)<&(BZr^OMxjh)$%zMG%pYe5hXCZo4aBZ*=B} zFIE8&Hk*Isr#nGlVkixxtPZ5pKJgWa~n;RRA*Y0(8wzSM%8LX_?lzi6j z7p<(UsDBm#lFkC$R303RK7cbwxsNL4N~ z3LhU~ykf>nmIXajALNr(=_m*$CZ>sr2?PR+4uT&!85!5@>xi1t;^Mu*^e$)ToRNH; zbBw-Gj%B_dQ^~SSoSdQp+@|Xw(k;J#Z%nN{+G8gn*p3L1PZZISlZ$iu*gTi1!dhwx zaG+E7?r?oLM=AaZ@;-iY@=*+2GLI&UoR1&dVIlwwkxLPnn`^#)EuS&eX8&|?c{wU9 z?BnOpxp{fR{r$G~_IP-BM)8M7Gv~VtZC&3v1O)}%-@U7@s=7QJ-Fh+Ew6M!hrKqXt z)*OI;%VlKf&!5Hl`CkjW0Drf3i%vw+e%8xAdp5U{Xk=)(FHHVj^u?;m?P$?Y_>{am zdwcb6`%DlS8cItH+nh&cmzK6Q-WrhU>biS)9L?EQLJxar!e}f*cST03?(XgaTE_8O zQFLY3rKSBI8%u)#-{^zp?CdNg)EvQ*Amm2R!Qryd8Y0hxd}f%MTCmNo&HaeoE&7(8 zi_0;8{iprq9#UdrX!G`VSAnSR{{DWAUccFo_>@1Ur(SQ*h7#i9(v(N;DflqE+>WO4 z^YN(<55Kv%GCnEzeDLp$Ut3?LGlu+peX+2x#xVdefMZa7Za*Grk!sZE47+s#VgO@m zWtrQir2wW@QBhG-S^0VW{`c53-{4?5Ny!Cp2A8cVwHGg--g>&aXjoYOdpllPMa6Mb z>%N6o#(-H-(Q&I?RMfX`QJu2avN6tGV$xIXE$TIzKMiffekmBQ82D!#8y)p!4;ms`o+;vV%>?2D z#9a8A-2UXyki*)bF*})sr6teqT+y+=7%kP^(cq6C9i5$@Jb6;gRsET&f3hMS4-<_- zC|=RV!ovSICMG5}`mg3d!epZ4`y`$1?Pk-}Wnk$3XQNYb(y3^O^?#y3_L3;bTW(R& z{9pn%B)=y7NP~35o)VUn`;zbl08EI^s&QFzJS9kY$Jk!I6z|Pb+Z#I1jhQtSM zmE7Rq;IPsi)6>?5Tm>1}pOTUiH+TuKBq^GHZEcO5L-%!s^<9KMr0AW-S;oN< z(>`9S3G|qsAA^GpId9w8Y)?#RJ&A{XlaY{oY+C@32J=ZOZ3W;)-hVyufo$2||7ln} z9xfeSa%N^GgUlC*&d5cDURM%zrVb7agvZ2~8yaq|t=)JgVFT4BX~cEsUElkOjm=Bb z4h|NUH`dlyf1A+E&CP*Pd{BN=SHCluZ!Rq4WQs61GD7bt(Y3n|3qRqe#tUl3d&1n0A77?v$jHdJyPto) z!(E?Cj)z&|x@&+H_!ue(ykdJMvZAy!Y2Y<-%{uQZ8*c7bA|kqo#xjfK8#jU?m=t24 zsFM0M)w;dnht2cs;7uMr0YUF)hxw!by%!)}uno$&QLLf7ygWCzG(Ekg-*(`1-y6A9 zsjpzfz(9q8!Pef+4g~VWl@;z7F;!Iz1T6!DFzijhVHttE6pe;@<+cA)?8OUl1*^9< zHcE<$UwnO$Hxa!@kOej;D`)D|I0NJ+54`^R_2t8d4+jSaNpPO(c)l|>Zb_91)vJ}A zE;jC3?unxv5`&}*sisLBm4jne&wDe0$DEj){CiAHOzecp!-u`*Lw~65-UZ!dp{JL~ z7)nh|P2R%9x^egJT^Ny#0Ob0AT~QCp%FDk-MEu*@vNkgV%+aju@9(k*MLzg>x;0$` zh4kpr3p~uBkr5^qmQ(2d?rwQ7b{`Zf9RHWf%72%ab&HK|1WD!R<|@B>1w{z31mrte zZk5QZkXKuK0h$fx0Mr)BjE#+5>$*EXUE=}?2oi~qkWhhco!9`BJ~MS$CX6h>N+*+|+Ei zB1Mc8E9k%`UM)^hLYM8<_Rh}6w=p)jeod)f`XcwxQ`#PiGx0rzvklRmMI%Lxn}SqD*nPmQUz3hi5oaLu`w|>vHc(+ z{rdF_4>L6<2ejnAi_0?F_rwk(7vnriN=iygV}zc0_|Q>bKk37V-{;4wu0mJ93+OrHCr#t z&!1UQfjoJbvA?$b;^Iwt+7(;V{|;w|mKrbCKgX)wSUyG@sq((Hx4$pT_!SPn{eAw% z!QmmK`ArR8PT`|@@U4spB+`2RhsQCfQN=g$fW&iH?8a{L)`AVmB^^On-)lUu3E9PzYZ=*VNJRZ23frj7#QFRnVAHGBOatk;|YA&^Mo*oymk!2L%W3 z?(a*YNS>UYs;a0YSt@9-i;9YRLk!4#zX z%4?q+HOJTsCoSEWHtz`shs}!@k9@=$4T{2;6FzM=sCpZYhZq!2WX3l(uHkjg3h`cEPhpM%0i?K~_h} zGd;SEr>Qv(3ATte*_P}!ULOdg^>lTe*(r=tYVq~IykAaw~c8Zgt$G1SoTyBtLM6T_orN(>aavLE=O9b^ZIyQD9EQ8TZ zAO!RO;ll^8B7Ok@PY(~!lK^8Ab2Br3uM2c{i962AeWL)(Sy_F4$VHf{Q4m#CRm$vj z;KK%-(V8W#lWG2(j~>na{afk6!Ann%TAT&Cdj(~uUdb0d8xC@Q<4l+H_UDrmEEALE zqoX5WJO+%9QuCkzc=-5t@5Y0l_j#=^wB>*P{FzxP!N}NHyaV|;2>}@Q15UM&O49xhYlkT zad;^ar}aPIbd$>+T-qHtk*f`**C=d?W}nu>v+-WuG1tR0Q%z9qN5u|K#4i7+FT>lbJfo{fpCmsI{Ym12t7u z6a)_skMrgP3mx4fPEI0H(#!dlVDq7$cfp$=n>Oix`&Jtg8p^@SDuH~Q)fpnhEmG2Z zM97OYeTkym>+3TWedoRLH7qPFt*z4e`T2VL`Pd*do~k{r&yFd{KP+_ASKou-ru&AizjSb7UZ|$!xX5YQT4Y)xi{O)&u zKj*!BE#2K4{mIQbI@gR;j4d-vW`TuBic|+}KbPUqe6g2@42398}I5G0E5J3U|H6DXcU|2pmK04wB2wPn>TMcVU zvKcSNC|sLLmX?q#=;-J`LAbiPK@br2$TZzvS{q{K;^Klx;X{z6g7d9lxUCH`{ysbrwz6RVZpcm#rv zPd!r_xLZqWeY(c}h}ZiN^&hazl^FmPlwePHcakK?`#rg+gQFwe1~1QOBM<^-=kmO~ z2RYI@o)k4=CMIf6pZb@Tkve`9qfH`m-LSQ@v-)qD;Qil03&q97C@3f}pW)$rSt_iI zw%1-B-rk~Vb-O!br=xla=)aPRiXOS!KZ0Vpckf;%ZsyFuzza1sUXd#lA29?XtYfh) zlqN1ZT5RvejT@JjmjJFl6H{dtF6!#v;WwF?nR9wNBA)(Kh-;l$-bVSa_atG=SROt+ zIu`YnPEC$2FXu&wy?psKI2bo=>HT|;xbZ{g=J%+RZ#bii&;e|cO2B)8=qyI~Vc1S5 z%5tFjzJ2@lp5DsH)D#y7=jzf0fpd6gpBU4xsG@?9fIv|}p{%%=^}cIr_7hcARnjMM z@$r65`lzVAMSaWO*gKtfF_#IK2GhH6$=Esh`1H=Mfha&ENy*5B-S)oe6zBX~I8pF? z`4=2~BXDoe9>N9=0m07!Gq4teVR!{KwJ&!FY}l!&MzC>kT3ct(5Vh|PKM5xgBi>6S ze~XOtw2o^)*;yn&+h-n}n3(wU$8lq90LY=ZGeJ1v{AhDwak19@xVOKbNbYuU3n~H! z7q{(gNFq&_5m)f1Pi@4&dz5ac$Q9$#(k9sPiFf{yW)SSeOkC z2x#3HF9Bcv8Xv!Z`K9vOL;ib}{~nSBw5U|@36eX%`!ck%-NJ@R^mD8Z9> zYGV6=KYvI%*V?}n6@^2P_wo|Ax5vpLe)%TQ-+yk`H8a3-9Sad18{2PInxkG&yxji= zl}6MHkAUFnWY?Pv;?gNhb!%&De{x-&Ff;QCgu;h9)qjSD&=9L@Ylp|8Twbk|AK`qt zV!Gjb`C4V4giFf+jmgQ?fok;iX^m2bMn_%N|Cl=+t|eOTt79chz41bTS$W<&%zMLm z8}@Je+mI|TFE2Scd1PcnnV-QqEj``I$!XWsL$)1bM5W$rfL>6rW~J{{UF}g+RMgM( zbpL>W|8CryUs!m?_!Xq0sK`!5<3>zyes0G!nTWH8PQeuz`Sc;_%+_}SHWoZd0 zuk-5FP=9~ew{Kv0z=I3(#c1m-|1G!{)M50_ZL_RUqu#(jJu;G%q9?tefDpL|2?BxR z|BHI{oB#hz0yesDax$HJT~X2Q(dJ}~{4zwTo}LG4xrL?0#ne=cx9>dgn=s-+36W+X z4niuffY{mT-7DX&9aj%?^KoB{cY2;;oDIS)EiK1eEm_&wUrNM}oswT>t*xzr&wT&> zJ@Ldu=j9+b9IDbMCr8K9ii*DIM+*%hyXPpzQ+ZigYunq*;j*!@vAM5EaF+gLy$T8n zauupiPTuW_;{!qC7khES8p*{96qEt*^t-sB35-A09h9d-vdhmAJV0QQZ98 z+}ykb+kJV>QnQ;iEx6?5qhId@pPsmOb#>)rXJcYwg5%cJ)qw>;+J)IBBO!5ga#B@O z>y1u^JaplCg)tkux96h4PS#|^CGtSf_rFEXwP$AB8_o*#>&gD-nFbhF$c>v5Wf7Mu zknxKQ+k&L%DMIqIvSN6xVjCK0XlP~&$+Wb!H#aswHW=uCwQUE>GX6|Ut95(zQ6d@n z9zEDXd+A>yIF!D`jIEhE+~R&(BJBT~qkaeI8|>RmxFrQ4qz`ubi&lI7U!5t${g41He zbqBAtkojIj$A^*8Fa%^Y9U#!;2F*GMk&MIwg9l;5xHX6zV{8(f$Ls#`Ob&}R*yo-| z*}DIK;QVJ;!-JHRl)b$@5Pm=o!vdPyjWv~(Z_VV74-S6obHWf25Lg5TU~;^!Y`oHj zgaLNj-rF0{{izM93;g`iQuJ03LoZ0^{r#UNB)Eecn~u*U518G&c~e(+2IBdfw-FHT zd*UjhV`A<;aU=?oiu(S&K;sRxFF-0cCugB?*9f4GxrIf8$7yFrM^#FS#Ov3eoi-s% ztvOP3`BEZ3)@Wm6;fhZrq=AZYX99>D9`{J+>HW?+S$Q^>=mk&*-Q(QeRD-StH-=Ej}|eG&~}ItEkuu zgawWm^3D5rOUK!nmm*|&eqMq;9HId+F){2K4Gj&z61pYq1v)voDRiNi7xlki5ZTkx z(ts!k&(~6vGoAj8=v3KPrKc}N9Ao?sBzoV6NaA^Rz=B9BC@3f?LEaATX&w=Kh8nbp zT<(#1@&;k(eRlS#no*0vv}X%)CdS6(WMu1W3XX}G{t}OFf4)3F1{6j?WU8V+}zuc3$u2fda^HfTTfu25Ksnyr#^zuFPu_yshR!cBBKK{)L>uKb2 zEemZ*`b8Ij#vjP`5bv|Ivqwgv(&fH;6=#74H8zSlIP8O8aXft3)W+A**B2_!6w2zc z)VTyBv-Xc8`Y*p}Pwdj_>e%RLg~ez-)HWp_Jq!uQYwYE@xq+b}NUaKripUlJ`H>$4 z$&Prhm~no3Dkvyer2V9%xv!6dnVFo}ez&6Z%X^F+O$WV>$DaAgO+nVgu2mJjgvKL!5YU+ELIn_tX&l`(dlrLnj|PD|9R zTC~vE*5)$*dl%eGO+{sFY;4f16i9?F(e=iSprH&Ua`Nv}^`3AnZIkW=QBh0?S^7bmX{5~driZx)vJYE61MSq(igk8&zKv%B zc6k53*>HB`#YJL&kyu)W>CWDsZjCcO4yFC>{8N1VkoNXC0s;aM@Qtr`@7_g6eG{#B z!rWv~q^S4>l<4sA@WqQ4kf8pJK@!y}@4LAP;Nk|K zA8)%jdr|RLjgE|bm1P7<+!27GTY(A!2{rofeNn5i!kdAVwszwvo8Lgwg$-LpB`I#- z#wH-pt)G(6(#lRxA8u(m{M&>^$!GoJk))}uEhjDQ-(V5u+tGTrUG1+I?n9p4+1WWf zTv}PFC@fS~S9fuAMBd^dfc)SV1~^#`jzpdM+6x`GQ$efEI}FUnZ*1-D-&$CRqo4*h zwYBlpqfE)_*1g+YTf0L=#RwDf<_#SkUD4af_>7E*{nQB&d+;L_$Jxae0|UWll{^4R~1i z{M|bWg#PK?68r^1)@RGNYlFrlIO$1A?^XT8X#f2A14$?FS$0kioD#UFg2#_Lch>MQ zCB?;2-m1yStc(>IIzI6<`p^J84x?9QahKNL%gf8Bu&}W5MD(Tw-E7pG@ACbjH!zn+ zF_3)$6JDgj&PGCm5K~hlLvY&6yavEh;7!8A^!4?Hb`6`T&dJHCtBW@#G&HY54Q_!n zB^l)pIie>{f}5M0g{9+7yuH1B?+<}nfz2VYzpPYvkSpri8yk~4wu22pe@oHRHQy%N z+}vF0!$RKjU>uy4pAV9$8CTsrWz}xPh2tOl7+0;b`C_>-;(WXNI&kFQ8@+0n=Ulx8 z5&HRe@7_I$=wN4Kb8&E}sHkwUw?8xTb6Dw(<9bTR!g2$-E{?G4&R?K12)xgkB5vKf zMM+6Xc=ri^_ClhMkC(T%x0Tg&<^%4SZm9Vq3i!T@OGQ{%*ztA_3IduWJUralIVbAD z`KWZne~;`~5B*dCw#a=hDJhBSqpYosJAGbiJ~U=X^D`skftC?}_9O{jH|K3UX;)V% zZ|`fuwYr9e>*1VHJr99ghifYcSb#Fqm3D?ME=op=J&|lyngfP_8OA0i_n4VQUBenX zI@UJpMjIRT)4X~4_>NmcC|CLt`?3W*&m8USc7OTfYCfJUw~80__HuPSfvoN5XtKCy zR3d?k*WA4H-56N z&eM!%qPf{~rq*pk=}R1+O^Wglx$h6(Y|H9-`xF!?si>$ZC_KjW6L4ImwdktI%Brfr zY6c`>PxXr4R)Y9pZN1gl`2OR^_G05M>BrRy3JO+l-x}OqUtcfA;zvU;GBN^b7DF50 z)8WrBudS|T0za6U^$!ll3OFqDe;pnk=ChvCC^ou5(uSX^E%CP+_9(|8mDfi6qsEzDD9=KX_ep|3z%>#M7PKWKloiAtygRJ}w#+^*l3b`9x~O zWlkS*ed9)PgZB+w-1sM|q*^HYoVO*L{gEFTX0-nA-xvdhor422qmVv12#B#lB?2KL zQV%VmE$ou%dF&l?9bbs9j#LSFAxB~xEC z|B_J8(;A;C^K{Q>dI^P+7!7i zp=qBoclwB(bUwOw**EI&v4$F z8XiA=0a;Z-!Z$E*Wp%)?+2c~g;{sPpM;f% z=bP&I&`@4l8qfMKGFDR3?Zu@f=K8PcL*{@JW<2kfIwMo-SMb?XSX)L$TA`>f%eI$$ z+5t+72=3sWO_W(QiQY-N$^x<1(A1o+_p~sI8y?;cmo*X-LpYk5n+q6sk{peqqN3Os z80_sCw`NKrpF4+PKt8|s_dzq8OEe9FI7rBDzVh>Dp3?DiPug%BO>y7ylexE z=46G<_lO8Vx4qv|d(CM-e~P$<6*{gFAB~Ei71HEQw(@X z2w%z~qR!w2ZO_o9la+hpaXC5r^$PV5+U4H9eO07kssA^l1h)|4Bj+q7SWRl`zHrHm zt%E~cTpXCp1@HK6ucw^1KO>(9c>e4e3m#_kU?KFA}h<(Jcajp!VpE45nC5q0DkDI?Kni?Bp1ZWU0KIo2lavLvTX+<20 zrK-x!^=f*9@xVR23E|f7iA$N7A zk_ryNQ{<9SJz#dRQCBh zoN=yz53g_M;JUc*A>O}#FQ%+aL@=t9{xT)Sy0g6<`^JsBcZc?A9>@ow5Wy|w6``hb z&HDW=8)J4GV?{6eq9P-$C(H3KZuuTCs0eVr-{0SNfY83P!|$~I=PxZvwqAv`j>;c} z)os9Oat>W1lX~j$<*Unc6y)j+w~7vZowhhRIYqw~7IJcPzp}9S_oA;i_A#5lX-r6n z6Zql9#YH%3YinyqM<3b4*RETy#XK(qUr@U3|0F`_+t{qk7yBh9(sZ^iZPt;8w$TW= znxzTxR4K*rhAdG&V!dp29R}M;`QY0YytShg9rH8KX}XsAw$DVxG#5` za})?ey(libXOJKe#GjD&0%YjbI4h{AID!ly-b4POq>O`{W7_u>_BlSQu5oaDtTZ)< zmoW84U%#I3zg3xYva&##6c(huEi5l1uU#PT+u^21^&ui70|~QrcX!v*+m=PiWI()+ zj^?ikodJ`Cs22R`lXNE}7Bocbpr>SMdAW#p0>#anB3}}@2?;~t8^y);+S-&kUqNU? zq*DjXGA{x1Dl7SE5T$@U&yM91{BF#Lm# zIwuplw4bDW{}zw^i593!)3ZY_-igV{h=_<#DuKOcZC!V`O=M+1hVCOYO54M}e|O1U z(|Gxk7}2PI(Z`;Zl0whI^5|`xvIZk-1rn^8D8FU2$u`YOg&v)H6ZBF?7qLC z6n(@hU3XK8i$5hLg?;JmzQwFKzv~)hYiKwW!);nyd-TqA!_j#r?Cai-!vzmGz*+A^ z&0D3nH&TGR{m z)8cCljp(qj_N$+yWMtMxM!#cg0Nf&f{P^`mE?F5B&5ze=;`d-!m~2{S=X1484nsr3 zSFa#aCaS5cm*i*X<=v&Cny7OhZJ&Enq~Ydv`a))AcGi1u@!6|aukMdBAoKxK>F9QM z7nl+6328(i2^NzqIX<}rJ>cRR=(rSXb}H#Vkg)D;!2x26Q1JmD_X z@M0v+f|x6??BwDiASjq9=t36wFJmCHK(|ii#fvJtg(vf?B@y!J#C>hFYX(0#W?;`D~*mG18Zoba8@6cad0S^pQm57H8a~O zXmExA+!rq>BPWL&+(J);&CD!wKU-Q!slvynDNlPqYMv;fqrIzZcwnH)_0fk8qrbao z`^!C(rRKLHIzE1`P0q^FR8{R*_gBm?HZ_G4Ai!mjOn-T_eT+{)kTQ^Y>pJs|MNEPA zs-u?4vIT%JDQTpprF{Gor`FGR`WrBdr7OzIy{<0Y-o2|14ebNqOtukJ!NbF2Qiv^e z-kj*}?uO}l=k7jRd#B@yR6$lYEHbjJxY%GA&a)w`o;Vzwy%_n{zq9}}g8g5aA8cYobnv?$eg5zP zy@q8NAR#R+?b9b5_?bNIib4%bgLzRO6bed8pb7E^TEDM`3?d=Jf}t%fElC6#8>e$| zaUC5UrGELOnBnHOIbJp7ry3D;^y}9zdQs8P{|4ZAt3@KVt-D(u({F2KB_k`VqnOT+ z>rQ=rJ&4@)tUBxo2NxGioGa$@#YHVprCybN%)OC;f%^YGp^uQEt$$|bXG%)<*3M-I zs?wHTMQKF^2X*0rH)snO1EkGz~5HgaFH@dN@Dg= zrlVu2q@p~7owIX*5f1JwGFC@gjOHuIx;An-8*xB_>H5wQ=oPvFWpa_Z*FCU5D_it@+GL_no;(xr6mXf-{R}QCjE`gO<+z!D*lgc3&<7VJNMUy zGD>WOW1^$cvGimW6=NP5V&eGI69?5eZ$^FpKKkbmW5hE*KfhN$j zX?e`FoS%|1|MxF#kQ7A}U*uCr3*#j#FpnCKU%!6c)FiIVB;@7gB`4RVUZAU2X$zE* z4%7kj0?uAHYuptT@Zp1zv2jk066MIrWW}|VHGR13N-sub9`ot+&E%Nn<7 zue8*M(95P~56RyxEy2MukCflYC@B>r>67HhkVXBsEnu6yeOvE-Y^{;*>nkBE+m7A_ z>C6HYQA=xLc9sz1HqotH?t6>7C+dK>jLf3vMhpC}ugk5p0el089c*niw6s121xc>; zf%c8N+}zvSgHnPtA{f4N`5xy-4-iQW z4Grbxn0u}Hd3nfB%)ayMSHEp?Y%GO)NLUyrLhRM6oYd6R^z?fS42EgzcRDSKj5-XU zWI%T}#utVM2Z>2ZVSL;cKVG-Ya zB&4LI6gFqse>yC8zZtc(x3>qJ2XAq^y6`^w9uN>P*2V%GJ^k01m>YSYlav`-T3TF% zW~Qd_zE(M`?n^%Um6_4Vp%5o!T@ z^t}X)x(N}e@PdY`l%ciOR_X28h6cBNCW1i2yq@&5G>DSx|NcP(g|%ytl9JxK6;Z_g zG4k8D3hU{?(b4bUzqhruW#s0jWn}Q#Ka-#(g5cQZ9iN+(Wo2O@=(5F*<4;UPq|xBz zX=3s-F;SF{@3=dL8?x;~ooXqj2#8P^h_PbhU>_fGaq*@E;e=pv4hXYGT;qLxqO^af z(w;?tV)rEo0}+0Zpo3S%F)sBXA|a8YC312~T{-phc_X8#dHS~r4YHD?bBK40gMly4h8o(a=iEbkF&8tv}D?Lu11GJhf|C9UvP!+lMY<{iNzYz^; zF%THQ$pXEGC+4rF&(AmR`uy$Nx1qto zOqJNAq`xUogXvI!@nC0=4pRoqC_2=7qQ97R|?y|&EgADhc@GX`0&A_shi+$$0c)GP0e}EiLHr= z$pgLmAHsY*IR08?Z&h`5t<^`{K7DclN|;|*Sm};I!)SCrScNFo79Ss9q>)=vG895N z3d{|IuBM~IUA(*V-=+}9i-V2r>RK82;e&EkX$U1Bh=bP%ZD2rvfq?<&zXpp<<26>- z!v~&|!-qxX<*mKF`2fVfexYhr5i*E~Bm@S6h2kN?qE8BIYhMGR#>HvBcmYyjVD!gz zgaI9MIf9l58x75`Z=&_$lYWtgaNTKQ6eSw6)1!IJk@tf_nT(ZunX~1mqoac;9#ny5 z9G}2#$}49G`LeHbpasguZO@1)qRJcj;X@nXFX$K;C86+ky-QD{Xjtk)yv9eNlGyTj-?h?Cjh) z{~wY3{QQL)8;czgZmzDcb*4cNg@lD=SU*AnfQ-B}H%DL|mHEeeKMWA%Mb;l*U%uQ} z(8z>@gd!o#H~L=Oz~V~iMw7srF*PpRTN7o$z+Cc7@XJqSWK2~=D_*Q^Z#N(xXnq8B9ynC5Z5|7g5;UzY%i6c_yd~L&ehlJGNc;!_V(Vr zyD86CxRG+*pmAFdDc@{WW}FbWF`^B&C{tPKqhXXsSflllcs6d9g#<{ZJn zR#gog9XU70IypJbEiM9ku(7bbP*W3e-pKspbtnt6a z@nc23Maap?ar{9lVuduLjek6(r6r=Fxjrx-1pZ?t4njpm1uYyLju%*0h>3||Wo2bz zWUQ{-c>gvf)#jO;TqspW>cTrjBls@NyRnfGD0F688c(*`%IW@!t5DO(NI>079UWmV zuDy{wZP19jcjJ?jlg)TyosIw+LD&-Uma)+G-QVkTH84`Vg@osL@W5uf?!Q}5Xylo= zd3ky1=pND2dyL&$3O?PLLnC9OWn|>vQ!zGHwXq3}j;{Rrl|F|{Sojjyxu~cpH&ZF` zceA0X?aoR%V}Q@8+j~BhH}wM8=)b@`H8f5j#w{$qzh;Mw%C+A8e~phJAb9qw<;#!T zZRY3Yy}MstUPQ#?<4jq$XW(@}`-Fkr9AMT>N|pVc_n=@0upOWqZT9-bi<;-_fSFO@ z!xO&Gb00i?`t{Q%V0rla+{M^?`|I-)6M;>}ubF`oGwyfj-w(*m&zH_*3_;?9s*3R$w^83eq|&i)X9m6ii+#S{8;SH z$o#pr=HU}Q&|ZSi#>}9FcR+dP2Pb9O*w~(#v&*3&FbLwYF<%%3_#%N>gTe~ zDWM4fP)h>@6aWAK2mq8a{X&4^;+aSu004ke001Na8~|r=6#-}O<5-}O;-cnbgl1ONa400aO4006aIZFAem zk^YWfG0Rk9DdCH~o2$FCC0%JHd990Vt86)YTd9-^B!(nn5MVHXXzo@1`}Nb^GZ>JR z;%qKkYg;0L!SwsnFN2eBF5h3={d9X}-rT*tF}I(-zq!6JgVAJieRcPGGP%6F_47n}J!@c78g@tjiZAe?Fc$H{ctZ zyeaJ24{KY`o2n|Dd1KSHxv}YIbFs9u&$d39$Ti8yL>`lzeE;TYQCQPdCbNy55h-?6)mu{#N9f)%x%l1h%(|`?b-Hq6 zWA2u=rW@%`LtM6Ioz{)R?X9Ejn7nyuAQSwIrxy9NPU~%wmvl*5nsmJ`@>$yCRXH?u zTbBO9S(Vu#U6IkBwAlXaKd;(m-8N$(i3I=R>_(T*OTOSno0Cs7r zxoKvrv?!|C(6|bl&PhG!gTSC9+=KmYtF|`wi=DMiIxVohEHfwA>Dj38OPx&k1FS}? zBp`m&F>xwOuUZBpA=wIZo!v?gtz zR#{>DtxFfQjl6kABvsDkQxP5ZrR*S4&1u=1WSbCwWh){Z+4;@o{q2XVoA>9Jy7QOJ z+mm%|&wg!e`Cz&$P6w0L)e{mT{&8v5mDL^mZniiXM>sZ^8 z$AltkXJoI+@XS8gqFVDd@ElrvgU4-zol|foK)Y^Z+xTMJwr$(CZQIGjwrx&qO>Adk zJ2~^8o4sq-K6Nhox-Yt_tKV8rug5l7Emvw@K7L0Px2uEPZej}C%C9qQec4<*>k|5c z$*)T;#}3Cao1V!0#7%9;+vu^A5;;ZWG78*2cz`adN4iHp*rqC(1W9_AnXc0gu=fd;&Qf#wn`q9L6Po4Tc(cp3h!z{lj!a*>YH?vk%Qb=7!4R!ow zH1DDMpAq9+~Qz4fI*b1n2|{d%mNuSf%l_X~T=!kHXdyd1RBtsD;c*vf$%JU$&k&tUuH zebSPxt~?|kWDX74T+=>z8JQ+2=VEBawH3v<;s)e~-(AFM=3f*%%zqvk(BgA+<2(;> zpqv$t5Zw*k^PfQsRqL&7bTE;4RPOEEuk^FDH@#wyd`?h$Y}2MZhI|1(5R*hG1UQoa@-JzlB3wKlqaq zKbvSz*`ic6RB@4pk*8dcQav{PMbzcLWxPZXBy^DsIw!JA*B@mIPM;0_QmYlNT}{tN zXQZo&soo_1W(6CvXV}rz`xFwPU9&q9*nh7FYK7X_CpfbkQ)}yRiJ#FbEezA6@p>pU z2<^MPz9onrm3$;A!$e(-oUry`NIJ^1b(cdKzZSaxl3zytck%1#!iVOhqs>tzfBl|v zso={D3^)Lj6N9VN0+$RX{n_|#ow3Pw1Gyj$1Z(8G8Gu3Mzxq7MIkMnT`@-IvSqYtt zrYp*LeJz6&EPzzmnEL+9*d%df;)wBPP3Vw}ZkI|Ih;I+1-{pC$cj~ToP#^PHScMll z+vh$u2Pcn(iiM=lZS#P%qT} zqG=rWBfp$=P|@9Yk{9tPd==8!sh-u-)D^FaD#}PF8{~9UWU*^_Gmvl#tLYe0C{fBK z`XXkK5SoHLwwkPArFrnFqo4k{CO>J3HW)CRa+%I#mVY)5UHeq zHgiR4s--rjDKy+H6@F=Gn_P07eJ=rh8oj%Z91(KOjFQ0+!{BRp0|qtA+>v2r~(#|i@YcVFeceOsB{yw8HLV9O75|vQyziW z6<1S{t+x@fVps_7UXUKezrr%wmDga`%93)W0wh|AP_u1vK06+Hd?^AEPU!-Oq#^|2 zGY(?g*=`p~k2$D~CPH!YRQ5%-9Cq)KaqcIRAk&@G;Vgk`=GI{!w!pJl{N|jXuf0oe zq2z`eFAqm`5Cm(UCNg@-2CsXkx)d-ker@?PY`J!lw+UI5jPAR;J_{s_QWRz6TG>8r z%+v;WKeBKDR+~i0;IAq#5ox(~Z%Ll|B*JTHf@M1vX{2{=;S1NlqC@wV@nJ`>Y`6)i z!iI+JWlFW%an_Z%$Jd6g#x;v#i}7T-wMqm3>Fx~sKPKBqc; zz&nN3CJNfMTte76e)QFqo=VG3?u#VOXcaWaXab`r1LokQ&BaP!l~W%d5EkF%k%O`5 zHg$bYP{T_RmkgbgLNNKS)IhqP1bhv~K3q?N)16)(-_Oy4)8X`m43HKc?@O~NOyO61 za8jAYY{`5^MObcRt1LmitVvH4@~4YgwsTGe%*-))jJ`nsA+LGLwmgCnEjh_iNQhNy<|~ z>yjD3uW4Z~D8@Ia=6%bjgbJxFR}+1sIMK!sMNR91nWqKX-Yfavl z$8)BFsYA?I)yddNg7V3Y9Cw*mvKm(3-ztCjr-T!gIuRdz+|H#au?Q*OEcTfIZq;<1 z?Icp1!6j{T)>Dk(EI*=bCP6DjL!RwEa> zsI-ac>jf4&HG@y_r>%3GsRc`|5R zA&e{OzgfD>DGg!}mx!F@KzKQcj;XHzf8{Zbqw+41 z0f||Uh@9y-OinQ6(j$q!@=w@v7(~7u@B8nE+kYZH665~8o^^BkKU^=sT|_f)GY zJH-PU{HjZ1aaD)QgFk5r z8WQaTTUPtqcXxwb#r0hJDw54qXg^7YsGTy;k}NtLB^?`Ql_$x#%u=~FrX=JFz*Af@P5JznBbw68rx#@$6#SpJ$=nF2qC{q zLkpS@%Ua%r>ZGLqijMctb@m*#@QK6BTFxp_bG5tCp)cu@;KNXfxDB&N|EA>@d2iW8 zo2eE%^Ob-9`;{&BAnm~^;cY3?gUMZH;}Bf91oK~^*U(si^DxTo$SP+tZ7Liv*+ zV_d{36HneIzHvaRzu*?6I(d>^+af>~%YsOz5D{&44cQR;!TR#*H#y|z zk{6%Rn&=xng1xY6$p%bdkM zj5BU@#nyZkW`8<-M$B-_o&y>ogvChe4LLTsVW#7~-X>@_Qxd#R>C0lPJ0j!FMh0T; z3i>R^^+N<@b519SqJwkkg~FT{|B&Dgz5Dw3SZ1G=8sR;J6B=|5Lf+1c!O`sX)4^X% zZStYXhQ_Ti^lTxNi55vHNNb@A76`*^4+o~u@koK*u?7@=+eAc-VZW?ggo|E$PWes5 z39Le6L||tQ*V_!if5qNRB&f!4i2N(IP7x)oM_8#?1p4H=eVFY zylF@emwQ?d7FeIpezEDw)gCH{9vmpta1|$eeZL`>-7QN?9^AKV>eyO6Y`unTQ)x#U zYqhHWX2HqdT51!Drl_{IqiA;90!dq^!(N=vYF}~qh^BVw86!h?eldwzFEkM?U z!nEtp{h0hIEw$HlY3WcHMsg9I(r9WCq!y=$PF<^oc7Wz!R3e+otj23BaMV-}UDpvg zGHG#7vVC2ksW#;CRqm+4B$+YCPNwO>2B>t0VW@#@{?)r|jOSI5DvH34O}Q%mdXBH) zS^M@>g=WdtqBJH`WOZkYKz!dKBTufnfhCpp6BCoY!)ZT+ zo?M(b8u?_FHQk|AX8ICR_zjr=S3sQa@%`V!?Fa=-j~fAB)e-*8`9I!ErMcyH3q5GH zk^M%HZzLADZZ;8mc;%O2>b1OJuIDjlyumAKZ{XXg)uUaM0tp&oMsxK^u6)b=*^cl` z)a7dU_6myr`bX0~Vu5`{0@2j(Xqt(h@m{a+ri;5zs}GOw5&t&R-QGJFAiPNpJTZ_yl@E}R6w|oKFLE9#Lw|AVMSmDCeQmBJtDTmjdQRT(FHmy0uWwyxKmBo0 zc>ju^sD0c#^|2Mt(JD2#SL;9LNl#nhD!_8AmvYlhYHuFD$I-$-8g~ryOuDcg! z5EHIYNd?4o0?$?YTx+`@kC}{jw8W@RqPD)RucS>&+_J>gXHOQNpo{JCDe;lf$oe_I zMPUYGKDAt_kN=Deb@ugmdw6`km-jOi{`O~G8yZSaw^;4i$S`AjBfjvJhL}v$t1Oj# zABTPYXxafJAqY0q_&3UQ7Xvv3e0;y-pKpic4lrlh5Y$Fb zVw!l)fiol3sMTsixGFoN_y94hGEK2~k7)?qV2G107WDWaAbN9k74cGk<1lx#!z-4K zkbIZbcnB3@R2A4%rhoMTX$16!Ik|tow7K~)b%Ce>L?po1IwRGrO)y00#_GSk6D>|~qKc7+Q znTZ4k@nJAwBe<~h85xm40nJ&qvOw0aTSA>TbA$*n&;|&~T_LaJbIrIHfhKRjY*Zrf8WzrW(4r z<{jGbbD^tJkt-XQrr3q@haxmxvy_^E`&02mAqK?zF$DhiI*sYa;t1=uRZ#>#tT(;S z65>!i`oj7f|Ktv}sst`>^tU!kY$FSw3nrP{3?dg;0o^>QU8fQxsWK-n#c`e~txcEHo*{<7kYzRo-N5M74NS zSr@|dH0wzc|8|+gPLx%)CsaN(;*sGh+~`M$LOvsUuTZXuSiN=SQvJIIFFT6c zf+eJE@!7E_M*JIN;$FIKS%{N3bvuw9E=p&Pz@ctZHYQHG>2cG;{F+IAh_y=9iWP~3 zgyy;1$356@3rU#V!@(iys=E1_h_I6AFqG)UHztGQv-3n7A`(5WXBxn^P%q9Fg2Y=1 zI)ueQr~NCH5vKUA1%@DK>G^U8h-B^&*edPQxu~0Z*{@F}Y8_^fz#lvzB%jF*^vBub z2{trX{*1?p)P$9*IRQ-W-_Xv)1c<=*M;)^{q}|xTTty9&Lx;v6v&W+bbwym^8iJb< zea5&jQ=T=%tyWYEklRlYxhRW3xe>bzR*rDOX3hcopvPYD`*mV!&FA6?{!udi%yB-$ zY!pViVR-X31+JyHrH7QKrthuyMa9*6Np5ckm+&K77o(q=e*ldJo(-|UBlUm%o$J-F zCd_@c32iiNGCW^-4?-x2_Qja^W4e|uveur!zp|P9M^<0WSX*P5ko3SFm6z7gm4cT_ zwe)qcZdWwO5It5?cpq)!4bKzc1sgt18>ZZfd21|=b`P-A593AeE4fXnTHyP$I9WeP z4n`*y3VjY1CXo;lbC+qJ6?*+9_x##p16BsbT>YE%c|XtJ^1sOAnIf{rq0oeMlzpS* zc`Jy}s6Erd!K3(KjZ0NcL_8s{33E82gRgXxDV9a?u|sY{fMV%U&b=f%g*O2_ko#SS z{?vT#^C;~dDrm_D>UaQDp99lhv6-bkARfxj*x&LkI2faSPIYPs!d6_`4Pcca@Y8!; zQK5mNTVd@S_~6IxXyFI5V2r~E!2 zropa^@POoT!Bx&=EC2kh!9#RRfaGo|c3OV(7aZ69WR0#q5b@{FzT!O}#3*z{dO-lc zy=|_+&cj_;sOMyvpI0gKHjJMN?_tp24e)aMsHEvCMw{_Bl#>>#P%Q(1Xd(Ik8kx$r zCqP;3Oiuvrj%eB2kGIZatnjKdh&Sbv*nz?!j?cUaj_TeoZt?vy^LkVX{$BD-@q17L zKfBq0kqpVK?RQWP{W*Cp;|8EIbQpj=6dKd|Z3gU5CNu z^$ysf2h-#4CpFQpBL3V6CU3=Fk12eqAhrz+o*EL*$f$Ep& zpW3$1zsZ{GsA_|`M#RCcR$n^JD;l+X?E<~84>a$_%=-$%$do;v-^T)ZQvtr7PBpa- zXiwAHC$aA8=iffwe0)^(n9iCbG5W9RTLi&>5z-41_iFU+rc_sIz~z?-SDV4*XKO}S zVvhE~{p}qieW7OWDjD5#w3FAJxHzGzxa`y@965N79oA|STPAZaa*?m#pX)r=bjs?O z4#tIQbi&nmG7-q~mswniTwp_zzvsmsH-dkM9ppZmraa%LaPl)E zB9MYXb@ld~lL~|+KBnTF&gAMfDv=f5UMC2?W_~v@gRb8PZnK$Fc~1XI;AHH>6Oy!E zUDyQiUv7g^wV-gU=zcgAKNcmtN^K0v>zA7+{}c6V6sABdc?=^iiik=;O6zR!V7?~Q zq=!XBgr`cs`cNhu7APQ%ptWA1)sBON! z2!V1n?rdV&q~$J#fGHa)OLag0a0Wx4+(L7G>?#&`Gi&c{rkdzA7VOf?8oJMz49Vw1 zfW6&3KJLtqn_*RVuh|6&5tTtmFQ>I`p5I+Gn)T3O&nkrmjbL>OnoGCez#(B0Ek@6< zve%$;)1wCiIVfy~it{IATA7n7oTqrwn9KIDxopin7Z^;6UXlhUA_T4;DO#jB^vG}= zpCNLCh(S%fkcBM?_Xc+KahoZ%&U@_E@Z0l^t=LiaKPxLzM3`HBa_+zGH(r=DPDS&ut8?cF-xe>l<$rAmPQZTKZhB2y zGuo%FXaxk+E!;y<=PN27AWbs>9iP6wi|ACL zzO}p-wJVWSw^9Pl43kxMlsJ36LXZu$0>nfKC|6LYOr9xz!_u;^bOfQu1JT5D`F(!h zry7v*8@CYg5S0LrBvf{13i-}Gj^Hc@6-`NfN#zNLJ*=OAytG13rKM|hzx>{jSDeak z-qKqe0{ODn`|O2rU8qqnt7~l=`m5=lSA~azx2fHLm-~^MnX56L2Rg-j%aRO+3>pK> zJw%^+O#I=;r9`U~Xk=_Fs(ppW{mDKkI)m>MLF=mo4`6 z{EU8(V!E+fDFW+}JX6!kY5-n*m9M2;sk@4f4n1qswfL|NwBprl{jLWP;hObCa&z;8 znI6As@;^c6ix~dT@#XLHCkKtwgNzFghmk+^0{y+b=sv|0NB5uqu0^hH{$ie#iMNkl zE$3K)Ih5Cz&!=@-uP(hy;{tcxOV1)(d5Sb?7I4T) z&>gC*p-Yetyi0L9KmuqL<)gIOS4i7}A&m$MuaX4059grhS0BXLaSLTUMbm{>-0D=U z+|&@nmeNao7^SLZ;rFB9zQ=tZA|Mr8+w8A6_udPSrea1Y^(L6bc!B!m{=hU>ZSaCR zSIQC!o0Z|1AeXd>1ay!B=u^~TK9y*z%7Cy0ffd984bcGbP`@0)CmLOilUHhW1cv%O z_dU&Gd>z6=x$?%>IfV+dXLq=nEk|GJR6t71{#NJ@(hV@o-Js-+gIidKz85X7OnSvH zPc$82L9^i=yCI2m1wxv8XK;{I!;;0SvE|v~PIF@GZk$4hE~|Fz1L*BV^{|Wg>4$>s zco%_*2oW7)h)~P%h#ltm4g7cmKK7q7MNBD|J-OUH@}bpsqOUVkdZlc#prOFO?*_)o zHc)qupa1A)2o~O?Kc_*aPwOZmW6a%mg71_~Vy#;Wb}Ct^0W~wH#l3tq<)}>-ET*N2 zNny6xNh_rx$L)jF3(^kX&{dE%2nC@*a)B}R0}Uk^vPt8ls>QKZ<7R3j?E)r5Wz720 zaYan~GuUW9f)yxMXwW)kx2t-ppy9V51M8i-Tcw+-${j-ts@Qn9;J_2{hV{~MRVT$u z3go{H`SfQvqLfyOE(b{lfVWl2q}j62W{O0|fbX{?lsF9!N|!+K_o?n8 zSIYR(Ti9C{9f0rx;epzM6-}=qX$z!yv*#?RDv@*!t5MVmfHd+%{eGg(Ojs~ zZ(XCX0^JHyATtG=50s8)k*C3IeabMpR72`}kfq!b~a63dawI7&>xV z#qd%H>bUNR?t#Yw*I=6zXrM>s27uucVH_V7HSNg-SETHN`HNZiqC0~{xF)AcMJtGv z^9mz^c}h%yfvDVk>v}p3eWN8CD%8S}j>+yjt1u9GvF72tBpa+A8k>mQK}V`+@$rq-C}-oz}z_ ziq)zN?3a!2h+c-^)VF|3E$DZ!&>c^HdR(oB4HP>v9D)@8&Q9$w@1e@^|lF#%+g<#m%~~N|LM% z6XX>9z=rgRCpsG~7(nm+s$(X_`7`}fS8Tm1ZJ_KW8fB#Q_8EO;TfHW5|bItW5-fJlP_ z?HAHb>*2AtWlKA4JvAVLXFaipcBCAatH(JKUI@almDM%9me!}^t4JIaq}&4CW|B=b zCG5x#@4#lc@5DbjNVX}Vl7iKSng^kxCDI8HM){8DUO9$rgV@B2N2UClOsJN^EYji4qWsQ zM7Fo7S_f?#5xsTzqgyQx$d{4$+L)r2*Mo~)mhD`t*DEh`43?+87L zDO?~70u&^9qV%&#(svMOm$w+)n>RxaE%Fds)TG$Bn7ElnySOY&G>;=EgqMk4NUxNs_zGUh`^x`8?LHRVhC>IdU1Sz zM8-(lT%B@0ILM+6*}xS5jymM!$Zi7TdT{@CaQN2$<^BEr*p3?6+;5nA6$#|!bfUqv z>rM*f?we~1Jlt9!M0OlrWwo)91s$ml?k#7m*nY z6s*g$0c%*<9VhRg-`QpukR1&@y9O-0tIz?0Ym@AL!xqH*vn{2w0>j{q|}2Pu*yi$;mC1PQY&5A z0p?f`P{#WCgGz>9+DMH9XUjB?2o0C0;tao(9P?Jk-G&xOXlb<@es}g6Wgji}d7nGE zbcYJsWtI`;kJwQkH4i$EWC1A>4UuhWDiNj!YSb~I(k#Ir{=pU@4&}_7!+F}RwMQGi ze#qQ}jWzmau7aLUV_;?sBOJn|$VeA)>ffoIVbs~_O-8A4K7><3fjXYs80a_bpJt2} zO>ajOe3-be@PX+Bu~#KhI6bQ%6w<#*=w|-IKqMo&qqqZ~s3NVDL<+dTJr2e}lxPl; zV>TPoKZtKYI~8TDDXyuH^LC0KbjdKPnYA zic|;Z2tuqFj>sPAlw$p)3C91xc!k=rBVKXi1d&1N=Qcq5(PET$vzte13J^ET0~PnW z*j+-4DrDN@chBra+Ynj{6jcXx@QaONQ+E^;F)k1Kx9F6`v5vG~dbr`-h&#qoH<)_N zsgrtpfq&|&jpEB826*1tB}?Gi0{?9j^3n#8Yc7xGdUIda(sO=8gN3EvH460Qa#}~@ zjw2wZaEd#9&#eXp}i(D9(M_Tr;T#I+>Hji$vT=+1Pz(e&)VL3Kv%rvGUYab3RUOd z8Z`x@Q4``e)uUMldp1Gun8=wLFqZX3z4-eJ#(J)j_YSZaQzgkwo>c9D)aC)FFf-`! zJD|Gl(JwsIqj67uU#P({2Q;NRUbFxTe-#q>IjqPsXN8?Ytx%B^nw@E62 ztFauaB7YAOa2<24fK!^JjM98j$6isjyae%yI>JF+_ns`}nN${u8neQH{TcB4ZN$Zc zsgYr({@Y8njkI>IfeWfcjLyN=vm8lU9&)&)A|wtXI6j_GvaG`U67eQMBFi}|4fv{;*6x8@{3*AOe7m|)b;=SA0vv#DP)_vJ8#5$VONXF8! zCK{(_`ngfvbQx|ENxT|mr2_JG(u3pR`B4~V@2oo4SUc^S2BY*`Pf%*`)5Sism|1{P zTWMP%e`MFF6|*q5l3f67cg$P6E=t%#aN z?){YxQbd)YGB!-2rxNo!E1;4JR*57s&ZjblT|ik)!{hg(4^Q}0>>y*-I>Lf)xBU(#ANB`>Hc3Dv z{ANo)-?0RfLLkEf(?QogbE%>vW3IHbRd|bk6!ZLcn1OCCs)UrC`rC>FVCu%21W9wX zO&sI2R1yWk(X7HEgfI5*baIu1(!jxJUF5eVjQ;_1j}(YuIJ@x8T>`9^;nq0{Sjwm`C6xs{v)twF$PC_I4LGaVT?Z-a@Pptr~ z#|vw+hcE#yhft(38GbiG=C>?bAorJsULF}?G`H+RF!91ejXlH>L;>R@!pv&bE}UNu z?OW|m6b?5u7vb`K?y>0YY-d|-&gFf*px%^d>~(`3?NfhN1Ialz1B;QUJm`SpkO;kG z{`yqjZss#SW)VJuY|~rgt^K8DB0$(isQ13Iy#;hi>+Pujv5fdu)H;}2j;Z(sau1cK zc8#%UqnxzCGJT$vzwT6)Ps0;doPbul8RH9#WC=?J@2G}%$qyXNI-CGT$d@udjW{e z;=L?b#&WO-EF#Z%GuxQ#)?z2goe31`3588u4a^ z-ZL(T4Bv!)xDnyhx>8rm>w=Vs>Je%V9X`0G0UEt3n<~v3@5M>6$ZlTLD9C<%3z8qh zvb~XDa#|2`I<#ykkAx3{Ww5oJaMcSo#~~*|K?9}QxoR+4*4lT1`Qi>!YAfidGt};4 zP9iRJ6SM9dO_l=0Rf>&9qv^YFcO&U!wA4>?|0UN9`(NHaG?^l&bcxC{oV>DCx}6LZ z;Z=uYU6AaRj2|u!SH$*r&h4=ZSi!C2Ah?4lBjN3Dzn%dq*Z2BZ1oCiPGMvx0g%#!dK~{#!bFC|l;A>kB4Q+t*!4otbDPaD)%9y(>`Xx}GGF{af-~O6Q2S-+I~|75dG^-JD)J8_ruaD5=F>Up z?2yQ99OqvS9I{v{EQ@HF#})mGI(FmfKzzg^_#Y~39$8*I#tzypcDU!e{eGkj_Zft& zNXPKtQ9bt7)!ekniwXt=z(^6>P|?J1pjg_2S}>}i??(C*9?f00C|aS>)-qiK-l8M$ zs|Y8Fx*8bVheLa(F$Z3Yrdm+R$eFg(-1y=#`a)$Kbx12LVxCr6%W=# zD)NpZB1xD=KbeImFvk9|Uw2TwE~|ocBLSWag7oNTlcAUVN0XwI_=vFEW6D^Rgjd= zK;0=k*(u$Y2jXC$R?qF-^N0l1A>RX?iLpGm)&=W80|`kVpq0W8R&g_ocYQyCPA-p8 zk*g%aaw-dFK(n@cA(Us0_xhlrvZmtx>OGinY*5iP_pbVuy=!(K-M zgP;N!zK4O{)d3(kTmA8lpbN7d4>9x;{t-r9gF6-_ghLqt#soJjgl50v#Ngz@`b{O` zh?o*4wW@Bp--oJJgRzlAJ~?B9Tm~b&#S`s07Sl`$r{gSWMYIV)OF!FMJfw`QdxMOE zEPvJxCC_Ok!CjN(#j883GmZH;T_Z#~W`{i(P7MKZHogK`L+SQw_Y0%R+3O0)De~8c z81A(AdNoq8@5W3$2^WvHs`3|3y%s1r2U|)|0y$_J4@7yd6_imRRlQcGQTugm+4PHN z2SbH1#?}Nth6kc42w(2+zsPqO;hvr3g-gqsOT1_aO4tF&N@@0FQ)K0Trx1|yb-4&; zwKT@xoqTO++9F*08SRnEWmt&xfdGzOG1UlR!)3U`FW{m{*lDG&y)jPx#rFx&^@dU+ zDRnQNZ4MoXbn|*Z1c|9YL*=n^qW^%+6z@muf$)=IW7KRE#oJ7cCM_mqQ5vFSE zT(*0wfA<1{N3*-%^flD5p5JBV8$6QIdb^Mz4?{vS>OB!cGKF?#ytV`y3 zXepO=gc!BA(l1$~iNULuJGXnv&chV5&Sc6*LWLS<$L*PO%)D!FcrB% zeVE5qKR2$JqvN~p8&3sNq_XN#dy1Lm!W8h@8N3+$@%|3Yu&SVMy%FZs7kQ81=s;8V z7Pg0IT7AhZGz5~(^vaDrfZEsRjwmsznW3G#na6?b7y;oMA|{XdyKd zQs;ixI~rvGpjmE0VA*Cy4&AzoT%xL6CRGcP5R zn9-svA??IiWu%LOQp0&LZX^Dylx~JV(^6NRE=NTui`Z4@7vO#UcKCqy=P#&bn*FUP z+QSJ|FIHRDtm0K&!uGu#--a97dxWv-~)ucc|NpoegubfQI zZmHqh2lEG|@Rw{whK62rEY;qv-Ksm<6~TMqW{@WiQ?R|oN0o5XuNW2#8 zh5{cQ2)aEcr)Fbwk@KTKEWl0L{O6`-VYsbTu~5HlRp3lG1Zo>TCE9}W1>8zd8UpvV zL#i&WNC@^Kl6N2~UVeDz`DC&(E`g0NM5ya8KtgmZu3Dq^#^dZnAHESmhS{;-4X~hS ziJNEdq&@kDf<7fgyyFNh#7Q`ouzZTg{XjsJcW*Z~IAce8o$S8q?cd(xh+Tx&?REDI zAmBKrZ_1lqa`N6Kfx_xkVH}-Vg22X zWeGA-qTLPU1PxtsJV%;p?EPxu$&@3Z>WKxp7Eh-ghK=QqE_z@K(I2H zhX{^La1ZP9+DGbXP*Or88%MF=iD`6c@WX$9(QdHCi>=V-vyJgqeO%U71&23q2+fV~ zNO=~nw{P(*mEI4Eyj!D6w7Q5tcXwhSPU0k8J{v#GmbfQdYW(iO#K-A<_j}@v~!0qZ*_c%y%k-{+WN)o= zI2^KLeAO8Y;&kgl;_CRD;*XC*a7%UJ5iUWuonw5d&ZF2hris!?jW`8-;p;269o?Ct z7zT};h+N(}c@doM_>7b8>IQUm{XAWVe>wi#rEh#OVDtg*G{_$44e_b!sPOI@~$N?j_% zCBNj?1-RwEJ(>kK;CEY(!k)FxJE!O@O3^!XHrA+S>dGV;L4}b2X=R<6VRfop1F-p zCv)N?j4Ea6Aot67>13T=Z_6k;7^}OCzi9 z4;wuFD$SP82JtuX@%sK@9BL2+pE!F(?#g1clP+dZS-5y~;3Zq!oH**u8NiBJV}EF@ zTC6gtoEGKMHe;6699Iz-5!?`1!P4f6-UxLAJvm|cgOXYscFG}Ey zCVg)Vxh$q$31Ud%u{S=64G(0T5mR*Mg-(`UzlXGxO4gzW*F#pg2w!oqX91rOGh$eZ z4=Kwrz%j{szXYdA9bI&y74E77rw?CXZSLZm{mGVUbrquv0z0&|HNz!aNPL<<)92Jo zuY5(zPgKl6qa)9lgZB-mFR!Me#h%k+Vg~wJ50;(N3ac=cnU^XOY2hn3?j|Ox77Tw1 z*|=+e*$ti@Aog0rz-zcCWO?}aNM0fRyyPaa~wl*{(@hPNg8y@rgo%PiU%`kzEp^G7GOquA~Omv{HRy)pWqm zV6*X$W1O{i@_pTc}3|l<*Cde;7n4&lV zOZ6y9P|`XYIVj_+lar~KL0aK|>`FPye{&a78$VA~Ack@S3 zZ0{bipBf_>pn&5*)P+C5q@k3uvwrP$3a_DarzHSiL&keir9;QmF0f;279$=Q?K&xO z6*1DSf0bMOqUe;(55srLQtawitok_kxp@UobJ@=xdP9c&Mb2P^rKVDcge{7U#h{tx z0(5pg*+69OU#;TuEd0j8j(@|^+~0hzM0G&`x<9#wOe_iSdt|QnVqcX??_g62UvM`P zY?O8kP9xeHBx3|-fvb2{6$aM87=j>#n-E5j=GFnBJXzMT_;z>34XVNU$f(4P(^K9= z2OsbJy{8Nv^Zcjqkgwz|Vv-=yS%d>ZAxPvJI7f07N)hgSHT1{@MH_wyx%>!{B^h1I zIdiz0>_aLIk|uuE#SG;Qr1*Ga6?V(3STt2e|0)?Pe=JJ$GtUE9h~%1C_6}&G-Fvkw zNYg*PGaDy+;FU=4LJwn7`9S*Qui&XV0e!?FOUCts8KKPh4Ofx0P8dNEEq|(_NEpoI zYYdtN5#)Q90K>LU`1679Pfc9Ech)2CJu2@h6CWF8R|v(t{4Z|L)0|#o!BK*annFy@ z3-G`Mdc!1jTEJx<$-rQ-ANMi95@S3e(E@n=<899vbEUxiqbMj>$>UVJ`aY`HbVf<4 z|0PL4YZ8=tgCcrfy~WZbL7*}P6>0TesbE3*hbut55fSpIzM7Znvxr&1ONr`7+sI$p z9nmHN#Y%);1!G8$ABOcauv9-cYCkgvePNJ7|;m<%^_hcx9%`xr%E%6+!KD)JY%9z-$#)Y8~hsv^NlwoCc-3gI0VJ;)dx`%D~`a8dH zIR|A>R(~6IzF;ylbQUUil9597kN4~MWc6ek8|aR!>6#X=d-CVS#r<7#RA_Yfs}4g% z#&O0Wi3P~v1tQN34?2&J0uOX4X)+7c`{XEPu;GH_m&Glk&o z2nch>=cq$n(vcdoi{CB(77O9+i`V7+5e_PH#J`oss#RrkuK56}eg1PB*eVJB4*$iP_+af~a}Lb&T- zTzFuc>Rj}*ZKaGQlXxtZ?p>Aoer&;*R!!UKw%65XzK6Mhh&$#@@y~nA8=2{eU;fM6 zx37oQS2DN3lrOdX7Z#D+64LkgY5R`%1xx|MzPqDcfv3ar7lDUMh41~&{O`+wx%>nI0M}!T0lvS{<49vh zd=KyUPXBLBLbK|HHRPwhBt}4p z@Kz}Z|K-|aLb$x&SZ`dQ=*gj9e>wWcQ@{O|*S_?r+7-3eed(Dyzf$*5>vPZCzNmXt z78}>R|H~V;5AHvH`MZ<}@j_n{l2N%;(*LrPHv3Eq41nIU0;ET8{p|SHKlw$Yd{tWxeZS!BYE&ug{xBd2_t?%sk(fdE`Y9bLz z;Aq(0wr~H8g#yMTuY~sPpH)`Ps~sxG8PGlVNV{Osp|BU_IsDnuIS6@;Q~q*?b>IHO zyp@C%EE0Wu&5c4eH_9~AlmXQ8rEn}?0wZ(tqO`PuMyN4?g;$iPkC&N?7&vW&i|jxC z#k+ZR)mDx)03F!H@#;s4rc>>z6?8tbm*2r6)Xf> zP`nS`;aD_e3r588@W>+A@aSL-f#mRJs)MDp<^fx<+JA{-l4bJnz$cN0usFtzP^T0Q z&G!b|&_Fd2nov%}`3hjr8^&tg3MyrrttQ!Li#mDLQ*JU_27{hKUQmxlxe*Meps51TN=^K>QEoYp*XcUE`p?q zbUt3aw+mzn!+D>=S>~^ea;5Xu#<&y236&!ylY2l(4P*9DP=;R{;E{0j56WWCZad{5spcMTQV^8p6UeQYP@M~; zzYmTWpgZSm=GE$Mb&|0~QJBiF0!o0y@D6aLG%%rXRulsC$|3v{+QN~`fOa(1jQOj!PqMg0GtrYW}pC0T1o}H_xE{8yQ24_k- zYT$WK39CO}tt`-1^&_2^b7AzxE};Cl@tTPR?hep4g*&y_3&%#gMIO`0KC%O77>>pi z@80u$?i#G?-F?p^k3IL)zE4K}e$lc0-)!X?j7@tuw+x%Er&}UG zLu6)<2y*VH!$4Au9BmS|@wd|9Gyy3J`b7zxk|%Z#Bwij7QIXS_FG zP}&dch|aC<**V-O9A+vwJ?#jA1gyv4j2pCaQGr(azARb+V!h+=)52m`5hlSEN>czR z&Pn~CBi3U?zjTYw4It4IWkjnaKRnq4%np%KMY%uHmS}`dYgh) zg&XR#%7^{H1neVyN9!fogj9((A&z8qSxI6}!w@E4tG0Wvt<7(?ib?><+m$BK7or>^ z2+5qzpNCmth&jOv1Zb>|aZY-qOIh5af*|@CVr6?|uwCKISe1?RgBCjhubH}{z2LHx z1Bi$HtG6z;?6zOwuTpB3cm%2gl?%FN*aDKWmfVbYLn>#H-$Csmb(Ix~JZPV#bqHA{ z;+=egu%gKW&cjMtP>BXvumktQHv}w8BKWszUh}%(AMrB**bj7l5kd{L;OFg!*>yYA5HI9BRS)|6`nAPkiKPx`jYM1u)iDu)#rD zqQfjW1+Y6d_4Q^X_EP4^I)s`qM1~*s=FdL4py!{151qPy_+Q4J`Q3~cK3w+dzg_KL z2g_dLiV-2T1}!9Zq9epihH@Ip4T#2D>1r;Bx}w14yZtVz+1%|PXV6YG!G!zXQ^c`; zu=Kpz8wZVAj0NF-s&}0T@&<39d9WU$Ic5Wb0AdbtkVw43v;B?y29d9rLzLvRTmKb_ zD4@HUcc+T*M9!{ zo8J15H?^?;qHW zq^T^96u^ni(s6X2fT8?-EyOHZ0@tsVJ6r~eYG+${ANB=>u)SgZLY3;U<_kP7mxMk7 z0e^cf2?O~`AZ5AtT@X$vyhStF4)fpesx7L@!nz42@oR2mZQ?9NSShc1#Ctm08CinS ze1;aT2Zww9OHa-JL1ami`u9stZi^L^8|hgQJf_rCS)OFQAj5244(=M!&6w6#dBk@* z%Io3H#nO|<*KE8DmVe1$@b`b|bX3nPcTp5V9*!Pz3ClyH{T-r}jO62xFVKG7FRDEq zT_qV2OAq(M{m0kfm7j|7I{G)6N8g|VJeU$#Y|J`JjUHjFY&fq#RT_+cnmPIA#i5jY z6p#~`X#arrQb=Y%eXX|~JW{i#TzAWI3)A$@f{-z zLNRcdvGY{!vU^YHcmYqrw_HS}c8FTYs_pW$0UA5+9(!(aN4 z`Z{?v=+Nc#;!D6_6m8uk)$I-1M+mOmDv29VK$0n42Qf4A+c|Cu zkh=Bl0QI)}4+@o!(hoNQp&2uCe}femzX#j{2noOw*YNV4X5_=*s#Ah`|RKnZ=l0H$Oh=TL84E>*{|_;ftl>9paNlL5S-HTp}Z>V zQoK89jSSW(HL!cIO$y@3&v1lI-JDuW^ia7rZ->o$5d+|Fay#6LtjB7_o-YmH5M|6B z*+ujH>A*~H~Dk8eu&pbm(!AeO=r#42!=Au2R< zNvqoypGhJ?At2)InaXZuQQZtXfn zP4M}cFsdw}v8U=5cuS+#-pg6s#VR+hIlMc$5jWbxfm&#^kj_qJF2kPOvTZB-D9C*+ z_?t#*V?ls!BkO`eoVKG)B8rFojr9nHS%k_@g4SRlG<&bS_&TrE!v))=0Z-KTLYO9f zOXn2jvl*Wm3`_I|9WKM&_UOJkDC1rJTgccEh&AkrXmxC6X)){{s~KGe|As(?G~tv{ z6R!&3`GODcA@<_rNb@C*NtX%n^`yyPZNMH~T}pz=05~0rgKn+^H=!6{FEi_8({j2s z;7y04aULSWuExzl(S(|UJR_>)0?>ij=_^~ZFdXyGaD`o{nK#3~p*zThM89c{?wB*! zG4~t;UwnZdP%KV>w_zQNc3L4|z%uK0skK!+gan5Q_?mAe-Gw|pWp~0^$>XqIlq1Qb zWjM<>8_sf0HTLRVKfh~mI%uwSC-rXk^l-dAV;+v2&aqDoQp#K1T(C`X-$nezATy?LggmzEV4gXtu?%12LyKpMLDy3WRhk290xi>T8zOH6z}Ej3}&hdaPc$ zdiuDl#0YMFGBBr0@hAvaIR$v$dCJ{#cE2CUjBpbh_k^Sevcdn#uo2 zVZpxJ$w3!y2{GUXsK5oP#7||Cz2-s!bcx-Saq6#5z&bt&ylvGjH`8X+o>~4$B1X%J znW>0L??-jFBXms}L@h$hcbXF7rm4`}niR@z&Pp|JH8s=1ay6tfLn=b2WK%KK(acTj zw{(FfADek9`l!m$i%oiFhpVk*n@KbbnCT4hFH$&ITIOp~-;0aD!em#Ff1#uRGMLQb#w#MrXQKAQr*vMKg=#%Ooijw4WO!2R^n1Ra9AYVieEix-qGq@g9Ga`!6 zVJE7r1~APzDOug^TW@(mCRWn0^33{BOgy{{XGh&&dzZ;H3qe*q3MfAc-$ZY)jaRFS z{zi=W8?ad)YG)m8>UzM4!XfxKlMw|(J1ZSDZ~5A+LW>1gd+PimFYUNXj+t-y4krp!`(I4U0 zt9+2TmhiZA^_@%d5bB4>^v8<#)O>+wR=UB{2d$BWw9X{Y)Dz-H1wqdmL;Q`yu;wPo zF{_W`Nu=mGbA5w*M{zQJk`kzf(}HO#X5L9MZGYHIuLJO$F4`(~A=-_&y!?7pf$+PN zGzEC1;!?{Pr%5Hk5mVQElODfD^r#G&Pp?pQHr^xk+vH_5g*d%-rX%Jy=5VhbnE`Lc zsB=XBYf0X8sU&5M3IWoyj0=$-2iq2jz7A`(Y6xtMbnG(&>hBn$6sxDGZx3@$S@(}g>{$dCt+|5N z40BR%aojEiQItSIqO!@7ht7K8%yAuX5E9Bg6^_M`L_w$ztWIe;N}y^4M^P+G5U95n zP7J~PYNwESW1 zl#&(iP~SU2E>RHdjB#M7B04Ze@p2W-IItTY3DRav@m8&ebJIrcYTQ5eU}apz)!Wc1 z>RgEIO44?e@4NI4b6y?ZxNs%CH!_o4hGGC#b7}J}IGYhd2uFG@3K1ERUPm01?+ZY= zoo;INL7J%4YutKT#&^1}y&Uw8U6toqh8pTh&oR4!w8v-9&G*~KXG)GMK#|r8%Gx1c zOAu}2%!u#i%o@UV4Tq8U(ZgU|Jva5@WYSUnrC=%q#JZW(VF*nu3pa`6GH%pYI$(30 zlX<$OkPrR3e=g3SZ6CLik5@S?Gue(Y&<9I*EePT2PqMlL>I^hloupIK@ex&XI(p3I zub?P!cKX4zuQKZeD7`brSNeF!)y%6Wl-gBwom)*asgA9S&uy8}ZGDkPnNz}iz^W3h z0Y8ib!)|ghHP~2t6fn_%7?4;Ol6@!GT$l;m|ehj%%O*By}=ve zi_F2^xV)LotT%b#8;>Znufmh@8ZI{tf+}R6f|Foey`x8k@QZ(QnD4IP)s9q=Da$c& z>fR&QD?G)bmk4lcMQ5xWO!zH5PHT{etD*&D5q^ruBzl`wL4wAe=klv&xXd;P-fK65 z@3Gg`P^D}K>)^5mdx-~_L%}NCZsHwvqMfLTiOa=iUn{7cg(Y*q{JYr>Gulg`K2T5F z8*rEn=A^uv>ODolIos-{_u*zySDEMFn$QVAS{U4k)*R8r zQo4ektld1FqjnLXq!Y9mDNqXsHyLKuQA{%9{rnNHiRMPJEtBn5*-bzY56o+#v}uF3 z`O;p9(Wm3we=UL&L;>6DVo%2j65;&46F|o`Q0FbErH2XW+q#Q}kPQ*Jj}dU=h2GA2 zj2`E@*fEwd;T?_ugL>EZx0ty~7KnpBh{(AG}ErE-X-HZ5^E65@zJ6{@k6j0Q{RsvV8egIC6YoxDDxvfQI7K zxjyMJrDDIU4~5eq+*S7J>$;cOCx^o2tJ&lqZ#%&xQUN!;%n+IB0j=u6Q%Vy08_Otz z@w`=vyx*#55Eb-?k`IFdvtzSXYNnR;Ub_Cr{`!_B>R$GFTS^)!u&&}TQ`|i00QmzWnjz^a+jW)MSsc>skvMK5t0ea2Gf#LNNbb8NDdxSmg zF#16gn{M;++LT>qhtF?UZ#qG7?ygLFSAKT0`LLtXZ`4-D0lyB>opddq5#l-uZoF1B z*s8^vgP}i*Fx;zmaj9B-s{Z>Hrwffk!Q^%7M7?cxH{W^oz~zjQ^u4Qx^B$hi{Vjaf z*Ar*GeYW7(qUnciLHYL`<|fMB!OeODs)Y%QwP2uP{0xSAz%v*oQ8yJaCsGj;zK{^+ z^=^-O#g^)wI7bm#8KkL_hLdg=M`0k_IA*fn^Kv-sf{3xR%rRLWKf)kyO`M2}1a9!D zaiL0dKSkoI)4Y;7>#t|JjHKQbO4G)jkBV?AGj@=lQpK@;Yju^n4xGm*&hOx6)^LQF z!Gz0A;XWf7QW+%cxuCB}1uzds^*Sg!CtMx~hv7vH&OK&Jm2jM)>9tgm?nRHyB#BcH zMb`-mLcx;`+HAqDn?(=-=w1h62Tm+w?hlI%dZTM?MQzyOozOMU6;%r2*yb{NXxT}J zw~1cgI7a1LFlPbuQz@`|`xM=5;5N-C9U`N;D zd+hj{jn`dg)q}Bl#Z1u_8^rz)csVGu=S2v_<+$jjP+SEsD$L+4%xqO54>JN0YLo?; z?CLYeJT_!rPM5M;v(?DE%&ZRC9VDs0Y{gl|l*jo!B8LUi8%N(`1tbAgcZW%m?}oM9 z%A5-rf!}QQx+pR(2yuA=^(bKS(H!vGJxc9z+|i}$B6zN^8byS1j7^cRunaB>Ne-Ln z##LAvH!%n=+A8Znnmi6cu{6@{BL9x_Lp4#Tiwa8fVNt*tj5y!CWZ(Ydk3a6#YZ%w< z;)a1uc|Uz}h_Et*6~)2PZU+yu4@*$Q_Ac`W#XHD^k=Cx~a$aCg#;VPhlZY+_*lT4$ z5J`*{&&+}9B8L@KAy|PM#qnc8zx@N7BQtL(!dBY96^HQSeraI4;&qjSql3^~Mdk6g zA^a=hZ3%h;bym({0a9}#(N$YhIUJV6J($*!epjETgtem32zYwjR<`Ac{ZzD)?$)E! zrb=&Xgy>Qd?U=R2diO{XF4FGX|HWCl=srEhktITtV-f-iAwY;DIKoG=zD$Ar9!-Vf}1tX5EO1+^QLk7CN`T`vJ# zPdyd2R&VYzy6HC2!rILwY2=sUAhbVL+Sk#oqlC%m*sv+>J>}s?&`b!$ai_3`?Xi)U z(i0iDmzh_*#9|1-Oz1-v;l?9hTG_9cbGTSCj{4^BNYN{ZA| zgL{~8(0VFr+m*<@?G`9Y46wTtEQ43z?vY~n$UHviB0;IXb>9aHgc2vBoK;2~J(#5V#i?GHXs11>8vY-zs0+%g>^Lg~ zQi;u%#6Jy7giSIo+K=mf8NO1s2rK|jtcEh_tEV-4xDB+|&sXil%^rJgJtChXua=L# z_I|Fk1n9es!zCJSoE0XVp}J(x(Ng^^ldV~Q2$@ZFi+L6&N4}oEY(S41xUCTaDtBukkO{_HqaO%l~fMp0D2-a8__?i&0 z>Z&h>V6siZ*%RQm%%*0)?u^kVCpfZ#ux9S;5V&cGtW87ZqADtYsqDs@Zmv=rNHl|B z)}5=&SxIkb++2#P@Lw}@7w!l@O@qNA2Xx(~H;7kn@dfG5MjLv7qw7pal-wT}MFKdw z)yyPm-B4%oo3UQ`9=K|sPqe{sQvb0y=-?KRifxFrM=-_?m%FHY636A!-S4<9-PF^B zkZ6Ygy%@B2N4=+b;Rqwn&8M)nOpRToECz0A+@QB=596+2;S@U2RjzlV!yhVT_yf*%twofnn-bl4Y6+YB_ZUK0Bgwd1DH8*F zm~i}#-yQhgh^}|QkLd)lMtVKKR#Y9>5mFEl6kMJP`WjF$AkkhhrSYkkv(*`9IPDPvE-CE>QYL+bYj;=&1P(codS-tb!OD;lN@F-9OT*Z?? zYp8DRkWF$FZ9%y5lSsh#gGDFGT`rv6RR|uPi1T|~NX87Z6D7dh#>JB9Ky6VI^t#~NR<@a(tBa z2=3MgGbI5^CqTV^Igq;s?PO3=vA{HBL{`grY(YAQ8wab+$F+?SY8i0Na1 zQwtl3WYtaArkbO_`=amk{Fk0O63LZ%^SehiCupwBDTdS&v$`VDG_9ZSDm=h(k)_}~ z##eIXtR}WbvW0ka@`=x@iA3och$6NufbG~vW4QL#d`~d7?usDikdnkDXLkuB%U8jAa2dW5CT`GniuBAv&clna!@Vd=cM=1iXHlj zXG?@c;_o`nlFXyMzyH0^7SA$>sw>iEbUI6?(PG|w=s_mcoBcu}hkP$iJ?hCmd#!|{ zdSn0cZoX^562FV5hvuh-KrYBmz2xEyBNOAv@NnxA__!VXXq{ABB8{o^;QK}Isny=Y z^F|ew*KoBvfvbD(%eHw1l7iDDBd=5vZ2mdF8)tVDzTHZ?`r|jh6KSB$q-SX=Lwwh# z!sL1j@p3q#xK#?FWOr1?aC}oxH)LKs)V|Ynp_L}}z5kK7jxM-vWMz=2G4me7zjij5 zW-^lwdZ-rX|3;$6;{0iJOCyqZ5T(d$(I*oH!b=2QoPLo*8|OLH;Fuh`0@lA;a9EaL z7w$3qvNZci0BwPuTzrq}y(QvODV%k@0f0H8N5yfxq1|yeSznoPxU&3+-OAD4D#{UO z1PY0k7eokPickomn24#X?-wXELA5pnS*m%?y0}}2c?OwZ$l*pTf$!mQ6-mUcHw!{B ztR2Sen+eA3fjCJpE!oBqXqgz&Wn;ibIy?K2Npr%}<)qMA#rP$d+J>PI54rnW?_LxGDEYjbic5_B$rOslP3!U zG@i6y+!m9Q>A=x|MAMHDEE7iULE5V)=D_WjjojdJ+ekmsFIi~5ziGKJ)CMs z({h?YGIrK!4i5@Qy;aNFNj+^(&x&#<05LUqeBWczSUrohdrMfq#3Ae-!r8OyuJId_ z+D!{r#EQXVt`iViMyp8A7A|O%6WPLcnzarR?6&EKbk6_O9T{W&!bw^%Ty~0pZ?1RX zS6XHQ4bG8ma=Zz*%W$WnM|F}!>!lq>DF@Ddd64YFZ58Pq3x)FI=#fmL%r zM8$k^fhX!vQ;emh-F4TCmgXsZOG;1CFu6}O_< zB=@7oEh}i?wsA%vXr$u-lPqyzLgzTMMEJl3S`9*iwh}m9J)TjgciSMyTn{Il-HoSp z^k-LLoZ$jot)S{tQ^_qddg&&yBG7VM$?9(T7J9Hj=Z?8Jm%Dldr=}HSEC~n?Shgmn z&uSF^d(<}Li0?87j}U=6gm9O51n1)Zv0>0olE_gj)giJoMWp0S0-cQ^&b40GkFVKA z_L_RylP|7jUQQ(Orle`dXX@z>0tY-*MO{kP$nKSS&E#W?gnp;A*J|m&nHWtt!jU^M zw

+M>*?mo7rciwEBc0UloI&)Tiso0j4Je?3zlY-6?@`j5|*#A+(rDW}_3ATHr~+ zN5zOygT74YzcqxLWR2Sr%0JNO&$FAZbpL=?!~k7O_3OP+65X0%HJo{^#;42G^|@3Z zv7sCVHCm5ZR}FJkuL?l@_tJG?M))-q@ZubgC{V8DvOpN=N|McHM@lF!lVUD01$wsBuz2inR3f3hf!2Z|A$$)sL9f9lm$CEgu8 zCI&f@nvx9L+v;xI`4u{on1Q!?)(niJ-bjd{r4u` z&O{VUJOglM^Wi zd8$kuaq9USS2#Q>BfDd0QP&Y_Oq-8H{b~G-bV~es6p*%Ab60?sziy^f)y}EGLnJ0{#tULOhPqO6J1Du_x8@ z%6{=1wDWPx&&dhd4?+NGo|$E3jz+Sk@K!3hvI5s6s-sEO@QpdwgGDv}?<{sxr30s; zv)j_wG-ZY1-_BG-`BQ1vl3gGr_hjDy(dN&(#l|h=x&>rvmhWN{Z&Epmj_1stAge)4~+JI0uA!IRB&y& z)#|ViK4*|->I=`txVRXK%HU{PYiKgWdmF_<*V2B)FUSy4T9M5{@kOR@Q~56j#oIiA z-If~e{>ZkuG2dXK2SUq@vY+F+$=J+qyIPKj!^)EU7sDDLfse@qdc1yml~j@U`k@3o zxSxYWD)_p%bHktahF5$?)r~m)CYK_3C0rg3-d|eig|EO1@*TWtEts1~~8>*}IzWZqWIBhJ~*QE}cIyuT1T?utlgaYGwIZti-7 zXJSeUon%$6=qXJAEvF-r0`*Tby0eRG+BDaTeKw~9l7i;>{~Kuj^1x_+RnUAoVCLHk z&S&gAyWE{)-qL_sGk|`$NiVGDXLC!Dud2}LA8k@s6aPu+AB@$=D!RQcZxGBa zW3|YNcbO~@)*}MG&d+sF?WM`exQZB=3Y6xWQa*RlQ8W_t%G(b^oG2b;JBN5vExtq~ zdT@&tYF6hSL?Yt*?YTzBGiI$goi`u!o4Iu|MqknJD8Gs(NX|t!H!u;FlTkD6H#^tm zoL5d8L1T3Hi)N=7WXyO@;;4O{N<6@~=og$sVHHuFE20Qn9rWxzKhBvEQfpqMSYI*e z^SkSn0f@M<)4>Jj(pd-RGdU!D+c*)hFr!MaZM-` zB|>v>TI{?8;{8XikjlD8`Q5JiLV7(71LFc1POwNKJtFT9 z@SZ>y_i7?1&6Zbg6= z;L&ahd5fb&I9i*>LTMSI&c4XqV5Z)YRnZb-n@)s*-*4&1v%xGggzu&c+j-iJyyNJ8 z(8bXLo>xM2T7Ob4dt31QvVWdUaaOWC9`r^O;%PpH;!Y%!GpLU7^CJ9%9z_+6yneCb ze7DZNi%2lD7srlxGFryt-6DgK*_CICI76LilS9|_P|fPWhP|x8)nl?4nKEpRLLR_o zzG3TZQdS?~yNb-Ei2QF4Z%gjHm&A^54%^3m+28^7ttMbE#K)zJPbJ-hRCZ~v=EzfJ*v49oE~Gvq>{*?0BJ zFCNtIP(I#k6mhhCQMv^)$r<(_o+rDos9-?0LdQodeH=fZb3!?lY`6rkerbum`a>1D z=899;KCQ35F|oR(P>^t?aieo&KfclV2RU0{wImDfG2B*ed!l#L zK&*FJqyXt^r@ZjDh1m7#p2SU%xI0yEx-E3Y7piAWo7~pY zF3X*>j3uw{Q9H+Pcxe3%J%yz7@365r$gCa?kh}XHN$Y@**#auQ5)f9??LAmG*zeoZ zHc*+S;mwB%Xp+xhL4RBE7W>wY`<5SbWx!a-dDQK4-CX6K(O6%z-O%TnuF&st6rk`W zc04geNvbDiGU5J`AC#oAi3*er?kokwwyCUtml~H{xPfhd#XaB+(@s%*Mi`$ z0{SH>`@iXl?LV%+aICU`)@w~7DGk?k)2d=EP3>99TWGkakLz!=4HWWusuEt^VPV6* zD~!Xi`SsG56aMAt^2qTu#_3-w;5>XInS}5qsWLE39bT$OBgMK>57Yz zpZd^p_O{ob!C%{B`4KQX>DKbffoBu%6jJ^r$@tqj@}}{|>tFQem!$>C2)UKM_jco* z?-y`!o=rkNEd1+%1Y{ST>w{>Soc2`^X-`6RKiBi*#|CiEtj~|^jqV_h<@6_B<^JtW z=A)nH=e-{^sfirs4{uMy*OMQ< zrGtsAoPXbQP&$NLQA8=O@VUhWPRXEL8sfUWj(PbAE#f{6ERjU59pw<(geQl$WTaa`QE%ZX;;49nYh{7oK~3d zh4P6?x?=RzglO_9)jO?QEKJHW#vvKWkYl`qUEzAH>8mMY+@5GrM2Pf2YDGZ zec$`%#A)z#VLq1oV$!VEtvNFzv5r4&FOSu}pO=f$*V4b9ScguTLHKIPpp|wmvAXjT z>*>4(?qOr;oi0bS)kXJnR-RBpym6mc4MZ%@Wcm3HDIe{O5cNQ9|IB3(Lf%FqLJnEk z982YHLc{{H+}P-QX6HKO?dA}TDB~{rvl_ zjcgJvc#0}W^r)HTo@bimp>9-{KdD#T16D0{A0WyF+Efhi8P!oPL@pkG`<<7uR;+I&ljj*=4S|eIj?>< z?rMIbq-Mg~lDOPlMqz5VZ0}_|8&Of_^3l25@=T7tBA;;FY%u?;!<_VpcNS`<1)^Py_$$#kLPIK=pDzA66<)vJ;DX(m zAF+02zQva(BK%#Oa z6%TrM0&~BO0wc~i=Ku=ep&5-osDCCyO{NrNE&p`B`!cn8>g~(fuFvvg?tG!_F5TLUg_c{YXV&p*&4a!}eJvze;wUyg>wwOv$4p&# zejetzlf}BUwwu$ew9tfRaj0%HzM$>{mL4i^jcls)4#lezpH5)1rmKC~h9SQj@@$ie zTO>fVcvDdk$*ptnMV_uc>pYWQWE)#O-XF88Xl z`BaUGPw1**6HYukO$3k*0;a$Jc|}?$r9K|2IQuS&7iQ*Gi?vM3Q@bhkF+lv3Yi;uQ z{^sL-! zuIfp?c2{ zi!<4Y%KAJdy39u5OOq^r)qUA0%i~nuk`exVE0yu~O<{uE=AqM)5iBHA&VL-A!UPVx zmQxy6rqR1AmFnL#rA(DuwV$?Tgo3k^heAd?kU3GQr4;!yQ>ZXIw@O@);T&nH%)@O{ zuy}QDEZ&%bpVO(6UXfZ=)9LnMZbtejGwOURg^-QejNqbk3v*_6>odut{&Wf*dvemz z*OQq%B~nMtrsFm?cUdT_mA)~xQ5l)M|IawIC$~nvFq6b7Iu1{v1GxI9xShpryAM`3Y$yk*MTPihwSwNeD_MDt_Qzmd}nW>)Qyi+-)=_xvs z3|~)?Vd^K+HRR+3XXf!}49`0ZxbSqcW|s{~ABLoJ$d-#H55>~;U;HtAiITK&#T=~D zIz`p_Fz>%3@%S=kwEUOS>(rI@U#WrNX+waIv{x>sFKCQh20@O3>>e`VCj)O1ea z{P~vx(e|*pc&8I1H^SPqDuVo3Y1BZ1ozDT9qIPFJM5B6C%zKtY@%6&u1&Q0(TBH|u}#PhFA z!ML?c!yjCei)H6$3QfE5F+m57S?hbIzT|*srwT*rj9<)3WGx?p!Z4BFI1OFQkH>Go7*UC-3r>FJL>d-lA&-;ei_7v9TQ z_ZYu~yjzUs;lc(GU1hrYEW~(Y7#`Q*iXdYDkusv z!GOBV19McdMdXJ1Ln(^pLUzhU@FX1Xk*%Y2AhRrSphf>wB}9o#en!RT-cCBSBYy^u z8nai+<(H_gcCY^Qplk%`%uu2K@hdU`^rEQuKT8~l(!W&Yfzn+v9RHwjw*41R(pSn*9Hq|*^&6(}#)qm=ohM{C{;Om)O<|4CRlWAO z97iceV4A`js@_FRhT~c;iwV*_e=bF6UsE;9&QUM~0>=(EgA?21)L5rnD_p5+7Rd2j zD_+Q3(&n9VsX*1ntdUW5Q8*MM9eXCTT4O190Dr0m$Rar)-r`X=aiPz+#7~mYPu>=S z43c#+NUCL!r1TG8tqKVvr#T~u%u-X6Pre)$RijnDne;tk-ox+3Yef& zDdh`1v^{aPQXtq=s9|%DT)32q3*6jBZaF1zS)hi?TXF#ZvBySh*4!ITHGtIY*Nbvt zIHNU0g94v(scJG;Eim%Be2i+`rV{mk`u&v3$x$^qbW)DWAH?4DZ%-+gteUS-EGMX2 zbnu=?!Q+UU5c(y;!x{7{tob`_!I(wG2Kf}xc525?QvZG%T06Bj-^Fh#UwXhVZd5S| zUcS>8e}VZR&5L_gUVPw3zbJ?T5yPr{4+_5-RhiOyr!W417Bm#E`Bjf z##e&GSR_iN;*xB~L5@;ov-=F*6>2xa$QhpU{px=p_nK5xHaQX=Q{Ia>y=0S`F^Vx= zp`3+`5uM0WseiHEL@s@#!Bp)w4>69Gq`|aH1yiDpRj&VGOgq$=0gDM=8ca82Gft#_BIiSDVXwY5h;J6ad~pcaBdm?ukqB7 zDpNCAoB+>f$YFK#no%t{`qe+Vx{`Iw7d?ARE+vOA|Rb>Bu+6+@u zqFh8H7xGeQOI0qw5tn@BRLbv&$OxLf*o7?>fUaK|y8Ue={@3vCOUItPwQt)e`?k%_ zI4WPXry@oG<62NQa=tXO3X^Xkc*DTm(!gCQ17G@o4ZQ!D$kP9FETvD!@4WMo9?vx- zS-s1ORRfqxVt8p;;77tV(+6U znH!!U6+mF4sp*!VkUML0zRtK?FWunyWJVyRN5_?(8LFcTX!xDV!!MPFcO-`2VxBU* z&72l^mC+XxdwI^8xtRtr`}g1ry4I*Xux|J@`RWcw|2d2{U_FcXhh9RqZtPGwLH`Y9(+5L(i7qXkt4X} z!~`gc-pvd=r)T>XxJI2b@XY6QBY@P1$5v=+(lWyyoFcdPST4_A=B!uCV5n>~8!CrU z3#1$OAR+9V24eg$(?O9?QTI};j3B?`YX*1C8er*Dc^1L)eo^(bhj5sy7qHe4PVwiSj@Q&icYwIepWzRpl!XydX7 z2lh^=%6@u>c<1me%+ljtzI@X>Yu_rM*#>sxlDjg9-7pt*QUA^huD`|__Wz0r+JNX? zM${w15%!#3gXvL|uWyYB!014bxG~rpZP!bAT13uiT+Q)3lfDT(m}~VFq9XPDv0NLT zvjQ;TR?IN@=fT5Q!dz%z*rO$30<>{dYEop7jk8ksHU@KVjyW`78NsBf;ESVUxmZYw z4*C~F%NmToH3dMEw`&fsY6w;XhoNjvN0?jRrN>QCL!vg$oC%<6tOv%KSF4P)KC1>3 zwhQJv1aG%o4`*uK(@Q`s=xkAgpl^w`h6C4QtN}4-C5Wl$rHJc5ORD6WoqU}ff8uNJ`agB5YyW47Li1W{{) zT>faY4{(6>_O^I^?A2HXM$TWsvjY=|Ky-~7RqnriOE0C;McUZOl@GoNZ~?FGQSPUF#w)QPR z5`g@BByQFYY?@{5b8w?ZASiE}EOV6~Ks(vOFCPLFMX9EyApays#Bzw^2R7v+F;fn- zcr@<(nSgS`oTBhwkZEc{>&(ZVo2Di{w_LiX*$9L_VL$ z{uJ*4zlUdEoiMh>GPTa_k#V$@3$J8}n)!Y_be16r*5*zQM1v3iP=cX!5)l<3Jc&}+ zFiw@?yBH-R2M=@SPwhKzn`}Yt>)4%fBPP#D&`N8Z8BY!iqSrCBS*5H6&B2`rF2o?s zb)otzdaculcX;33RV5k&R zqB@!i|GNVJOJBp-MQ4F&@Ub6V?LC1FDmPi#{)9=tPsOjLhw)3P^sHv>RX%6Gxh@c? zIgU>4Dn&tafKV`*$bqlbF{>s;KuZ&;k2I10&Z+t77A%th{myxkmc1qrcfW?dz# z$-_@=4Mdvc6jqCo(7c&@DTP56n1I4p^mAd&gk6a-K70O~WKJNE*LvsK^<|D^o*qsj zDD2qxF~Z5qLSp05Fl@b{iPOh=*6{2uVuL!ToA6b-9}P5Nr@`-VSD5Ssw;tTnoxHsW z6a!!ZmlfX@$buYZ3+b``*sU^0IQVZ2!(bXzfJTG$X%n6E#zB>mN;^n=d`R;kkwmRg z5=XJZ7K|dpnMninHIH4tqa=6-+;QGUDxhcR+BgDA_N#{wqCcTPD%k zj4j*v8nCqHCs~vV?2%VTgz7q9ha zC5(|$l^)^mq<~G#Ob{lsP+JRXXi&MFB9@zvalEZnraf*~*cH0U8xWz_ZD8%FVjOkkoQsjfyrEs??1Va~i10hfHh~m1j@2 zSHBiEVmra7t`|?P!nU`Jtu;wdA}5bJMM4sG#P9$^6Z}Ar<5dfLWnG%O# z@xAH1sNDs*dM~A^1+5WcBxQij^gik_Q^U>-*W3)RXHk#EXc~bC@Q4fkBlYFX5nDa# zLANujS4$)z#tQtZxE^Ca33T;gwkc9!8=5A(i2Zx=^a?Pd%)sYwg{w}PMyhDT~Q_ZvCI+XiXA9s6MO}iHJN)4)89P!S6q?!r_anpD({pBmF$eUG zV)a_7Qs|K;2J9UDcG$L4!vrlkdcPU$n2!0VAy$~bQDz@T&A7*OU@tI?e>q;8Ur=Jf z#?2vWHB;ZD1)#v!27lkDV?1DH2au8n=M;mi71!1JS0LUQCURcGcwG1qw1?o4nj9Qs zt0=X(P~?#t6^tBqdDpAJ z4c@P;Edl|Z$Fptz=d`9?fNzcXE0Py9ma)_|+JGHY1dtKDNJHIlu_NLw3Lj3Be!Qe*mMdXc+uYgZJctext$}-kf8SMcUcoM~? zj%rMY+bW;US^+QW`lDbo2wlqQBcIS)@SXN8FjAQfR?2|lqBtJlM~;cDjpO>qfe*4t zL(|JTyfilef7q^;5#(~BK*y1>CCtDP6YlSH05;ZL)~jn^`WYmG@bSZk0E6)$>FNYz z`&A(FjR#5aQ51P22<4+|Rxtd=ZcTX?Y=I)!5fx5t$2?%YGUP2q$5pB*NelGmPhkD0 z>zm?UfCvLQTmZvA4{F z`~0;6u3an&M*q^({tndg#2O7j_R#!Ckfb?XQMy^{6w$ zP8u{udgCk-d3#Z?pY*@l0aD?tfqA{3d0?H_<68|1i37OXefmsBU;vas%>(N+Z*=k) z_I(8)FftgAvmgKT9dc@CS^#qg>W7EI{WjF4tAjPyY3SXY?V!OWUmVN}ZTLa?Lf< z_Lj?U?#>N4^i2^Y26wt0Ty#P3B5HL7^s%9Chvzx+(;Kjjol{{GWWc34&>ouoNxDPp zhgYRLfPOR)srJwi=op^oPiGQO!@d@SpQZM>a{|4Vt|ZpDd(+nf0eo%!*!GcU?foVk(R+ zAc==>d2uS3EG3l2l&qPGLQzcio6{6`3-wz&cjjf_imORaPtU^T36=78-HKSO6v-E9 zj=KTO3&q9w-NeHOtMEpUC0L3np~{vJyoTbdg zXGB9mc{zTXb~(0*$)U>H;cwIOmbgRel_S*uOS3hb(=WBMa2IY;k7qLdQY)W>zauiR za`J-+_@px6^mOL=CF#=Yz`s={xR{e|QqB_i->o+bVgWjWxPM`QQHJ_>SUd)^7kUs zx3(2mAW^wwBHo-`&^nR0U|(^m*damo$JJkPv=8Qq`SxFwi)kxe+4Ef3rW$|jPd1_D z(8}%ecHzWDTo=1i*&kRYVZJMI7e60$ctx*Hps@6}=ub{p^hi&Hd$wG$vf9NabG3hY}TQr5pYEhJKpbGN_~3 z8x0-Or=i)cd-yS?1OtPemFr=S+K<9nWaK_I4>#rIE?J9*In-0Pc5uDD=b&cImnJb} zGBlB;l36a6HR|*>O7%xx>p>Y1INKlj(Pwc)2@$D-Smc3n*H&I{Kvfq|sCjP>#}`l3 zc5d=Y-&q~uU~v|1H+*FCO5Qdxq1EMyv4h6JnT#@9h!=ELC9%c5Uc(5jDBq8XVwA{Z z6fk{W;Y{6^5Ft8|QNJ%Amg@c53vZT;ir?vr!d$Tx+;q&R73>GK4+c=@>>H*bQd3Gf zWBwlTet7+*L`|9b|8CQHX!2k!xO+!7qqN9MkxXFg@Z~S_=-}FQ82$TN8@Q%Tb|3t05kBp(CD{w+oD(dZ!MCu@|_#s>_Ti8ldPo6^l z-BNTXZDBoAxCSK_NsAov3`LR>XW304XdhdHbn?aLO<~q3LFuyOCxBbhZ+M-=y zd~dd-nza`+4({A)uH)Ihmo>=mnKII0sT!Pkb2*0AgKAjsZaPm@baTqP@ zn3?y?vRL~HxX}ih^uV-5ULTruoJ;gC`bODee|XAjp~WI6PZt-55fLlReEF;b42nBIj(D7UVI%A%AX%b}&^cw( zYMR1YHP9Yqfw1fA_x6YGV@Z?fNjGk}Q`F@IXv#GBddY;I9(K(B$l{M*!mEdJRJc(i zJ+9vy_5io|PK9wOEG=PbB@LM%%!bwwUZae{o`bjgtBfQlQ~xwhO}yb9+FZ*AaXial zpqXeVGOw8ef)TZ#kJ6JIeE$A4??RFJG9K|WO)va!WnH|GN}Kh`O2|w2_XX|{48!Ex ztyBbL**&lf(a!3|euv(Q`g{Ax5iZEX+WX?nVJvyYvpaMqvcMiiu{Yk1*3Twq+!VeQ z%SoO{;@itTBw)UdZHZwW(}+H4Nvp*V99Uoon-2~e?cC$NTJfy1e)k5}#U-6?p?GQT z`2p0!%K|EF)JWC9GDRDpQM{a&e>PE|C_4-D>@0)3(2IE_SNb&jvV~r}o8887XD%gD zg4f!IgSJSs`Tv-^-r%UJEdRRG>ActJ#78G!CkCq@bV%BOv>|8`n5ymvIGqLpG!n5z zHV6!c3@awM{-J8C(|I6T(TXvNLnfgThlqmF8Kq~(*~(UeBgQzDa@-J@?%6=XZYB2^ZLT>)Sin?{&Gg4M^eFuK0C4 z_KmMi4A2Vaa9!e8Uv6DkBhtO@TOF$RH>zm$WYb9huS2f)vR!i%R)mTY7^LH%Cl@iL z&SiMS*iF`ZnJSW{SGE{g2A}baDDDiU7vW$0--aYfMs|y@#@=8^5CgZr+i6PM`x=v zd~i%|J|L`MD!aQLiu1do{&A+J&6>{&nbi$KCp#(pF1~>Zj6<@r^o!I5De_HF_M0v1 zug+|(rc!+D%0W3gI@{K?Ko|)eYWJP>@cZctRq;a(4h&{yBCz;~Y{yiuR0u_(PCoo1 zRt6%GZ7Y2-R3#Orlkw^N#;90i!u)Hr9}%Fkv^5K@JjxlDEU|G1jDb*QITU%jzX(IWV$ zMK&dW%K%f89lcc-?7ySQZo~GDOKwH;z7m(b8XVQZJTu8-`cP6VKSZMaEmhtzy3chm z@oKS4!K>Tr_U{oD`<4M$$@A>AzI$G?wVmoWm1y=S*~wx0Ltec&>T_LiBTS_;lrId( zs!I?!FyA<>@PJ;V{@CDrdaRK7DsVmybthhZo9jHfMjnd;^yq*rzTOUX4;B=Rvk&Yb zqx^H~ELqA#Kkf65u|u`_CE0W6Rl=++{nrz8a#L5X@aT&mLN!i&SMSQpt3Y z;>j}YCuHr=)U8x+J`v00c$md=nXPN?& z*B%|0-<3H2^kHUuG1Lum^Y|ij>A*>4X9^hQ&O+xGM31qV{UL&8>B@7m*xer2V(;7wF>uUdt zCaXQo6H*rQ3%^61i@7@g)M$s<9fUReHfo`!5{^3igoWD5x$I1+r%uM7B*%iO3tK4( zC*~#D*4?h5Ps|R~9TQb0k!bIC=&;V(^G72c-rT`k=$QK=dr!N06Zx_qi*T#y(b-g2 zU!Rb~%d8-&c%xdmSH04c=n2X+6$XuK|7O=>lx`0X~#oabQO+RH$ zg3K^G<3cBxov`afY2D+v=`KV_>rc5#1nwR88hgh&ecHcW;~m5OPu(6+JLs&iDMf8} zNNg4m0I+{lR4i>KaTI;6aF&jgUe1 zcAzO9Z9UVJi{$5pFJ~5O5wEqMM^TvxAB=@BZFkrscf(0_Nyl#hCXgL(%V!`-{Cc89 zby4b>C~O)CYr%Z0b|#960)|Yk4g2qabz`E`VqRpLC@X)^q;$)HiGs{7(w99g{vg`A zMpZobneBO51-!&p5&rJ}wV>DAgnQId9ZPtOU>zSJ`eK^K##2>R2cJybWu&tIqqR3p zlwQ;@yl%`R0Qi~DScre6?iGYBP3rzBGxz3G&UajSxPMY~Bn10e_hyVsKM&~noBuNK zW^QhsWq!Zv7yYx)yk4HGFF=hr`sw`xCc@0DWgZ|4r;pzz%u_5lG0U=~ZD+IR>hV87 z>jouj+>`aa_YQz`N-Zxm-|a7@pU4h~3g#oid8+HmR`GxgJ0!STRN9y+I&LfHUh?V< zqO^T8Iy=YMYGPE(T)c{p!kggVQezIA2c+vw%Fku_^#4ZJh#2?Z`x0rziCC!?`FfZI zmE({a>X6M4vTYJHl|J{_%W?KKp&TKSOGaHgL0o1SU4^@cj>EqmqfUG|9<%9NQfqDQj-Hr>5q4~Sk#FFY+@ey zX~#-c9Ka?a$f9BXDc-qOK5YZZi)_oZe*M7d9-%WHs-O~Hy$E)>SK-U^`acb(#*v3Gk<{{OqGgOexa9xy;(?lI^0+` zMu$wcm6>eYI+|e?d8o&~$FdGZPX_>gQ?nhyN&qJPC<7Z$^;gVD4dTG3`xgsAi?zyA2ztc+a!+HQY~u`s5jEi4 zE)~dd(({=h@PMLrRQaHRVjocXC}0O*fP>ONrHE4aTyCiJDG{v z|IJdrG|OT3H((*>K;*TUU@gE)5FWOjW1{Ymr4|>AqLyjl9Lx1GK38>WS`y|ybpdxa zbhqs;rs7NnPM5Ic`tId5xvsSrDR55M?O#|knQO4|y7{Oi>Efy4HK_CXF4DzYQhGqP zClazZD&9Kw?G*9mTc3x_*2MRGoS-VMFwk0$drNGE=>w?oAG9Rhy%0b6XVJF+Z2CULuug^3+~odPI*op!?nBo=@_VJ~0y%++ z{T|QTD%-?lFpnHeu0jUW@IvX;(re2Xt&XaU_A@D}D}-?1LooR4q&zx1U%?LDNHxn36_3>zeu<0G(go;55txeemMU#+?RzFxYQobK=*G`)%WKduBH7G_VWX-`lva^51+1 z+@x$~<2Hub{Aq^cHb&X}%MA70c-%wR9k)L0_zxWS5##mFp4qsKQB@z$aJ`LDRk0b3 zTZgg5r;mH_%*Ne){VMVI0uJ7+V{9sQM|@7jxS}v;CP|dq_No+A=7;DT4#GX@gU06a z+Q;Va$h9|3A`~Z{eYdJv%N~oOlNpo5FM(<5( zxl+pr7wq(j*`cG#_HN-jkG0 z)7e0YE$io+TwhRsG>_8s(7kJo z`mNw&(eKa8`!XY;hl0MVJf;@;pH;ALZuPSl2YqBf| z{d!h?zU9F^i@X3dIXMXq!6#`NGnPzWc54?#lGHEN0P9#*43kmh*1WH2C0Ko_^9ICi zo27N)Hp&w>sNN@3N?!J$coNkF( zjW_faTec77Tn{(9begPT>$5UAwNG8!C;)pc3=Al#p*Qbld@u-OjI{&GcY|FXBa zR=5r0!q^eHEk+pj2aVnRGYJF8^WO!U3I)ZIwVEq<$!)TBxZ0bcTH+O9i+{-Q~JZ}BAA{o*5rxa z<_YOA`RrNJj?Jt2^()4<{Dkf<7ICyhc`465uNHT0u>lc^nJ`U(n7NXM(KTO_Lqo!I zGEWyh+U~Qy%%WylL>?YCgi#mZSaz#o3-g&*LDL_^{9g9;j~WuSdQj1*Kdw5b!nVWm zSVV7N`6>+w?JfFU*E|oH(`wfXagK>$$y(J4eRLZ{<)iAG?2ujTD%IrOeOXq@RDUHY z+iXntU=9DK$?B`kBQD7Fgx86Pa#;Y`LP|{?n=oTOD#sqe@_)bF5t~x;F_U_OBHDNf zsKZYFLGN2I)Uc6$(!voEH`MmVrcVf=!i$3Kvs6H6NROKvsV{ryReKCnw`*2IpHs zjYFH%;y43Rs3BcW}$1!*xBKGE!J(xO!_iHpNi?Jf5n{^dnlN9n68^dBRCxU#w>zzDn zUwnRR4|SYVDixLQ-zi)Fq#73o*dAHx_h2e#p4U=QifOVIG9?uj z-qO}H$wHLJ;eolySjxYplk(jsaLbu|whIbPB=Hw?&vt9pbwvWDliqk4UC+}ME7}LiCAu_nAo3nkUxS?|1bd7TA zsH_VSJWYYyW1zEkGm28oCS--D@0T=PyZ10@_bYt4%?MEfvK-7pJDo>YVph`4Eak9p z4}L$TIudjMX-L>q3U~{+7!Q!gX|nLCih283=L*$@JbGsmt>XEJ_M0#fP--nE`kM(d z0C|EkOV+X()Hkpon2pIH; znCMB<8?QH8+ydtQqz!VP4S*7Y&f{ibysFqwkFnx}R~sAL+r<>U7D_20UnSD=%}#KelxhMTx=(W0PzItwm_ewZf+#^k z4wFI1LU8LO5o?|2K5^6(=g8))5lk z?I^MkyyZ(~8Dd`5 z7HtG9jf04LL}_vH*{kD$SJGUtCBx<`q zehQPRSGHRL{9l-HKt2T9V36wn<;Y?XGA7U{9!Lf>-CRMIdlf+t%?T?xS|$Zgr&t`A;SqnBX1df>WARLl2L=KxSL#5Gt01%$+Y2Rq95x*R_wAz{7 zVnN~2stdh)X)X%j)DNcNO6p0mf7$bB!lrlxrMDCOG)uyW&cVT4ohCAib`y z%kt*A+cP$pg$U;uRW(b~`lv5T|2;7%^3aC&(fs-)dAyH+-2h~1o~SaRUw>nQ;|64t z3?Dafj;RM%tAVN&9ERJ2uF@_JfYLq0gvl}KnAFwWrRttTz5w%D@ekqMYUN{vhvX65PVQVc z=Fs7K28dQAa?cS}yev!F@u`$O4Q-g1Pm}R{9!Z@~x^@VTwicap47yDm>ihRat>hfD zvpCMQVS>lYi};DG@3n9LoWTR>D@>7w z`xEs!@HB2e#8EI39j`h=;D0Yv`g=WxIKG5Mh3(any&SS9EUGuZ8mqGw&BqQ_I=8%V+muz5vCa<5E)2U+QJH#T-P@iNifQbpR_@4!DWtj?XloP{C ziHkaXd9BV*=;ys19gu^Ys`euQYF|=h9i&i)EUR&s{fR`04wt-?$brJ!QcvEsqPTtG z|8w>%&`nj@p0sJW326;&z@!u>krW#F82W)0@vc?BufsC?>xt$YgB4q!!=_Ni%` z#?NS9_)4|Ks^#O-f;yJ*S1j->U4VrLPEkQV3$V_Dd412Bv2Q)cx$k`LJ@=eTPKGyY zK^NsF`|h*PKKtzd_LEe#6l~TLkH{Y~NLp@LnOYxk(jSlvWT$5oOKw~lIlnfOh~pZ? z4qtADETC1BdGj#u5}m9sw*22i1Cdz%qq;}rYHlT#1#Mw=I=sf$lNKgUvR0@8mUc)c zCrYGQ1@VH$a8jna)pj*&^iHJ>VeNPec9lMcJl384xB16m*9KSRg=+NR1|BIyIzgOi zMzjLO5iXCSqTyEZMT%%YM0D#3$Xv+l?V95aWs+=}5drBr?DGrDn26KWe$;(xnc_4R z?;T^qI00@^K&tq%YywD5MRq|MR||U4ZxQwlaOgBnsoNUfkL}hKVl7+gY7LtC!bHr2ju)*T~ zc0vWYC`iF$unhA5eI!)Mgx_Q~&aAeI$U`BN;c0QPc z70&z9@fmC;x5bX}kgJr*C9&snEn-Vq%1p_M5-qt~$_7HXLEQ)6Ot@E)9?YLR9SbMW zXq(po4!968UI<9L=7-9olB{etJ~4w3*K!qC;tu`|q@?oY(vHrAmAF{y{Xs%nAb);J zF^-Or99-PZV22l)h+U_X3cX6a4_;=js?25BU3SIgjzVkK9-2eSWZ<@&pt^~x#~%(z z7r(@aR>hY7lUeCsvI(iH%b+>pb{lgBT2j*;m&wI567^)*hpfO{xQj`bx{1DBX>q$| z$SKx3D^~DV;e1=DrZhnUVi~Z$MX4K7B=k;rxs_))NP<_MJELk+V*`%(-%exv3qCqvy--EkiaWpTH z2-D{VJmEFvIGK0MICpA-b-bcF2MUMgouFUnnB{J-y}i+d+Q}g+Qrf0t`!M&>x zrv=m+EQX4??uKH?i2cb>=zTP_q}P>7y0F1JukanxP(m=Nh*tdS^Z~Od{}aUx1ii4& zt65X0bbGWyYQf9@Kb75)OAhR zZiVU=mvuJ+(h{CLfunP))d0Vlx6i|L^)B?ltib!7`Z-Fnc1uoKU z6ir|lCCG9rNlo`e`O(r!Eku2JhoC$Ekcc%F1;&OGSy=ggFNSqQ2#cn+=+(|u0WQmv zCV8SPMQ+@itO1)Q0`^3pA)LSfdqZl*$sThWI!DF6o6pnE9(t+b^=EMjy#B04oRX3L zPHd6+?E)cI^Ga{6WdH9ge-=(0uU|7LXpcMk`lKzHylYdv=~gqFbef!f8Owwt{~urk z)~Whq>@m8hp@~!o3<)MVo>6lE;%T~q*4#Jg+BwC_w~F0q@TVuSMk)&%n&EC~0`WF< z1AU;pf+* zStRm*El953tIJ|KNk2ExUBDr+HdQcu5Mb(s_`^m8-T z^l><32%1Bk*F_318lra@FVteFg=2GJ7=$GOnT+LFu9&r)RSWBtRnv`jR$iT_+N*42!)N4?6gEVsB~? z^pai#VPX9ZLdYD}D9~>2mia?trDvr@Cl$|%W@0bUjVjkpn-0RUHo+X$i@Hhozn~nU z?|kbJ@YF>s58)R2IeiD)n{^OmIt(`XMnR0U3;6O=zV_igjem8O2pdJSz0c~ZCn$s( zU8-NOUO)F-9nCwFKVFa0-D%QK&c&VkQch(ApI{jb zi&mkVN56ss+{3TJ9B{|J-4BlA7m-5&p5_)IZ}_u_Eh}`=Qe(bB-7r_d#nX5{zlw+G z=l1if_{c9>#YBD;lPJIeek+7$s{)za1t-nyN}km4O_YtPEk3`yoqPY|r2;#^hejLU z;o+2ChT#ke&4DNwkt5af+b=rzSOgy7o?g?$Orirg#v8%hEYNMYa>6!AB+d?_DyVxS z?9+!d={cqwbUWQ3RBr%HA>RKpAuF~b|6u+egitp3v_M;Ns;M+pGJsSQuo)A0+eNgc zQ&4KTk$c*!9s8Gk4r8GN!T^L^JW4=t6W!c|4=6vBRug7Fg)dq`0Jw|*@Gs56M@No{ z;;`#b{7^&jHJ<}O6r&Kuu{Pe85fSl6L_~f)np7FIn+h@u4}kInmTmr{K_nY4p)SWx zPJ*Uu$HbBdAoW7#B(Siav*sJ>!!h8=2q3)viwo4IhJ@#}vwCiV6#!cT02`*b{9NgU z=#;E^BwzqQ4G<{?6?4Zm!lwZMfL)r%0$3r0_adis-DzV%vAcec@K#tll9Odm)78o6 zZs&~&ArfbKByQ3;tWk$us(?=)%;L>e`nAJcpzwR)(Rt6xX+kqJcn%YPKt+tWH8YDp zcrr!eIETb;F%onAf}{3Hgd>Dicwn#a3eUqDujO%@F~2k_*o=vl+?_K;Q#JNia2?j` zV{$#>h~@?||6DyoPI`uhlG*DiB1YmF4v7&O5`7#JHwii7$_S1SOEh=|EFpTuoAC(G zl^S7dpJgB9WEIEe2swW%Z<#G*c9-Lbq$IQ8()oceZJMCLOE(p;4!D^jEb_N5=8!1X zkT~z_oy}~=hkk!RK#GY)9KUJp6lOf@?_+RZ!EUH-N00O7t7hGOx}FT0RKC_0hZ?`) z&c~f*W=s6@m~REejCGt>^o<%CwT{cofb=$_P!ss!7>7oYM&Bg?+G6v&Z{=si^6JXh zoCO-uxU(x<&k$pb-4k1#&p28mv8=(^Mn9R8)UoVviFsnisN~WfC5GMY7RJ7^Djr%w=;NQgZe(qcL|iG7{=pp|pCUi8D6F zXiIvAd5|LJ%DLR>pemd^ZSWT6NxFCi&D%K(n7TKdCiSF}4X7F|yo8_Fc{@i(wa9Q? zO6_3vnSIsN^RwM8yud2UIHshQ(bac{&h4u{GnIC}wh3&^jH5ZYxc#8#b;h->-@&CMtImzwu<(G+-NarWhp6Zt^W!;)#2J$kc^k0B zq37LMyogq)W+L9KHx+tTi`OAHFX0xVMmqXO8;LhcG1cSk$Tu8s&!?+$<`3i#N29h@ zSx}M97Ue;_y^XMtf*hpD4S{T&L^}0s?doKo7|6#Q5ZXgw5CMV90ZI!nr>`fk+a`;- zWbxhH^-kq@339xaoRHLxq|3W=E?61_Q35D_9(#(D#F_?{+_Iq5k_n1>%w|VIGW@Zz zcZ$(b41bNXIIQ+*GwI(MbP=~Cz2XBCpaoXBTUk}A$zw3LL+)Y z_}55i1Toto{snId1^dn_&d);cmY%vlSu9?UEdbm`Te;a?XOn=h*F3K9K!}7XDx#Z2 zL3>1C?$%3Tq6RIhnCJ}q=gDQU<0W|O-(XcYUOQ1|MFPue<91@Xc2CqN9fJ z;20!7F6D~?HHiPJ?_w!NF1zeT+jE`$Wm}goqPpd!l^urfQFu{&z3i!G+kv&=EnBzU z7I?3}?CARw?^2}l{>bIEZ3Zt&uu9u(ODT4HEQg(-J;xQT5d;j8eB3u)qn!M=hLH%Z z{^#F8b!(H9Tj+l_MvsR;*cglk6CUz}0&}3r-UR=yw9(#8F?ak&w!cvnV>!Jf|MN05 zqG42$I@)RK%7geouj(`UBhQ~~v1Oy$1u-9`nLAm| zRC;D+pw<^%la)b_8Ee`M3C{M-!CSlsoVHLj7|kyB>VrBAqOuNCyhZ&r5YKbN)nQt5 zd%^~M*WL2MNo)2ogPFDii^&6zCuuw&6F13@H_t*GPb&}p^Bs}w zm4&W>I66c11B@gYpxgde^;qYZRe|X!!6pt5o?%ubo9L!!od}#JNft|qNsN50qS$Pw z=X85ToOl1ky!#pL-39Es#jj?~gr$7!WBR?Q+2chrBX{BU4T4mG>yY?o4TOD~q?`{?CWuO=}Ol0@5o%6m?uNRLWU(&9P#a%g@!4(vX2$M z@1hie3Bj6$9#!fN}W(-w_9tD_{L|!;SZq~x7`sQ;~gC)uJAW% z*sn+0^Qzr>o@jk|EGjXrYw~?RD{|0qOg6YYQHV^ReT6r-9qycIws%K7xm3lh>sguw zf-NE2M94ixgXA_s5J8gzK22!&&g^zImq*Q^M3A5D0d-Uuj}OITe#WajL^ZI{2?(>R zcsyDwQW{X3qgOV?x!$U38A{Kfj2Xd)=;4OWez~k_eC|9Fcsbd!K~SnimcCkB`b@g? zqqcJVzt*91wYN9+kdVs{FAB!tk`uzDh8(BXxBD7%za1C!55Ua-g`aiUC|;K_2hVA- z{UK|-*E0s=YqbAUpZi+tKk$C1h4=b&7?!>`rN?JIR>Z{I!=N=%FTs3dh-+Q~KyvX&_gl+TAMAOzvx4)k^Sfic~Pr;*DpM z{Oo6)mju57+Xwxx%vT;9jn?#iB#vPrC52&U)xhg;xQ6D=Ju}qgcAnP_oyNt#tn^J}Ndbt`M+er%T;_>L{>msA4Fdo^eYZg~O zY>h|Kykv^T&q}HCa*Rf^ieI(T8smmwbg3{9UoWSfV$o9M`1`^*B1mf!zw2oLNH21DPBB`K5|bbqs2rjCNE*cwx3;cMMvLj%L+#)6XS;@QY$DF#U8f}r zITSE0MJ9@>0T`^2!FOJaR|XOVd0yXc-3;6(Q=7yFB#RIIP-&NqE-&L}N>$i}Yy{Y8YV%i8NesX*C9tg& zguD(e`L!mRBc==0n7&w!UYbvGrTYY#! z0rdqBS<|-qfP^xPR79RmL~`ni*=$Wsy>2^Y8WW`Zx&8uHY9}NgsQ15sJdC5LLu;r1 zpx=UX$t3Q?`lXzt1R+g+$GDKO94{++7mQ(DqAh>f;}1LrK*$I;n35#LhkQg8O=1q$ zNYa{k7{8@jnhGIzPJEln-_xLcx~=&6`VHeK|J_mO+U2P@hT3q-e;@E?rG!UbeF@fhqP~KGiAO@-2-$5!}J9mmUs%QW*#Jes%7p{7&Quv;c@PY znN$Z{bwLXpsa`Nt(t#lSXIu@9#>i(T%Dd=+{U_CCysFf6IOE-W)VJVg(4gK(C06ol zQ3(TtP{Ke+yAFaHZD|swLBfSBry;4Y?9?YhonJS#)Zj`C!2kjRLDpjbX%s}B9z;nT zy^8Y1|5f)r;7wdtzIR4rc}9$#K{BcA7&@|LTOy82q~(?=^z3yuS>*U8ef&8F}|akA-4vPs)C z+uiEjGoz74mSpJm+wZ;ieg43bHCOkZd(OG%oO{mi>@3}#hSkaB{_~lG@^iCHB+a(l z^3CHLn!xvLJNt#qS#Qi83p_9Zu_Sh6t5@PIYyfKD9}y*U>MM;&9DB(BfSLN<$n8ic>;cJt-o zo$i_Juxn3NieAC020YX!wL=YxQ@J8HPp?iK*s^IBr}pe?w6hAvOlq_*&Zh8+Q`sm%+OkGLpUu7)stjoJjeawWg}$XE zm2Wo9g-aaiRH=K?Wirl$=3!T%Vl<%Fg!(n5r&7^fn9BUjwMmPXKIs!MnTPS!z|`py zuoa#Kb0O<$N1Z@jVgGc!Els^jO8(3(B|jL=Fiz@C&2HwTdTX-s{yKe(Mjq5&x@BVh zKPpI=PiRy|x=f(qfjK&j{?DXVIKk$uE4cUH&@kE0(#d)qcWZ#dTp1m;QxwJvXBKG- zThj~K@Y*Ldmm8Us5!gsxD#%C+G&yX~WC9UC)P|5VH4+~pUAoJBGI#H8%Xjbj@^`d# z0`W}ja(+Tpi~BceUi=+2`q(;uNHp#} z@mP_HLo)xl(!5JPJX(0k-_LyYUj;%b z%gSHNgl=xe+*YF$n$<%{Ou4hY0rF~Y9NOV-k}+kzCvAW4yI=_vw?Ln@QaK zR|vKY_Yy52SE;F%_+ecms)(UTvwZyszo!^p5Uk41JrGxKuG z?-P@GNTw77Jm1HW`x!lhsxI{-wu-YF@kun-=Mgud07uyP0B1$!R-x(=i~Y1y=VU`@ z>uHG6+^Ct*;{k+}dbwX1$MJ;TqI8J2%rc?E^XWCwD~Srxfc8;>+cqg0Io?vH^J1Ub z=q{f|Mv@XGA8R9C!nCPR=XjdeE8Z0J4ta2oT_TVpdta;k9m{^D)IQ40ot{ zcHiipI%UEYj+y<-W}U;m#wlwCIV$cvBgv=+Yaz zpV_0)0}<>%dkPOj+^I1*Wq9HrvIv3g8} zsL?V&)|pfF3l(wsGM979@QupF;LOYA z19=16sv3xOp>odS^wFM(!zB{ny3}*!qj*D*T$d-%*kzChc!tHIyG@DzguC7=0*F0? z`km7;P7H+?S-HkxYEmFjnTJFyrK9|%Wu48T;a!1fgVifrh7Y}vgD6s~NxjOb>g)HU zzHz8>DQ|$MXz1 zivV`A%SKx!TS%4|B3LGb1fH?P8-2pXC@i?r=(cS@d)-Y4$yxQBJE@)N3rgtzXScbg zF;k69%N+-yDUIBT=x-+E5Ofrz!Jf}VQiam#Ha7}=dRtLHr$_ooKwPRD_92G@>mIbM zB5+wm{T$1m8rB(E8I$(+;Vh}R_feA7k@n>S^^)V)v_ry#sFtEglsj{pdN^`EAXimd zD0>U-_aem@zg>6c*1!svs~sWpuRZ=$$E@E~uDq0Lm-VaQb5BpEe%~s%)y$@3fsOdm z6RW#jjwmV679bTN1w1^1rHX~fDosdS0AYJfv=AjJP+<9{U?e3~@1A^>G8-uW6N@*{ z9TT!pm5mNqBxfC#cRcOY5fD;Hs05rtwe`SVk=+j&h+2d-bU9)TlX48cx9h!=A9*Kb zdLOQSeaYy_pY8m@yheqGp0{-7OP5@$Mx?fukHQ7cy!4IVJB)nHzr#qSogGo^b0^*X zuSmj1(E_1Xiw|=y!bctg6-a04#MgJbuduo7PY7}-c zuKCO6w$)%ce;;Uc$0kfWqMJhCyfsLIiw==yE0SOGl8lY1Fx)s+A9()77QeSmiHy>x zU@B;{>`|?Ax?lJolzO*aO&z~wW%#Q5k2P}3YrB8>{P9e4O|G3cr*o&T~T4W5+r_8MgI(;5%-0SJ4JyEFv zIrbt!0l^JTt>}@K1W-v%@<_P@K$ZQe>H+>2r14C6{ zGX)iOa)e`lmma}mq7de;vn#eVQo@{QdsVlg&=Visy)3%zD^uA4yMXayr2)}%g!`43?}Hc6Ze!z&;9 z(9n*j=uWJDm}MZDo6N7^Rql~DZl~mEF>g-@$ZSbn!kq4}9ph{)fwcuPB6N`^P{2*1 zN~N>aM!KccOv8yJ7<7VT6l;EbR1y&)K~wnLHaqYHptdh>p}?vl2cwFB$UM4y(&KAUUT8SG)19U_yDY32%%#j|2K#vIJ|y~1$p1Hio4iLFt(QNG3=#}eEK%0SU( zQ=u>$GMe>Bk^XV+3bT2_IZeemkP6IAMv`f73UbP}peTwuz|Olm@uv@!!inpuT6W0f z0o8b(IqM6OR)%!C+ztC%({Sq#cVAGiP`1)8rF&(q_9$ZfLh!M`mBH2FFp)$E+c*f( z?mR-?J=7WzbZkb*8}>vm^TGB5)E<~Q;)y8diMnlpc(v@4W1lPH(8+KaSCfsOy2$WG zJf~YaJqpOY-7zGV^)xzoF&q-cT}K+ByJX4*`epoHaQ&@a~s+CHY6E`h6(R}N`Ig<*)-H+9JO)L zz!Xu76|Y!__W`K8lGbDMl}bnf#MI8;1-5;4F-nXP1Rkc#U0y>q862|0pOw=Zq36=@ z_GsgN;#+bom)w5E@_|I0qKirU-wibEUpyU4?b`#o1zO^W zfxA~Ra1CKsD7J-Xpv@3|S>dK3M2N6Y;-*~{qz>+KH#lt3`jQY)67UGRJq@VQ8YkS4 z9>5zy5GP4CN*uOv1u$yO#>ps_)?NY+gN@KJlwcE4Q6Iju}!uoF~*S3(|ob7h(71=%Poa z+D7Aqv1=4nS0a5mbk(uN)K!!;!|_tD^loRAo(xK!fGm)IUhr$#5Ko?lwmo;4*OZoF z>#n_mEV5uPmaP4a)Rs0KQq8F&Amlqc|FR8 z{A=CuGQr9!87rswmd70l`u&uRlUno?L3k~6^n1z(uV{>GImoWm+dV*-2qA5bmF*hlWe}FwVeJ;Z>}&KsqN!N<46L3F|}WZnlNq84`7A4tce>ddo<=x3)U{m ztj|7WQdciCqL|@SO+xwLP+e|yL-MJoA1E%eTcRoT#CmP0A`HEyM4MA@Cg)K8#~VTn z6T^nrhduU{0xHsl7Ik>iMIyfx6|nJ~YpHD6zS%b4h-VsZ?P;uwg5iJ2)H`&A^5Er$ zrHxhl{CS(Wvogd-k)pJ`zA9N|qq*xm{8{X;J6Bg2dk0KUU>7YhC>U$@PG#B`9U8p~ z58O4$69YsjIrwVSl4>-YkVwB{Dj_0+p0pPaOkqbqmbVC@tW3W3Oz~XBb*Y@Sr}wcX z>K>P@TMZuf_zn+W_s@noj0`Y$egEp>Dk8F4w(L0OQrV4`pr;8NFvnVtELgqupd*)V z_A$AW_PA@RRo_E`UNMXfJThj|Q`MF9@Y0PFt!D;JiF}OZcELa=^zte5@)Nu%g&`N@ zzNNNMecrV-X#g``3`83^%!&ELNAlG)+oyRZ$!bh5_r zL6a~d@SCczWmiWB+p$5CjhizVcR?VcdG4{s=sFY2ps1U~HeLW5TB3p4?hV`W0b2h~ z3d`6whn4i#8rME+Du2GJO$EA8jXPV6SjJcq4nF#U)VQ)KIN_|>9My$l_Ne`Ke*J{g zW#{POMWLQ8ZcqIwXp7(t+U7sPdXFh-xoHid^gp2vL)(Xmx!#eXR}HJMK{}ViM<|W0 z@_tMetdR4@`>M-26$e1c8fGerl{Ixmj%1sngAvxCX9ySXGIV;4Q-i_wNxm35ac^li zPGB>185AD2HJSD}F3X)LsW(|~4c-TXm>WS|6xPVu2Og=1GcL$cL-~#V*y5kUP2@B(8;elYgNG{^W zcDega{oEvW#12C(VLumTEt7ETKjFVJXo`tf25a-^rDV-ssa`Ogk~1QG4w8}E>NHRW zcXS`tPG|&0+ne-)a>(VYHT{W-8l+?`!i4M9E1O@%e<#6WMl6GC-44Lm6M_?4qelf;Wi$l3rj~KX?D}omq3O!G0sMT~bcpfV(M1`rtZYba1M2 z3mJwmIkFU}DlSX0>Q9<3L-m3@O*v;asgbFjz1;Xxi-4u5T56actgD1bp5)p@hy2)b zlOv*@veBq6(uGA?Zbp1YK$t>EfpZ~lP`1LTkuy3bgm&ZCuJ#!^R8;^{E7@<^HXZE7TO%4DRB5_bht(|MFS2<;y5q=p(O_c8pc6u;ueu�i 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 %}QrkTSApESl`f5m8Ub7}ad< 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