summaryrefslogtreecommitdiff
path: root/chromium/third_party/tcmalloc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/third_party/tcmalloc
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/third_party/tcmalloc')
-rw-r--r--chromium/third_party/tcmalloc/LICENSE28
-rw-r--r--chromium/third_party/tcmalloc/OWNERS2
-rwxr-xr-xchromium/third_party/tcmalloc/PRESUBMIT.py12
-rw-r--r--chromium/third_party/tcmalloc/README.chromium94
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/OWNERS4
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/addressmap-inl.h421
-rwxr-xr-xchromium/third_party/tcmalloc/chromium/src/base/abort.cc18
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/abort.h19
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h79
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h235
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h369
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h416
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h359
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h502
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc125
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h428
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/atomicops.h391
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/basictypes.h357
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/commandlineflags.h181
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/cycleclock.h165
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.c190
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.h627
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc433
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.h134
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/elfcore.h385
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/googleinit.h88
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h2280
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.cc665
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.h53
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/logging.cc107
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/logging.h288
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.cc522
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.h106
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/simple_mutex.h331
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock.cc182
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock.h151
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.cc102
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.h64
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h114
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h62
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h60
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/stl_allocator.h97
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/synchronization_profiling.h50
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/sysinfo.cc1144
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/sysinfo.h235
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/thread_annotations.h134
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/thread_lister.c77
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/thread_lister.h82
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/vdso_support.cc189
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/base/vdso_support.h155
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/central_freelist.cc372
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/central_freelist.h200
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/common.cc222
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/common.h269
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config.h19
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config.h.in277
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config_android.h271
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config_for_unittests.h64
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config_freebsd.h278
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config_linux.h268
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/config_win.h311
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/debugallocation.cc1432
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.cc1128
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.h390
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/free_list.cc145
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/free_list.h202
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/getpc.h198
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/heap-checker.h33
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/heap-profiler.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/malloc_extension.h33
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/malloc_extension_c.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/malloc_hook.h33
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/malloc_hook_c.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/profiler.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/stacktrace.h33
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/google/tcmalloc.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/heap-checker.h424
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h131
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h404
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h99
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h358
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook_c.h173
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/profiler.h166
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/stacktrace.h116
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h133
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in123
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h20
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-checker-bcad.cc92
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-checker.cc2378
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-profile-stats.h52
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-profile-table.cc751
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-profile-table.h525
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/heap-profiler.cc695
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/internal_logging.cc194
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/internal_logging.h152
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/libc_override.h94
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h111
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/libc_override_glibc.h159
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/libc_override_osx.h275
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/libc_override_redefine.h93
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/linked_list.h102
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc128
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.h20
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/malloc_extension.cc377
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/malloc_hook-inl.h322
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/malloc_hook.cc723
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h165
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h267
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/maybe_threads.cc137
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/maybe_threads.h52
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/memfs_malloc.cc267
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/memory_region_map.cc816
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/memory_region_map.h415
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/packed-cache-inl.h240
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/page_heap.cc546
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/page_heap.h311
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/page_heap_allocator.h127
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/pagemap.h526
-rwxr-xr-xchromium/third_party/tcmalloc/chromium/src/pprof5348
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/profile-handler.cc555
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/profile-handler.h148
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/profiledata.cc331
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/profiledata.h183
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/profiler.cc344
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/raw_printer.cc71
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/raw_printer.h89
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/sampler.cc130
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/sampler.h179
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/solaris/libstdc++.la51
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/span.cc101
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/span.h101
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stack_trace_table.cc159
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stack_trace_table.h91
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace.cc110
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h121
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h145
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_config.h89
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h83
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h128
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h170
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h91
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_with_context.cc61
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h396
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/static_vars.cc73
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/static_vars.h111
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/symbolize.cc280
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/symbolize.h83
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/system-alloc.cc695
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/system-alloc.h88
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/tcmalloc.cc1880
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/tcmalloc.h69
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/tcmalloc_guard.h48
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/thread_cache.cc514
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/thread_cache.h430
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/type_profiler_map.cc112
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/TODO86
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c156
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h155
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/config.h306
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc64
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h34
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h123
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in123
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc121
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc1219
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/mingw.h67
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc431
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.h197
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h236
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/nm-pdb.c266
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/override_functions.cc122
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/patch_functions.cc1080
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/port.cc362
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/port.h477
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc684
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.h611
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc367
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc296
-rw-r--r--chromium/third_party/tcmalloc/chromium/src/windows/shortproc.asm169
-rw-r--r--chromium/third_party/tcmalloc/vendor/AUTHORS2
-rw-r--r--chromium/third_party/tcmalloc/vendor/COPYING28
-rw-r--r--chromium/third_party/tcmalloc/vendor/ChangeLog646
-rw-r--r--chromium/third_party/tcmalloc/vendor/INSTALL539
-rw-r--r--chromium/third_party/tcmalloc/vendor/Makefile.am1386
-rw-r--r--chromium/third_party/tcmalloc/vendor/Makefile.in5373
-rw-r--r--chromium/third_party/tcmalloc/vendor/NEWS338
-rw-r--r--chromium/third_party/tcmalloc/vendor/README265
-rw-r--r--chromium/third_party/tcmalloc/vendor/README_windows.txt118
-rw-r--r--chromium/third_party/tcmalloc/vendor/TODO47
-rw-r--r--chromium/third_party/tcmalloc/vendor/aclocal.m4928
-rw-r--r--chromium/third_party/tcmalloc/vendor/autogen.sh54
-rw-r--r--chromium/third_party/tcmalloc/vendor/compile142
-rw-r--r--chromium/third_party/tcmalloc/vendor/config.guess1526
-rw-r--r--chromium/third_party/tcmalloc/vendor/config.sub1658
-rw-r--r--chromium/third_party/tcmalloc/vendor/configure19825
-rw-r--r--chromium/third_party/tcmalloc/vendor/configure.ac421
-rw-r--r--chromium/third_party/tcmalloc/vendor/depcomp589
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html264
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/cpuprofile.html521
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/designstyle.css109
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/heap-example1.pngbin0 -> 37619 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/heap_checker.html534
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/heapprofile.html373
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/index.html20
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/overview.dot15
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/overview.gifbin0 -> 6472 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pageheap.dot29
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pageheap.gifbin0 -> 15486 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof-test-big.gifbin0 -> 111566 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof-test.gifbin0 -> 56995 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gifbin0 -> 100721 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gifbin0 -> 31054 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof.1131
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof.see_also11
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/pprof_remote_servers.html260
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/spanmap.dot22
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/spanmap.gifbin0 -> 8482 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/t-test1.times.txt480
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.pngbin0 -> 1882 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.pngbin0 -> 1731 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.pngbin0 -> 1314 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.pngbin0 -> 1815 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.pngbin0 -> 1877 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.pngbin0 -> 1838 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.pngbin0 -> 1516 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.pngbin0 -> 2005 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.pngbin0 -> 1683 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.pngbin0 -> 1656 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.pngbin0 -> 1498 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.pngbin0 -> 1912 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.pngbin0 -> 1689 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.pngbin0 -> 2216 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.pngbin0 -> 2010 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.pngbin0 -> 2163 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.pngbin0 -> 2147 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.pngbin0 -> 2270 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.pngbin0 -> 2174 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.pngbin0 -> 1995 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.pngbin0 -> 2156 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/tcmalloc.html765
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/threadheap.dot21
-rw-r--r--chromium/third_party/tcmalloc/vendor/doc/threadheap.gifbin0 -> 7571 bytes
-rw-r--r--chromium/third_party/tcmalloc/vendor/install-sh519
-rw-r--r--chromium/third_party/tcmalloc/vendor/ltmain.sh8413
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/ac_have_attribute.m416
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/acx_nanosleep.m435
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/acx_pthread.m4397
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/compiler_characteristics.m424
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/install_prefix.m48
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/libtool.m47377
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/ltoptions.m4368
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/ltsugar.m4123
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/ltversion.m423
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/lt~obsolete.m492
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/namespaces.m415
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/pc_from_ucontext.m496
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/program_invocation_name.m419
-rw-r--r--chromium/third_party/tcmalloc/vendor/m4/stl_namespace.m425
-rw-r--r--chromium/third_party/tcmalloc/vendor/missing367
-rw-r--r--chromium/third_party/tcmalloc/vendor/mkinstalldirs161
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb.sh74
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/README7
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/changelog196
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/compat1
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/control25
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/copyright35
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/docs47
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs5
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install12
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs2
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install4
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages1
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/deb/rules117
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/rpm.sh86
-rw-r--r--chromium/third_party/tcmalloc/vendor/packages/rpm/rpm.spec77
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/addressmap-inl.h421
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h79
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h235
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h368
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h416
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h359
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h501
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc125
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h428
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/atomicops.h391
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/basictypes.h357
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/commandlineflags.h131
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/cycleclock.h163
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.c190
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.h627
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc433
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.h134
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/elfcore.h385
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/googleinit.h73
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/linux_syscall_support.h2182
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.cc665
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.h53
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/logging.cc107
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/logging.h258
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc522
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.h106
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/simple_mutex.h331
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock.cc182
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock.h151
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc102
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.h64
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h103
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h62
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h53
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/stl_allocator.h97
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/synchronization_profiling.h50
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/sysinfo.cc985
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/sysinfo.h235
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/thread_annotations.h134
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/thread_lister.c77
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/thread_lister.h82
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/vdso_support.cc189
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/base/vdso_support.h155
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/central_freelist.cc376
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/central_freelist.h200
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/common.cc202
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/common.h246
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/config.h.in274
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/config_for_unittests.h64
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/debugallocation.cc1420
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/getpc.h186
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/heap-checker.h33
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/heap-profiler.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/malloc_extension.h33
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/malloc_hook.h33
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/malloc_hook_c.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/profiler.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/stacktrace.h33
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/google/tcmalloc.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/heap-checker.h424
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h104
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h420
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h99
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h358
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook_c.h173
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/profiler.h168
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/stacktrace.h116
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in123
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/heap-checker-bcad.cc92
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/heap-checker.cc2377
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/heap-profile-table.cc696
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/heap-profile-table.h422
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/heap-profiler.cc555
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/internal_logging.cc193
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/internal_logging.h143
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/libc_override.h90
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h99
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/libc_override_glibc.h148
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/libc_override_osx.h275
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/libc_override_redefine.h93
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/linked_list.h102
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/malloc_extension.cc372
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/malloc_hook-inl.h322
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/malloc_hook.cc723
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h165
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h234
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/maybe_threads.cc133
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/maybe_threads.h52
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/memfs_malloc.cc267
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/memory_region_map.cc652
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/memory_region_map.h340
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/packed-cache-inl.h238
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/page_heap.cc483
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/page_heap.h294
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/page_heap_allocator.h113
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/pagemap.h323
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/pprof5348
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/profile-handler.cc555
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/profile-handler.h148
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/profiledata.cc331
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/profiledata.h183
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/profiler.cc342
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/raw_printer.cc71
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/raw_printer.h89
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/sampler.cc130
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/sampler.h179
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/solaris/libstdc++.la51
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/span.cc101
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/span.h101
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stack_trace_table.cc159
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stack_trace_table.h91
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace.cc110
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h145
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_config.h85
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h83
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h128
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h170
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h91
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h351
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/static_vars.cc73
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/static_vars.h111
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/symbolize.cc280
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/symbolize.h83
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/system-alloc.cc530
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/system-alloc.h77
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/tcmalloc.cc1673
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/tcmalloc.h69
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/tcmalloc_guard.h48
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/third_party/valgrind.h3924
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/thread_cache.cc503
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/thread_cache.h403
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/TODO86
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c163
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h155
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/config.h306
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc64
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h34
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h123
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in123
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc121
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc1219
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/mingw.h67
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc431
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.h197
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h236
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/nm-pdb.c273
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/override_functions.cc122
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/patch_functions.cc1080
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/port.cc294
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/port.h474
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc684
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.h611
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc367
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc296
-rw-r--r--chromium/third_party/tcmalloc/vendor/src/windows/shortproc.asm169
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj127
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj301
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj150
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj785
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj373
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj157
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj170
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj127
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj201
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj157
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj154
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj151
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj154
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj153
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj150
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj170
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj170
-rw-r--r--chromium/third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj884
449 files changed, 167593 insertions, 0 deletions
diff --git a/chromium/third_party/tcmalloc/LICENSE b/chromium/third_party/tcmalloc/LICENSE
new file mode 100644
index 00000000000..13e8476246a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/LICENSE
@@ -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/chromium/third_party/tcmalloc/OWNERS b/chromium/third_party/tcmalloc/OWNERS
new file mode 100644
index 00000000000..0c374cc6905
--- /dev/null
+++ b/chromium/third_party/tcmalloc/OWNERS
@@ -0,0 +1,2 @@
+jar@chromium.org
+willchan@chromium.org
diff --git a/chromium/third_party/tcmalloc/PRESUBMIT.py b/chromium/third_party/tcmalloc/PRESUBMIT.py
new file mode 100755
index 00000000000..8675618f309
--- /dev/null
+++ b/chromium/third_party/tcmalloc/PRESUBMIT.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Chromium presubmit script for third_party/tcmalloc.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+def GetPreferredTrySlaves():
+ return ['linux_valgrind']
diff --git a/chromium/third_party/tcmalloc/README.chromium b/chromium/third_party/tcmalloc/README.chromium
new file mode 100644
index 00000000000..41bd1602586
--- /dev/null
+++ b/chromium/third_party/tcmalloc/README.chromium
@@ -0,0 +1,94 @@
+Name: tcmalloc
+Short Name: gperftools
+URL: http://gperftools.googlecode.com/
+Version: unknown
+Revision: 144
+Security Critical: yes
+License: BSD
+
+Description:
+This contains Chromium's locally patched copy of tcmalloc.
+
+Contents:
+
+ chromium/
+
+ The chromium patched sources, copied from the vendor/
+ subdirectory and containing our local modifications.
+
+ We only copy over the vendor/src/ subdirectory (the only piece
+ we need) but still leave it in a chromium/src/ subdirectory to
+ keep the directory structures in parallel.
+
+ vendor/
+
+ Vanilla sources from upstream:
+
+ http://gperftools.googlecode.com/svn/trunk
+
+ The current revision is:
+
+ Last Changed Rev: 144
+ Last Changed Date: 2012-02-04 00:10:11 +0000 (Sat, 04 Feb 2012)
+
+
+
+HOWTOs:
+
+ Take a new version from upstream:
+
+ 1) Grab the revision:
+
+ $ svn export [-r {tcmalloc-rev}] \
+ http://gperftools.googlecode.com/svn/trunk \
+ vendor-{tcmalloc-rev}
+
+ 2) Check for added or deleted files:
+
+ $ diff -q -r -x .svn vendor vendor-{tcmalloc-rev}
+
+ 3) Copy the new revision on top of the checked-in vendor branch:
+
+ $ cp -r vendor-{tcmalloc-rev}/* vendor
+
+ C:\> xcopy /e/y/i vendor-{tcmalloc-rev}\* vendor
+
+ 4) Make all vendor files non-executable.
+
+ $ find . -executable -type f -exec chmod a-x {} \;
+
+ 5) "svn add" or "svn rm" added or removed files (based on your
+ "diff -q -r" output from above)
+
+ 6) Create the CL, upload, check it in:
+
+ $ gcl change CL
+ $ gcl upload CL
+ $ gcl commit CL
+
+ Note the revision number since you're going to want to merge
+ that to the local chromium branch.
+
+ Merge a new upstream version with our local patched copy:
+
+ 1) Merge the local revision to chromium/src
+
+ $ svn merge -c {chrome-rev} svn://chrome-svn/chrome/trunk/src/third_party/tcmalloc/vendor/src chromium/src
+
+ 2) Resolve any conflicts
+
+ 3) Create the CL, upload, check in:
+
+ $ gcl change CL
+ $ gcl upload CL
+ $ gcl commit CL
+
+
+Modifications:
+- Converted to utf-8 with: vim +"argdo write ++enc=utf-8" *.h *.c
+- Added support for android.
+- Use NULL instead of static_cast<uintptr_t>(0) in stack_trace_table.cc,
+ for -std=c++11 compatibility.
+- Added support for pseudo-stack heap profiling via a callback to retrieve a
+ simulated stack from the embedding application.
+- Inserted spaces around PRIx64, SCNx64 and friends, for c++11 compatibility.
diff --git a/chromium/third_party/tcmalloc/chromium/src/OWNERS b/chromium/third_party/tcmalloc/chromium/src/OWNERS
new file mode 100644
index 00000000000..520dd608efe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/OWNERS
@@ -0,0 +1,4 @@
+per-file heap-profile*=dmikurube@chromium.org
+per-file heap-profile*=glider@chromium.org
+per-file deep-heap-profile*=dmikurube@chromium.org
+per-file deep-heap-profile*=glider@chromium.org
diff --git a/chromium/third_party/tcmalloc/chromium/src/addressmap-inl.h b/chromium/third_party/tcmalloc/chromium/src/addressmap-inl.h
new file mode 100644
index 00000000000..b122f17b857
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/addressmap-inl.h
@@ -0,0 +1,421 @@
+// 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 <stddef.h>
+#include <string.h>
+#if defined HAVE_STDINT_H
+#include <stdint.h> // to get uint16_t (ISO naming madness)
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h> // another place uint16_t might be defined
+#else
+#include <sys/types.h> // 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 Value>
+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 <key,value> 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<class Type>
+ 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<uint32_t>(x) * kHashMultiplier;
+ return static_cast<int>(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<Cluster>(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 <class T> T* New(int num) {
+ void* ptr = (*alloc_)(sizeof(Object) + num*sizeof(T));
+ memset(ptr, 0, sizeof(Object) + num*sizeof(T));
+ Object* obj = reinterpret_cast<Object*>(ptr);
+ obj->next = allocated_;
+ allocated_ = obj;
+ return reinterpret_cast<T*>(reinterpret_cast<Object*>(ptr) + 1);
+ }
+};
+
+// More implementation details follow:
+
+template <class Value>
+AddressMap<Value>::AddressMap(Allocator alloc, DeAllocator dealloc)
+ : free_(NULL),
+ alloc_(alloc),
+ dealloc_(dealloc),
+ allocated_(NULL) {
+ hashtable_ = New<Cluster*>(kHashSize);
+}
+
+template <class Value>
+AddressMap<Value>::~AddressMap() {
+ // De-allocate all of the objects we allocated
+ for (Object* obj = allocated_; obj != NULL; /**/) {
+ Object* next = obj->next;
+ (*dealloc_)(obj);
+ obj = next;
+ }
+}
+
+template <class Value>
+inline const Value* AddressMap<Value>::Find(Key key) const {
+ return const_cast<AddressMap*>(this)->FindMutable(key);
+}
+
+template <class Value>
+inline Value* AddressMap<Value>::FindMutable(Key key) {
+ const Number num = reinterpret_cast<Number>(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 <class Value>
+void AddressMap<Value>::Insert(Key key, Value value) {
+ const Number num = reinterpret_cast<Number>(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<Entry>(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 <class Value>
+bool AddressMap<Value>::FindAndRemove(Key key, Value* removed_value) {
+ const Number num = reinterpret_cast<Number>(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 <class Value>
+const Value* AddressMap<Value>::FindInside(ValueSizeFunc size_func,
+ size_t max_size,
+ Key key,
+ Key* res_key) {
+ const Number key_num = reinterpret_cast<Number>(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<Number>(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 <class Value>
+template <class Type>
+inline void AddressMap<Value>::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/chromium/third_party/tcmalloc/chromium/src/base/abort.cc b/chromium/third_party/tcmalloc/chromium/src/base/abort.cc
new file mode 100755
index 00000000000..89c9ab440cd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/abort.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/abort.h"
+
+#include "base/basictypes.h"
+
+namespace tcmalloc {
+
+// Try not to inline so we can find Abort() call from stack trace.
+ATTRIBUTE_NOINLINE void Abort() {
+ // Make a segmentation fault to force abort. Writing to a specific address
+ // so it's easier to find on crash stacks.
+ *(reinterpret_cast<volatile char*>(NULL) + 57) = 0x21;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/abort.h b/chromium/third_party/tcmalloc/chromium/src/base/abort.h
new file mode 100644
index 00000000000..18ec319ca56
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/abort.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ---
+// On some platforms abort() is implemented in a way that Chrome's crash
+// reporter treats it as a normal exit. See issue:
+// http://code.google.com/p/chromium/issues/detail?id=118665
+// So we replace abort with a segmentation fault, then crash reporter can
+// always detect.
+
+#ifndef BASE_ABORT_H_
+#define BASE_ABORT_H_
+
+namespace tcmalloc {
+void Abort();
+} // namespace tcmalloc
+
+#endif // BASE_ABORT_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h b/chromium/third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h
new file mode 100644
index 00000000000..a47e6bbd2b1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h
@@ -0,0 +1,79 @@
+// 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_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/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h
new file mode 100644
index 00000000000..e083f8d3730
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h
@@ -0,0 +1,235 @@
+// 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 and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
+#define BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
+
+#include <stdio.h>
+#include "base/abort.h"
+#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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ for (;;) {
+ // Atomic exchange the old value with an incremented one.
+ Atomic32 old_value = *ptr;
+ Atomic32 new_value = old_value + increment;
+ if (pLinuxKernelCmpxchg(old_value, new_value,
+ const_cast<Atomic32*>(ptr)) == 0) {
+ // The exchange took place as expected.
+ return new_value;
+ }
+ // Otherwise, *ptr changed mid-loop and we need to retry.
+ }
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+
+// 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);
+ tcmalloc::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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ return 0;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NotImplementedFatalError("NoBarrier_Store");
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NotImplementedFatalError("Acquire_Store64");
+}
+
+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 Release_Load(volatile const Atomic64* ptr) {
+ NotImplementedFatalError("Atomic64 Release_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/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h
new file mode 100644
index 00000000000..dc069870d89
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h
@@ -0,0 +1,369 @@
+// 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 <stdio.h>
+#include <stdlib.h>
+#include "base/abort.h"
+#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 Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 tmp, res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrex %1, [%2]\n"
+ "add %1, %1, %3\n"
+ "strex %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (tmp), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+inline void MemoryBarrier() {
+ __asm__ __volatile__("dmb" : : : "memory");
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 tmp, res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrex %1, [%2]\n"
+ "add %1, %1, %3\n"
+ "dmb\n"
+ "strex %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (tmp), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ int store_failed;
+ Atomic64 res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrexd %1, [%2]\n"
+ "adds %Q1, %Q1, %Q3\n"
+ "adc %R1, %R1, %R3\n"
+ "strexd %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (store_failed), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ int store_failed;
+ Atomic64 res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrexd %1, [%2]\n"
+ "adds %Q1, %Q1, %Q3\n"
+ "adc %R1, %R1, %R3\n"
+ "dmb\n"
+ "strexd %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (store_failed), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+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);
+ tcmalloc::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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ 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 Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+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/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h
new file mode 100644
index 00000000000..7e49560dca1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h
@@ -0,0 +1,416 @@
+/* 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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+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<Atomic32*>(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<Atomic32*>(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\
+ cmpw 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<Atomic64*>(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<Atomic64*>(ptr)));
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
+}
+
+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<Atomic64*>(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<Atomic64*>(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 Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+ // 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();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+ // 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();
+ return *ptr;
+}
+
+#ifdef __PPC64__
+
+// 64-bit Versions.
+
+inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+ // 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();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+ // 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();
+ return *ptr;
+}
+
+#endif
+
+} // namespace base::subtle
+} // namespace base
+
+#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h
new file mode 100644
index 00000000000..430b9ee0bb4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h
@@ -0,0 +1,359 @@
+/* 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 <libkern/OSAtomic.h>
+
+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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+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<Atomic32*>(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 Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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<Atomic64*>(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<Atomic64*>(ptr)));
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
+}
+
+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<Atomic64*>(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 Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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 Release_Load(volatile const Atomic64 *ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+#endif // __LP64__
+
+} // namespace base::subtle
+} // namespace base
+
+#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h
new file mode 100644
index 00000000000..6a38bad559f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h
@@ -0,0 +1,502 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include "base/abort.h"
+#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, <windows.h> and <intrin.h> 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<LONG*>(ptr), newval, oldval);
+}
+inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) {
+ return ::InterlockedExchange(const_cast<LONG*>(ptr), newval);
+}
+inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) {
+ return ::InterlockedExchangeAdd(const_cast<LONG*>(ptr), increment);
+}
+
+#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0
+// Unfortunately, in some environments, <windows.h> and <intrin.h>
+// 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<volatile LONG*>(ptr),
+ static_cast<LONG>(new_value),
+ static_cast<LONG>(old_value));
+ return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ LONG result = FastInterlockedExchange(
+ reinterpret_cast<volatile LONG*>(ptr),
+ static_cast<LONG>(new_value));
+ return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return FastInterlockedExchangeAdd(
+ reinterpret_cast<volatile LONG*>(ptr),
+ static_cast<LONG>(increment)) + increment;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+} // 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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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<PVOID*>(ptr),
+ newval, oldval);
+}
+inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) {
+ return ::InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval);
+}
+inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr,
+ LONGLONG increment) {
+ return ::InterlockedExchangeAdd64(const_cast<LONGLONG*>(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<PVOID*>(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<PVOID*>(ptr), newval);
+}
+
+LONGLONG _InterlockedExchangeAdd64(volatile LONGLONG* ptr, LONGLONG increment);
+#pragma intrinsic(_InterlockedExchangeAdd64)
+inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr,
+ LONGLONG increment) {
+ return _InterlockedExchangeAdd64(const_cast<LONGLONG*>(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<volatile PVOID*>(ptr),
+ reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
+ return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ PVOID result = FastInterlockedExchangePointer(
+ reinterpret_cast<volatile PVOID*>(ptr),
+ reinterpret_cast<PVOID>(new_value));
+ return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return FastInterlockedExchangeAdd64(
+ reinterpret_cast<volatile LONGLONG*>(ptr),
+ static_cast<LONGLONG>(increment)) + increment;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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);
+ tcmalloc::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 Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+#if 0 // Not implemented
+ Atomic64 temp = increment;
+ __asm__ __volatile__(
+ "0:\n\t"
+ "movl (%3), %%ebx\n\t" // Move 64-bit increment into
+ "movl 4(%3), %%ecx\n\t" // ecx:ebx
+ "movl (%2), %%eax\n\t" // Read contents of ptr into
+ "movl 4(%2), %%edx\n\t" // edx:eax
+ "add %%eax, %%ebx\n\t" // sum => ecx:ebx
+ "adc %%edx, %%ecx\n\t" // edx:eax still has old *ptr
+ "lock; cmpxchg8b (%2)\n\t"// Attempt cmpxchg; if *ptr
+ "jnz 0b\n\t" // is no longer edx:eax, loop
+ : "=A"(temp), "+m"(*ptr)
+ : "D" (ptr), "S" (&increment)
+ : "memory", "%ebx", "%ecx");
+ // temp now contains the previous value of *ptr
+ return temp + increment;
+#else
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+#endif
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+#if 0 // Not implemented
+ Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return new_val;
+#else
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ return 0;
+#endif
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+#if 0 // Not implemented
+ __asm {
+ mov mm0, value; // Use mmx reg for 64-bit atomic moves
+ mov ptr, mm0;
+ emms; // Empty mmx state to enable FP registers
+ }
+#else
+ NotImplementedFatalError("NoBarrier_Store");
+#endif
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+#if 0 // Not implemented
+ Atomic64 value;
+ __asm {
+ mov mm0, ptr; // Use mmx reg for 64-bit atomic moves
+ mov value, mm0;
+ emms; // Empty mmx state to enable FP registers
+ }
+ return value;
+#else
+ NotImplementedFatalError("NoBarrier_Store");
+ return 0;
+#endif
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ Atomic64 value = NoBarrier_Load(ptr);
+ return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+#endif // defined(_WIN64) || defined(__MINGW64__)
+
+
+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/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc
new file mode 100644
index 00000000000..4f75d4724c0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc
@@ -0,0 +1,125 @@
+/* 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 <string.h>
+
+// 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, // bug can't exist before process spawns multiple threads
+ 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;
+ }
+
+ // Opteron Rev E has a bug in which on very rare occasions a locked
+ // instruction doesn't act as a read-acquire barrier if followed by a
+ // non-locked read-modify-write instruction. Rev F has this bug in
+ // pre-release versions, but not in versions released to customers,
+ // so we test only for Rev E, which is family 15, model 32..63 inclusive.
+ if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD
+ family == 15 &&
+ 32 <= model && model <= 63) {
+ AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
+ } else {
+ AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
+ }
+
+ // 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/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h
new file mode 100644
index 00000000000..c34aa5c08fc
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h
@@ -0,0 +1,428 @@
+/* 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_
+
+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_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
+ // after acquire compare-and-swap.
+ bool has_sse2; // Processor has SSE2.
+ bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
+};
+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 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 temp = increment;
+ __asm__ __volatile__("lock; xaddl %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now holds the old value of *ptr
+ return temp + increment;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 temp = increment;
+ __asm__ __volatile__("lock; xaddl %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now holds the old value of *ptr
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return temp + increment;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ 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");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+#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;
+ NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII
+ }
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+ *ptr = value;
+ __asm__ __volatile__("mfence" : : : "memory");
+ } else {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier on PIII
+ }
+}
+#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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 temp = increment;
+ __asm__ __volatile__("lock; xaddq %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now contains the previous value of *ptr
+ return temp + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 temp = increment;
+ __asm__ __volatile__("lock; xaddq %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now contains the previous value of *ptr
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return temp + increment;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 old_val, new_val;
+
+ do {
+ old_val = *ptr;
+ new_val = old_val + increment;
+ } while (__sync_val_compare_and_swap(ptr, old_val, new_val) != old_val);
+
+ return old_val + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return 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 Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+#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);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ 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/chromium/third_party/tcmalloc/chromium/src/base/atomicops.h b/chromium/third_party/tcmalloc/chromium/src/base/atomicops.h
new file mode 100644
index 00000000000..17e8a27f0ca
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/atomicops.h
@@ -0,0 +1,391 @@
+/* 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.
+//
+// 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 <config.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#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"
+
+// TODO(csilvers): match piii, not just __i386. Also, match k8
+#if 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(_WIN32)
+#include "base/atomicops-internals-windows.h"
+#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
+#include "base/atomicops-internals-x86.h"
+#elif defined(__linux__) && defined(__PPC__)
+#include "base/atomicops-internals-linuxppc.h"
+#else
+// Assume x86 for now. If you need to support a new architecture and
+// don't know how to implement atomic ops, you can probably get away
+// with using pthreads, since atomicops is only used by spinlock.h/cc
+//#error You need to implement atomic operations for this architecture
+#include "base/atomicops-internals-x86.h"
+#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<volatile AtomicWordCastType*>(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<volatile AtomicWordCastType*>(ptr), new_value);
+}
+
+// Atomically increment *ptr by "increment". Returns the new value of
+// *ptr with the increment applied. This routine implies no memory
+// barriers.
+inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
+ AtomicWord increment) {
+ return NoBarrier_AtomicIncrement(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
+}
+
+inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
+ AtomicWord increment) {
+ return Barrier_AtomicIncrement(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
+}
+
+// ------------------------------------------------------------------------
+// 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.
+// ------------------------------------------------------------------------
+inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
+ AtomicWord old_value,
+ AtomicWord new_value) {
+ return base::subtle::Acquire_CompareAndSwap(
+ reinterpret_cast<volatile AtomicWordCastType*>(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<volatile AtomicWordCastType*>(ptr),
+ old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
+ NoBarrier_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Acquire_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Release_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
+ return NoBarrier_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
+}
+
+inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Acquire_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
+}
+
+inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Release_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(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 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment);
+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 Acquire_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);
+Atomic32 Release_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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+
+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 Acquire_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);
+Atomic64 Release_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 Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Acquire_Store(ptr, 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);
+}
+
+inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Release_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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ base::subtle::Acquire_Store(ptr, 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);
+}
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ return base::subtle::Release_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 Acquire_Store(
+ volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
+ base::subtle::Acquire_Store(ptr, 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);
+}
+inline base::subtle::Atomic64 Release_Load(
+ volatile const base::subtle::Atomic64* ptr) {
+ return base::subtle::Release_Load(ptr);
+}
+
+#endif // BASE_HAS_ATOMIC64
+
+#endif // THREAD_ATOMICOPS_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/basictypes.h b/chromium/third_party/tcmalloc/chromium/src/base/basictypes.h
new file mode 100644
index 00000000000..75b7b5ae777
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/basictypes.h
@@ -0,0 +1,357 @@
+// 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 <config.h>
+#include <string.h> // for memcpy()
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // 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 <inttypes.h> // uint16_t might be here; PRId64 too.
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // to get uint16_t (ISO naming madness)
+#endif
+#include <sys/types.h> // 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 = ( ((( int64) 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<uintptr_t>(pthreadt)
+#else
+#define PRINTABLE_PTHREAD(pthreadt) pthreadt
+#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<bool(expr)>
+//
+// 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 <bool>
+struct CompileAssert {
+};
+
+#define COMPILE_ASSERT(expr, msg) \
+ typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+#define arraysize(a) (sizeof(a) / sizeof(*(a)))
+
+#define OFFSETOF_MEMBER(strct, field) \
+ (reinterpret_cast<char*>(&reinterpret_cast<strct*>(16)->field) - \
+ reinterpret_cast<char*>(16))
+
+// bit_cast<Dest,Source> implements the equivalent of
+// "*reinterpret_cast<Dest*>(&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 <class Dest, class Source>
+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;
+}
+
+#ifdef HAVE___ATTRIBUTE__
+# define ATTRIBUTE_WEAK __attribute__((weak))
+# define ATTRIBUTE_NOINLINE __attribute__((noinline))
+#else
+# define ATTRIBUTE_WEAK
+# define ATTRIBUTE_NOINLINE
+#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)))
+
+ // Weak section declaration to be used as a global declaration
+ // for ATTRIBUTE_SECTION_START|STOP(name) to compile and link
+ // even without functions with ATTRIBUTE_SECTION(name).
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name) \
+ extern char __start_##name[] ATTRIBUTE_WEAK; \
+ extern char __stop_##name[] ATTRIBUTE_WEAK
+# define INIT_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
+
+ // Return void* pointers to start/end of a section of code with functions
+ // having ATTRIBUTE_SECTION(name), or 0 if no such function exists.
+ // One must DECLARE_ATTRIBUTE_SECTION(name) for this to compile and link.
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#elif defined(HAVE___ATTRIBUTE__) && defined(__MACH__)
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__TEXT, " #name)))
+
+#include <mach-o/getsect.h>
+#include <mach-o/dyld.h>
+class AssignAttributeStartEnd {
+ public:
+ AssignAttributeStartEnd(const char* name, char** pstart, char** pend) {
+ // Find out what dynamic library name is defined in
+ if (_dyld_present()) {
+ for (int i = _dyld_image_count() - 1; i >= 0; --i) {
+ const mach_header* hdr = _dyld_get_image_header(i);
+#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<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#else // not HAVE___ATTRIBUTE__ && __ELF__, nor HAVE___ATTRIBUTE__ && __MACH__
+# define ATTRIBUTE_SECTION(name)
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name)
+# define INIT_ATTRIBUTE_SECTION_VARS(name)
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name)
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0))
+
+#endif // HAVE___ATTRIBUTE__ and __ELF__ or __MACH__
+
+#if defined(HAVE___ATTRIBUTE__) && (defined(__i386__) || defined(__x86_64__))
+# define CACHELINE_ALIGNED __attribute__((aligned(64)))
+#else
+# define CACHELINE_ALIGNED
+#endif // defined(HAVE___ATTRIBUTE__) && (__i386__ || __x86_64__)
+
+
+// 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/chromium/third_party/tcmalloc/chromium/src/base/commandlineflags.h b/chromium/third_party/tcmalloc/chromium/src/base/commandlineflags.h
new file mode 100644
index 00000000000..649b95fa450
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/commandlineflags.h
@@ -0,0 +1,181 @@
+// 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 <config.h>
+#include <string>
+#include <string.h> // for memchr
+#include <stdlib.h> // for getenv
+#include "base/basictypes.h"
+
+#if defined(__ANDROID__) || defined(ANDROID)
+#include <sys/system_properties.h>
+#endif
+
+#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
+
+// 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.
+// They are functions in Android because __system_property_get() doesn't
+// return a string.
+
+#if defined(__ANDROID__) || defined(ANDROID)
+
+// Returns a pointer to a static variable. The string pointed by the returned
+// pointer must not be modified.
+inline const char* const EnvToString(const char* envname, const char* dflt) {
+ static char system_property_value[PROP_VALUE_MAX];
+ if (__system_property_get(envname, system_property_value) > 0)
+ return system_property_value;
+ return dflt;
+}
+
+inline bool EnvToBool(const char* envname, bool dflt) {
+ static const char kTrueValues[] = "tTyY1";
+ char system_property_value[PROP_VALUE_MAX];
+ if (__system_property_get(envname, system_property_value) > 0)
+ return memchr(kTrueValues, system_property_value[0], sizeof(kTrueValues));
+ return dflt;
+}
+
+inline int EnvToInt(const char* envname, int dflt) {
+ char system_property_value[PROP_VALUE_MAX];
+ if (__system_property_get(envname, system_property_value) > 0)
+ return strtol(system_property_value, NULL, 10);
+ return dflt;
+}
+
+inline int64 EnvToInt64(const char* envname, int64 dflt) {
+ char system_property_value[PROP_VALUE_MAX];
+ if (__system_property_get(envname, system_property_value) > 0)
+ return strtoll(system_property_value, NULL, 10);
+ return dflt;
+}
+
+inline double EnvToDouble(const char* envname, double dflt) {
+ char system_property_value[PROP_VALUE_MAX];
+ if (__system_property_get(envname, system_property_value) > 0)
+ return strtod(system_property_value, NULL);
+ return dflt;
+}
+
+#else // defined(__ANDROID__) || defined(ANDROID)
+
+#define EnvToString(envname, dflt) \
+ (!getenv(envname) ? (dflt) : getenv(envname))
+
+#define EnvToBool(envname, dflt) \
+ (!getenv(envname) ? (dflt) : memchr("tTyY1\0", getenv(envname)[0], 6) != NULL)
+
+#define EnvToInt(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtol(getenv(envname), NULL, 10))
+
+#define EnvToInt64(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtoll(getenv(envname), NULL, 10))
+
+#define EnvToDouble(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtod(getenv(envname), NULL))
+
+#endif // defined(__ANDROID__) || defined(ANDROID)
+
+#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/cycleclock.h b/chromium/third_party/tcmalloc/chromium/src/base/cycleclock.h
new file mode 100644
index 00000000000..0ce1638612c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/cycleclock.h
@@ -0,0 +1,165 @@
+// 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.
+
+// ----------------------------------------------------------------------
+// CycleClock
+// A CycleClock tells you the current time in Cycles. The "time"
+// is actually time since power-on. This is like time() but doesn't
+// involve a system call and is much more precise.
+//
+// NOTE: Not all cpu/platform/kernel combinations guarantee that this
+// clock increments at a constant rate or is synchronized across all logical
+// cpus in a system.
+//
+// Also, in some out of order CPU implementations, the CycleClock is not
+// serializing. So if you're trying to count at cycles granularity, your
+// data might be inaccurate due to out of order instruction execution.
+// ----------------------------------------------------------------------
+
+#ifndef GOOGLE_BASE_CYCLECLOCK_H_
+#define GOOGLE_BASE_CYCLECLOCK_H_
+
+#include "base/basictypes.h" // make sure we get the def for int64
+#include "base/arm_instruction_set_select.h"
+// base/sysinfo.h is really big and we don't want to include it unless
+// it is necessary.
+#if defined(__arm__) || defined(__mips__)
+# include "base/sysinfo.h"
+#endif
+#if defined(__MACH__) && defined(__APPLE__)
+# include <mach/mach_time.h>
+#endif
+// For MSVC, we want to use '_asm rdtsc' when possible (since it works
+// with even ancient MSVC compilers), and when not possible the
+// __rdtsc intrinsic, declared in <intrin.h>. Unfortunately, in some
+// environments, <windows.h> and <intrin.h> have conflicting
+// declarations of some other intrinsics, breaking compilation.
+// Therefore, we simply declare __rdtsc ourselves. See also
+// http://connect.microsoft.com/VisualStudio/feedback/details/262047
+#if defined(_MSC_VER) && !defined(_M_IX86)
+extern "C" uint64 __rdtsc();
+#pragma intrinsic(__rdtsc)
+#endif
+#if defined(ARMV3) || defined(__mips__)
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#endif
+
+// NOTE: only i386 and x86_64 have been well tested.
+// PPC, sparc, alpha, and ia64 are based on
+// http://peter.kuscsik.com/wordpress/?p=14
+// with modifications by m3b. See also
+// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
+struct CycleClock {
+ // This should return the number of cycles since power-on. Thread-safe.
+ static inline int64 Now() {
+#if defined(__MACH__) && defined(__APPLE__)
+ // this goes at the top because we need ALL Macs, regardless of
+ // architecture, to return the number of "mach time units" that
+ // have passed since startup. See sysinfo.cc where
+ // InitializeSystemInfo() sets the supposed cpu clock frequency of
+ // macs to the number of mach time units per second, not actual
+ // CPU clock frequency (which can change in the face of CPU
+ // frequency scaling). Also note that when the Mac sleeps, this
+ // counter pauses; it does not continue counting, nor does it
+ // reset to zero.
+ return mach_absolute_time();
+#elif defined(__i386__)
+ int64 ret;
+ __asm__ volatile ("rdtsc" : "=A" (ret) );
+ return ret;
+#elif defined(__x86_64__) || defined(__amd64__)
+ uint64 low, high;
+ __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
+ return (high << 32) | low;
+#elif defined(__powerpc__) || defined(__ppc__)
+ // This returns a time-base, which is not always precisely a cycle-count.
+ int64 tbl, tbu0, tbu1;
+ asm("mftbu %0" : "=r" (tbu0));
+ asm("mftb %0" : "=r" (tbl));
+ asm("mftbu %0" : "=r" (tbu1));
+ tbl &= -static_cast<int64>(tbu0 == tbu1);
+ // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage)
+ return (tbu1 << 32) | tbl;
+#elif defined(__sparc__)
+ int64 tick;
+ asm(".byte 0x83, 0x41, 0x00, 0x00");
+ asm("mov %%g1, %0" : "=r" (tick));
+ return tick;
+#elif defined(__ia64__)
+ int64 itc;
+ asm("mov %0 = ar.itc" : "=r" (itc));
+ return itc;
+#elif defined(_MSC_VER) && defined(_M_IX86)
+ // Older MSVC compilers (like 7.x) don't seem to support the
+ // __rdtsc intrinsic properly, so I prefer to use _asm instead
+ // when I know it will work. Otherwise, I'll use __rdtsc and hope
+ // the code is being compiled with a non-ancient compiler.
+ _asm rdtsc
+#elif defined(_MSC_VER)
+ return __rdtsc();
+#elif defined(ARMV3)
+#if defined(ARMV6) // V6 is the earliest arch that has a standard cyclecount
+ uint32 pmccntr;
+ uint32 pmuseren;
+ uint32 pmcntenset;
+ // Read the user mode perf monitor counter access permissions.
+ asm volatile ("mrc p15, 0, %0, c9, c14, 0" : "=r" (pmuseren));
+ if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
+ asm volatile ("mrc p15, 0, %0, c9, c12, 1" : "=r" (pmcntenset));
+ if (pmcntenset & 0x80000000ul) { // Is it counting?
+ asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (pmccntr));
+ // The counter is set up to count every 64th cycle
+ return static_cast<int64>(pmccntr) * 64; // Should optimize to << 6
+ }
+ }
+#endif
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
+ * CyclesPerSecond());
+#elif defined(__mips__)
+ // mips apparently only allows rdtsc for superusers, so we fall
+ // back to gettimeofday. It's possible clock_gettime would be better.
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
+ * CyclesPerSecond());
+#else
+// The soft failover to a generic implementation is automatic only for ARM.
+// For other platforms the developer is expected to make an attempt to create
+// a fast implementation and use generic version if nothing better is available.
+#error You need to define CycleTimer for your O/S and CPU
+#endif
+ }
+};
+
+
+#endif // GOOGLE_BASE_CYCLECLOCK_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.c b/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.c
new file mode 100644
index 00000000000..c8b61bed2d8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.c
@@ -0,0 +1,190 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "base/dynamic_annotations.h"
+
+#ifdef __GNUC__
+/* valgrind.h uses gcc extensions so it won't build with other compilers */
+# ifdef HAVE_VALGRIND_H /* prefer the user's copy if they have it */
+# include <valgrind.h>
+# else /* otherwise just use the copy that we have */
+# include "third_party/valgrind.h"
+# endif
+#endif
+
+/* Compiler-based ThreadSanitizer defines
+ DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
+ and provides its own definitions of the functions. */
+
+#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
+# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
+#endif
+
+/* Each function is empty and called (via a macro) only in debug mode.
+ The arguments are captured by dynamic tools at runtime. */
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1 \
+ && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
+
+void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock){}
+void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock){}
+void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w){}
+void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w){}
+void AnnotateBarrierInit(const char *file, int line,
+ const volatile void *barrier, long count,
+ long reinitialization_allowed) {}
+void AnnotateBarrierWaitBefore(const char *file, int line,
+ const volatile void *barrier) {}
+void AnnotateBarrierWaitAfter(const char *file, int line,
+ const volatile void *barrier) {}
+void AnnotateBarrierDestroy(const char *file, int line,
+ const volatile void *barrier) {}
+
+void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock){}
+void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv){}
+void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv){}
+void AnnotatePublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size){}
+void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size){}
+void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotateNewMemory(const char *file, int line,
+ const volatile void *mem,
+ long size){}
+void AnnotateExpectRace(const char *file, int line,
+ const volatile void *mem,
+ const char *description){}
+void AnnotateBenignRace(const char *file, int line,
+ const volatile void *mem,
+ const char *description){}
+void AnnotateBenignRaceSized(const char *file, int line,
+ const volatile void *mem,
+ long size,
+ const char *description) {}
+void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu){}
+void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg){}
+void AnnotateThreadName(const char *file, int line,
+ const char *name){}
+void AnnotateIgnoreReadsBegin(const char *file, int line){}
+void AnnotateIgnoreReadsEnd(const char *file, int line){}
+void AnnotateIgnoreWritesBegin(const char *file, int line){}
+void AnnotateIgnoreWritesEnd(const char *file, int line){}
+void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
+void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg){}
+void AnnotateFlushState(const char *file, int line){}
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1
+ && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
+
+#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
+
+static int GetRunningOnValgrind(void) {
+#ifdef RUNNING_ON_VALGRIND
+ if (RUNNING_ON_VALGRIND) return 1;
+#endif
+#ifdef _MSC_VER
+ /* Visual Studio can complain about getenv, so use a windows equivalent. */
+ char value[100] = "1"; /* something that is not "0" */
+ int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND",
+ value, sizeof(value));
+ /* value will remain "1" if the called failed for some reason. */
+ return (res > 0 && strcmp(value, "0") != 0);
+#else
+ /* TODO(csilvers): use GetenvBeforeMain() instead? Will need to
+ * change it to be extern "C".
+ */
+ char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
+ if (running_on_valgrind_str) {
+ return strcmp(running_on_valgrind_str, "0") != 0;
+ }
+ return 0;
+#endif
+}
+
+/* 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;
+ /* C doesn't have thread-safe initialization of statics, and we
+ don't want to depend on pthread_once here, so hack it. */
+ ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
+ if (local_running_on_valgrind == -1)
+ running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
+ return local_running_on_valgrind;
+}
+
+#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
+
+/* See the comments in dynamic_annotations.h */
+double ValgrindSlowdown(void) {
+ /* Same initialization hack as in RunningOnValgrind(). */
+ static volatile double slowdown = 0.0;
+ double local_slowdown = slowdown;
+ ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
+ if (RunningOnValgrind() == 0) {
+ return 1.0;
+ }
+ if (local_slowdown == 0.0) {
+ char *env = getenv("VALGRIND_SLOWDOWN");
+ slowdown = local_slowdown = env ? atof(env) : 50.0;
+ }
+ return local_slowdown;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.h b/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.h
new file mode 100644
index 00000000000..4669315ced3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/dynamic_annotations.h
@@ -0,0 +1,627 @@
+/* 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_
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+# define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing condition variables such as CondVar,
+ using conditional critical sections (Await/LockWhen) and when constructing
+ user-defined synchronization mechanisms.
+
+ The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
+ be used to define happens-before arcs in user-defined synchronization
+ mechanisms: the race detector will infer an arc from the former to the
+ latter when they share the same argument pointer.
+
+ Example 1 (reference counting):
+
+ void Unref() {
+ ANNOTATE_HAPPENS_BEFORE(&refcount_);
+ if (AtomicDecrementByOne(&refcount_) == 0) {
+ ANNOTATE_HAPPENS_AFTER(&refcount_);
+ delete this;
+ }
+ }
+
+ Example 2 (message queue):
+
+ void MyQueue::Put(Type *e) {
+ MutexLock lock(&mu_);
+ ANNOTATE_HAPPENS_BEFORE(e);
+ PutElementIntoMyQueue(e);
+ }
+
+ Type *MyQueue::Get() {
+ MutexLock lock(&mu_);
+ Type *e = GetElementFromMyQueue();
+ ANNOTATE_HAPPENS_AFTER(e);
+ return e;
+ }
+
+ Note: when possible, please use the existing reference counting and message
+ queue implementations instead of inventing new ones. */
+
+ /* Report that wait on the condition variable at address "cv" has succeeded
+ and the lock at address "lock" is held. */
+ #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
+ AnnotateCondVarWait(__FILE__, __LINE__, cv, lock)
+
+ /* Report that wait on the condition variable at "cv" has succeeded. Variant
+ w/o lock. */
+ #define ANNOTATE_CONDVAR_WAIT(cv) \
+ AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL)
+
+ /* Report that we are about to signal on the condition variable at address
+ "cv". */
+ #define ANNOTATE_CONDVAR_SIGNAL(cv) \
+ AnnotateCondVarSignal(__FILE__, __LINE__, cv)
+
+ /* Report that we are about to signal_all on the condition variable at "cv". */
+ #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
+ AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
+
+ /* Annotations for user-defined synchronization mechanisms. */
+ #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj)
+ #define ANNOTATE_HAPPENS_AFTER(obj) ANNOTATE_CONDVAR_WAIT(obj)
+
+ /* Report that the bytes in the range [pointer, pointer+size) are about
+ to be published safely. The race checker will create a happens-before
+ arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
+ subsequent accesses to this memory.
+ Note: this annotation may not work properly if the race detector uses
+ sampling, i.e. does not observe all memory accesses.
+ */
+ #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
+ AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
+
+ /* DEPRECATED. Don't use it. */
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
+ AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
+
+ /* DEPRECATED. Don't use it. */
+ #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
+ do { \
+ ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
+ ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
+ } while (0)
+
+ /* Instruct the tool to create a happens-before arc between mu->Unlock() and
+ mu->Lock(). This annotation may slow down the race detector and hide real
+ races. Normally it is used only when it would be difficult to annotate each
+ of the mutex's critical sections individually using the annotations above.
+ This annotation makes sense only for hybrid race detectors. For pure
+ happens-before detectors this is a no-op. For more details see
+ http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
+ #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
+ AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+
+ /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
+ #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
+ AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+
+ /* -------------------------------------------------------------
+ Annotations useful when defining memory allocators, or when memory that
+ was protected in one way starts to be protected in another. */
+
+ /* Report that a new memory at "address" of size "size" has been allocated.
+ This might be used when the memory has been retrieved from a free list and
+ is about to be reused, or when a the locking discipline for a variable
+ changes. */
+ #define ANNOTATE_NEW_MEMORY(address, size) \
+ AnnotateNewMemory(__FILE__, __LINE__, address, size)
+
+ /* -------------------------------------------------------------
+ Annotations useful when defining FIFO queues that transfer data between
+ threads. */
+
+ /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
+ address "pcq" has been created. The ANNOTATE_PCQ_* annotations
+ should be used only for FIFO queues. For non-FIFO queues use
+ ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
+ #define ANNOTATE_PCQ_CREATE(pcq) \
+ AnnotatePCQCreate(__FILE__, __LINE__, pcq)
+
+ /* Report that the queue at address "pcq" is about to be destroyed. */
+ #define ANNOTATE_PCQ_DESTROY(pcq) \
+ AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
+
+ /* Report that we are about to put an element into a FIFO queue at address
+ "pcq". */
+ #define ANNOTATE_PCQ_PUT(pcq) \
+ AnnotatePCQPut(__FILE__, __LINE__, pcq)
+
+ /* Report that we've just got an element from a FIFO queue at address "pcq". */
+ #define ANNOTATE_PCQ_GET(pcq) \
+ AnnotatePCQGet(__FILE__, __LINE__, pcq)
+
+ /* -------------------------------------------------------------
+ Annotations that suppress errors. It is usually better to express the
+ program's synchronization using the other annotations, but these can
+ be used when all else fails. */
+
+ /* Report that we may have a benign race at "pointer", with size
+ "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
+ point where "pointer" has been allocated, preferably close to the point
+ where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
+ #define ANNOTATE_BENIGN_RACE(pointer, description) \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
+ sizeof(*(pointer)), description)
+
+ /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
+ the memory range [address, address+size). */
+ #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
+
+ /* Request the analysis tool to ignore all reads in the current thread
+ until ANNOTATE_IGNORE_READS_END is called.
+ Useful to ignore intentional racey reads, while still checking
+ other reads and all writes.
+ See also ANNOTATE_UNPROTECTED_READ. */
+ #define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+ /* Stop ignoring reads. */
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
+ /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+ /* Stop ignoring writes. */
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+
+ /* Start ignoring all memory accesses (reads and writes). */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do {\
+ ANNOTATE_IGNORE_READS_BEGIN();\
+ ANNOTATE_IGNORE_WRITES_BEGIN();\
+ }while(0)\
+
+ /* Stop ignoring all memory accesses. */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do {\
+ ANNOTATE_IGNORE_WRITES_END();\
+ ANNOTATE_IGNORE_READS_END();\
+ }while(0)\
+
+ /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
+ This annotation could be useful if you want to skip expensive race analysis
+ during some period of program execution, e.g. during initialization. */
+ #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
+
+ /* -------------------------------------------------------------
+ Annotations useful for debugging. */
+
+ /* Request to trace every access to "address". */
+ #define ANNOTATE_TRACE_MEMORY(address) \
+ AnnotateTraceMemory(__FILE__, __LINE__, address)
+
+ /* Report the current thread name to a race detector. */
+ #define ANNOTATE_THREAD_NAME(name) \
+ AnnotateThreadName(__FILE__, __LINE__, name)
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing locks. They are not
+ normally needed by modules that merely use locks.
+ The "lock" argument is a pointer to the lock object. */
+
+ /* Report that a lock has been created at address "lock". */
+ #define ANNOTATE_RWLOCK_CREATE(lock) \
+ AnnotateRWLockCreate(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" is about to be destroyed. */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) \
+ AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" has been acquired.
+ is_w=1 for writer lock, is_w=0 for reader lock. */
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+
+ /* Report that the lock at address "lock" is about to be released. */
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing barriers. They are not
+ normally needed by modules that merely use barriers.
+ The "barrier" argument is a pointer to the barrier object. */
+
+ /* Report that the "barrier" has been initialized with initial "count".
+ If 'reinitialization_allowed' is true, initialization is allowed to happen
+ multiple times w/o calling barrier_destroy() */
+ #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
+ AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \
+ reinitialization_allowed)
+
+ /* Report that we are about to enter barrier_wait("barrier"). */
+ #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
+ AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier)
+
+ /* Report that we just exited barrier_wait("barrier"). */
+ #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
+ AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier)
+
+ /* Report that the "barrier" has been destroyed. */
+ #define ANNOTATE_BARRIER_DESTROY(barrier) \
+ AnnotateBarrierDestroy(__FILE__, __LINE__, barrier)
+
+ /* -------------------------------------------------------------
+ Annotations useful for testing race detectors. */
+
+ /* Report that we expect a race on the variable at "address".
+ Use only in unit tests for a race detector. */
+ #define ANNOTATE_EXPECT_RACE(address, description) \
+ AnnotateExpectRace(__FILE__, __LINE__, address, description)
+
+ /* A no-op. Insert where you like to test the interceptors. */
+ #define ANNOTATE_NO_OP(arg) \
+ AnnotateNoOp(__FILE__, __LINE__, arg)
+
+ /* Force the race detector to flush its state. The actual effect depends on
+ * the implementation of the detector. */
+ #define ANNOTATE_FLUSH_STATE() \
+ AnnotateFlushState(__FILE__, __LINE__)
+
+
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+ #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
+ #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
+ #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
+ #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
+ #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
+ #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
+ #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
+ #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
+ #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
+ #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
+ #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
+ #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_PCQ_CREATE(pcq) /* empty */
+ #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
+ #define ANNOTATE_PCQ_PUT(pcq) /* empty */
+ #define ANNOTATE_PCQ_GET(pcq) /* empty */
+ #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
+ #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
+ #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
+ #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
+ #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
+ #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
+ #define ANNOTATE_TRACE_MEMORY(arg) /* empty */
+ #define ANNOTATE_THREAD_NAME(name) /* empty */
+ #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_END() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_END() /* empty */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
+ #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
+ #define ANNOTATE_NO_OP(arg) /* empty */
+ #define ANNOTATE_FLUSH_STATE() /* empty */
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+/* Macro definitions for GCC attributes that allow static thread safety
+ analysis to recognize and use some of the dynamic annotations as
+ escape hatches.
+ TODO(lcwu): remove the check for __SUPPORT_DYN_ANNOTATION__ once the
+ default crosstool/GCC supports these GCC attributes. */
+
+#define ANNOTALYSIS_STATIC_INLINE
+#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY ;
+#define ANNOTALYSIS_IGNORE_READS_BEGIN
+#define ANNOTALYSIS_IGNORE_READS_END
+#define ANNOTALYSIS_IGNORE_WRITES_BEGIN
+#define ANNOTALYSIS_IGNORE_WRITES_END
+#define ANNOTALYSIS_UNPROTECTED_READ
+
+#if defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__)) && \
+ defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 0
+#define ANNOTALYSIS_ONLY 1
+#undef ANNOTALYSIS_STATIC_INLINE
+#define ANNOTALYSIS_STATIC_INLINE static inline
+#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY { (void)file; (void)line; }
+#endif
+
+/* Only emit attributes when annotalysis is enabled. */
+#if defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
+#undef ANNOTALYSIS_IGNORE_READS_BEGIN
+#define ANNOTALYSIS_IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
+#undef ANNOTALYSIS_IGNORE_READS_END
+#define ANNOTALYSIS_IGNORE_READS_END __attribute__ ((ignore_reads_end))
+#undef ANNOTALYSIS_IGNORE_WRITES_BEGIN
+#define ANNOTALYSIS_IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
+#undef ANNOTALYSIS_IGNORE_WRITES_END
+#define ANNOTALYSIS_IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
+#undef ANNOTALYSIS_UNPROTECTED_READ
+#define ANNOTALYSIS_UNPROTECTED_READ __attribute__ ((unprotected_read))
+#endif
+
+#endif // defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__))
+
+/* Use the macros above rather than using these functions directly. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock);
+void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock);
+void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w);
+void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w);
+void AnnotateBarrierInit(const char *file, int line,
+ const volatile void *barrier, long count,
+ long reinitialization_allowed);
+void AnnotateBarrierWaitBefore(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateBarrierWaitAfter(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateBarrierDestroy(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock);
+void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv);
+void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv);
+void AnnotatePublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq);
+void AnnotateNewMemory(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotateExpectRace(const char *file, int line,
+ const volatile void *address,
+ const char *description);
+void AnnotateBenignRace(const char *file, int line,
+ const volatile void *address,
+ const char *description);
+void AnnotateBenignRaceSized(const char *file, int line,
+ const volatile void *address,
+ long size,
+ const char *description);
+void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu);
+void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg);
+void AnnotateThreadName(const char *file, int line,
+ const char *name);
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreReadsBegin(const char *file, int line)
+ ANNOTALYSIS_IGNORE_READS_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreReadsEnd(const char *file, int line)
+ ANNOTALYSIS_IGNORE_READS_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreWritesBegin(const char *file, int line)
+ ANNOTALYSIS_IGNORE_WRITES_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreWritesEnd(const char *file, int line)
+ ANNOTALYSIS_IGNORE_WRITES_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+void AnnotateEnableRaceDetection(const char *file, int line, int enable);
+void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg);
+void AnnotateFlushState(const char *file, int line);
+
+/* 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);
+
+/* ValgrindSlowdown returns:
+ * 1.0, if (RunningOnValgrind() == 0)
+ * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
+ * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
+ This function can be used to scale timeout values:
+ EXAMPLE:
+ for (;;) {
+ DoExpensiveBackgroundTask();
+ SleepForSeconds(5 * ValgrindSlowdown());
+ }
+ */
+double ValgrindSlowdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
+
+ /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+
+ Instead of doing
+ ANNOTATE_IGNORE_READS_BEGIN();
+ ... = x;
+ ANNOTATE_IGNORE_READS_END();
+ one can use
+ ... = ANNOTATE_UNPROTECTED_READ(x); */
+ template <class T>
+ inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
+ ANNOTALYSIS_UNPROTECTED_READ {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+ }
+ /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
+ #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var ## _annotator { \
+ public: \
+ static_var ## _annotator() { \
+ ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
+ sizeof(static_var), \
+ # static_var ": " description); \
+ } \
+ }; \
+ static static_var ## _annotator the ## static_var ## _annotator;\
+ }
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+ #define ANNOTATE_UNPROTECTED_READ(x) (x)
+ #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+/* Annotalysis, a GCC based static analyzer, is able to understand and use
+ some of the dynamic annotations defined in this file. However, dynamic
+ annotations are usually disabled in the opt mode (to avoid additional
+ runtime overheads) while Annotalysis only works in the opt mode.
+ In order for Annotalysis to use these dynamic annotations when they
+ are disabled, we re-define these annotations here. Note that unlike the
+ original macro definitions above, these macros are expanded to calls to
+ static inline functions so that the compiler will be able to remove the
+ calls after the analysis. */
+
+#ifdef ANNOTALYSIS_ONLY
+
+ #undef ANNOTALYSIS_ONLY
+
+ /* Undefine and re-define the macros that the static analyzer understands. */
+ #undef ANNOTATE_IGNORE_READS_BEGIN
+ #define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_READS_END
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_WRITES_BEGIN
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_WRITES_END
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ANNOTATE_IGNORE_READS_BEGIN(); \
+ ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ }while(0) \
+
+ #undef ANNOTATE_IGNORE_READS_AND_WRITES_END
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ }while(0) \
+
+ #if defined(__cplusplus)
+ #undef ANNOTATE_UNPROTECTED_READ
+ template <class T>
+ inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
+ ANNOTALYSIS_UNPROTECTED_READ {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+ }
+ #endif /* __cplusplus */
+
+#endif /* ANNOTALYSIS_ONLY */
+
+/* Undefine the macros intended only in this file. */
+#undef ANNOTALYSIS_STATIC_INLINE
+#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+
+#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc b/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc
new file mode 100644
index 00000000000..2949343700d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc
@@ -0,0 +1,433 @@
+// 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 <stddef.h> // 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 <int N> 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 <class T>
+const T* GetTableElement(const ElfW(Ehdr) *ehdr,
+ ElfW(Off) table_offset,
+ ElfW(Word) element_size,
+ size_t index) {
+ return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr)
+ + table_offset
+ + index * element_size);
+}
+} // namespace
+
+const void *const ElfMemImage::kInvalidBase =
+ reinterpret_cast<const void *>(~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<ElfW(Phdr)>(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<const void *>(sym->st_value);
+ }
+ CHECK_LT(link_base_, sym->st_value);
+ return GetTableElement<char>(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<const char *>(version_definition);
+ version_definition =
+ reinterpret_cast<const ElfW(Verdef) *>(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<const ElfW(Verdaux) *>(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<uintptr_t>(base);
+ // Fake VDSO has low bit set.
+ const bool fake_vdso = ((base_as_uintptr_t & 1) != 0);
+ base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1);
+ const char *const base_as_char = reinterpret_cast<const char *>(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<const ElfW(Ehdr) *>(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<const char *>(link_base_);
+ ElfW(Dyn) *dynamic_entry =
+ reinterpret_cast<ElfW(Dyn) *>(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<ElfW(Word) *>(value);
+ break;
+ case DT_SYMTAB:
+ dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);
+ break;
+ case DT_STRTAB:
+ dynstr_ = reinterpret_cast<const char *>(value);
+ break;
+ case DT_VERSYM:
+ versym_ = reinterpret_cast<ElfW(Versym) *>(value);
+ break;
+ case DT_VERDEF:
+ verdef_ = reinterpret_cast<ElfW(Verdef) *>(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<const char *>(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<const ElfMemImage *>(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/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.h b/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.h
new file mode 100644
index 00000000000..6f1f09773a8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/elf_mem_image.h
@@ -0,0 +1,134 @@
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h> // 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 <stdlib.h>
+#include <link.h> // 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/chromium/third_party/tcmalloc/chromium/src/base/elfcore.h b/chromium/third_party/tcmalloc/chromium/src/base/elfcore.h
new file mode 100644
index 00000000000..34a96dec3d0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/elfcore.h
@@ -0,0 +1,385 @@
+/* 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, and MIPS on Linux.
+ * Porting to other related platforms should not be difficult.
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+ defined(__mips__)) && defined(__linux)
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <config.h>
+
+
+/* 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_ARCH_3__)
+ 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;
+#endif
+
+#if defined(__i386__) && defined(__GNUC__)
+ /* On x86 we provide an optimized version of the FRAME() macro, if the
+ * compiler supports a GCC-style asm() directive. This results in somewhat
+ * more accurate values for CPU registers.
+ */
+ typedef struct Frame {
+ struct i386_regs uregs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile ( \
+ "push %%ebp\n" \
+ "push %%ebx\n" \
+ "mov %%ebx,0(%%eax)\n" \
+ "mov %%ecx,4(%%eax)\n" \
+ "mov %%edx,8(%%eax)\n" \
+ "mov %%esi,12(%%eax)\n" \
+ "mov %%edi,16(%%eax)\n" \
+ "mov %%ebp,20(%%eax)\n" \
+ "mov %%eax,24(%%eax)\n" \
+ "mov %%ds,%%ebx\n" \
+ "mov %%ebx,28(%%eax)\n" \
+ "mov %%es,%%ebx\n" \
+ "mov %%ebx,32(%%eax)\n" \
+ "mov %%fs,%%ebx\n" \
+ "mov %%ebx,36(%%eax)\n" \
+ "mov %%gs,%%ebx\n" \
+ "mov %%ebx, 40(%%eax)\n" \
+ "call 0f\n" \
+ "0:pop %%ebx\n" \
+ "add $1f-0b,%%ebx\n" \
+ "mov %%ebx,48(%%eax)\n" \
+ "mov %%cs,%%ebx\n" \
+ "mov %%ebx,52(%%eax)\n" \
+ "pushf\n" \
+ "pop %%ebx\n" \
+ "mov %%ebx,56(%%eax)\n" \
+ "mov %%esp,%%ebx\n" \
+ "add $8,%%ebx\n" \
+ "mov %%ebx,60(%%eax)\n" \
+ "mov %%ss,%%ebx\n" \
+ "mov %%ebx,64(%%eax)\n" \
+ "pop %%ebx\n" \
+ "pop %%ebp\n" \
+ "1:" \
+ : : "a" (&f) : "memory"); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ (r) = (f).uregs; \
+ } while (0)
+#elif defined(__x86_64__) && defined(__GNUC__)
+ /* The FRAME and SET_FRAME macros for x86_64. */
+ typedef struct Frame {
+ struct i386_regs uregs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile ( \
+ "push %%rbp\n" \
+ "push %%rbx\n" \
+ "mov %%r15,0(%%rax)\n" \
+ "mov %%r14,8(%%rax)\n" \
+ "mov %%r13,16(%%rax)\n" \
+ "mov %%r12,24(%%rax)\n" \
+ "mov %%rbp,32(%%rax)\n" \
+ "mov %%rbx,40(%%rax)\n" \
+ "mov %%r11,48(%%rax)\n" \
+ "mov %%r10,56(%%rax)\n" \
+ "mov %%r9,64(%%rax)\n" \
+ "mov %%r8,72(%%rax)\n" \
+ "mov %%rax,80(%%rax)\n" \
+ "mov %%rcx,88(%%rax)\n" \
+ "mov %%rdx,96(%%rax)\n" \
+ "mov %%rsi,104(%%rax)\n" \
+ "mov %%rdi,112(%%rax)\n" \
+ "mov %%ds,%%rbx\n" \
+ "mov %%rbx,184(%%rax)\n" \
+ "mov %%es,%%rbx\n" \
+ "mov %%rbx,192(%%rax)\n" \
+ "mov %%fs,%%rbx\n" \
+ "mov %%rbx,200(%%rax)\n" \
+ "mov %%gs,%%rbx\n" \
+ "mov %%rbx,208(%%rax)\n" \
+ "call 0f\n" \
+ "0:pop %%rbx\n" \
+ "add $1f-0b,%%rbx\n" \
+ "mov %%rbx,128(%%rax)\n" \
+ "mov %%cs,%%rbx\n" \
+ "mov %%rbx,136(%%rax)\n" \
+ "pushf\n" \
+ "pop %%rbx\n" \
+ "mov %%rbx,144(%%rax)\n" \
+ "mov %%rsp,%%rbx\n" \
+ "add $16,%%ebx\n" \
+ "mov %%rbx,152(%%rax)\n" \
+ "mov %%ss,%%rbx\n" \
+ "mov %%rbx,160(%%rax)\n" \
+ "pop %%rbx\n" \
+ "pop %%rbp\n" \
+ "1:" \
+ : : "a" (&f) : "memory"); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ (f).uregs.fs_base = (r).fs_base; \
+ (f).uregs.gs_base = (r).gs_base; \
+ (r) = (f).uregs; \
+ } while (0)
+#elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
+ /* ARM calling conventions are a little more tricky. A little assembly
+ * helps in obtaining an accurate snapshot of all registers.
+ */
+ typedef struct Frame {
+ struct arm_regs arm;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ long cpsr; \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile( \
+ "stmia %0, {r0-r15}\n" /* All integer regs */\
+ : : "r"(&f.arm) : "memory"); \
+ f.arm.uregs[16] = 0; \
+ __asm__ volatile( \
+ "mrs %0, cpsr\n" /* Condition code reg */\
+ : "=r"(cpsr)); \
+ f.arm.uregs[17] = cpsr; \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ /* Don't override the FPU status register. */\
+ /* Use the value obtained from ptrace(). This*/\
+ /* works, because our code does not perform */\
+ /* any FPU operations, itself. */\
+ long fps = (f).arm.uregs[16]; \
+ errno = (f).errno_; \
+ (r) = (f).arm; \
+ (r).uregs[16] = fps; \
+ } while (0)
+#elif defined(__mips__) && defined(__GNUC__)
+ typedef struct Frame {
+ struct mips_regs mips_regs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
+ #define FRAME(f) Frame f = { 0 }; \
+ do { \
+ unsigned long hi, lo; \
+ register unsigned long pc __asm__("$31"); \
+ f.mips_regs.uregs[ 0] = MIPSREG( 0); \
+ f.mips_regs.uregs[ 1] = MIPSREG( 1); \
+ f.mips_regs.uregs[ 2] = MIPSREG( 2); \
+ f.mips_regs.uregs[ 3] = MIPSREG( 3); \
+ f.mips_regs.uregs[ 4] = MIPSREG( 4); \
+ f.mips_regs.uregs[ 5] = MIPSREG( 5); \
+ f.mips_regs.uregs[ 6] = MIPSREG( 6); \
+ f.mips_regs.uregs[ 7] = MIPSREG( 7); \
+ f.mips_regs.uregs[ 8] = MIPSREG( 8); \
+ f.mips_regs.uregs[ 9] = MIPSREG( 9); \
+ f.mips_regs.uregs[10] = MIPSREG(10); \
+ f.mips_regs.uregs[11] = MIPSREG(11); \
+ f.mips_regs.uregs[12] = MIPSREG(12); \
+ f.mips_regs.uregs[13] = MIPSREG(13); \
+ f.mips_regs.uregs[14] = MIPSREG(14); \
+ f.mips_regs.uregs[15] = MIPSREG(15); \
+ f.mips_regs.uregs[16] = MIPSREG(16); \
+ f.mips_regs.uregs[17] = MIPSREG(17); \
+ f.mips_regs.uregs[18] = MIPSREG(18); \
+ f.mips_regs.uregs[19] = MIPSREG(19); \
+ f.mips_regs.uregs[20] = MIPSREG(20); \
+ f.mips_regs.uregs[21] = MIPSREG(21); \
+ f.mips_regs.uregs[22] = MIPSREG(22); \
+ f.mips_regs.uregs[23] = MIPSREG(23); \
+ f.mips_regs.uregs[24] = MIPSREG(24); \
+ f.mips_regs.uregs[25] = MIPSREG(25); \
+ f.mips_regs.uregs[26] = MIPSREG(26); \
+ f.mips_regs.uregs[27] = MIPSREG(27); \
+ f.mips_regs.uregs[28] = MIPSREG(28); \
+ f.mips_regs.uregs[29] = MIPSREG(29); \
+ f.mips_regs.uregs[30] = MIPSREG(30); \
+ f.mips_regs.uregs[31] = MIPSREG(31); \
+ __asm__ volatile ("mfhi %0" : "=r"(hi)); \
+ __asm__ volatile ("mflo %0" : "=r"(lo)); \
+ __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \
+ f.mips_regs.hi = hi; \
+ f.mips_regs.lo = lo; \
+ f.mips_regs.cp0_epc = pc; \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ memcpy((r).uregs, (f).mips_regs.uregs, \
+ 32*sizeof(unsigned long)); \
+ (r).hi = (f).mips_regs.hi; \
+ (r).lo = (f).mips_regs.lo; \
+ (r).cp0_epc = (f).mips_regs.cp0_epc; \
+ } while (0)
+#else
+ /* If we do not have a hand-optimized assembly version of the FRAME()
+ * macro, we cannot reliably unroll the stack. So, we show a few additional
+ * stack frames for the coredumper.
+ */
+ typedef struct Frame {
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0)
+ #define SET_FRAME(f,r) do { } while (0)
+#endif
+
+
+/* Internal function for generating a core file. This API can change without
+ * notice and is only supposed to be used internally by the core dumper.
+ *
+ * This function works for both single- and multi-threaded core
+ * dumps. If called as
+ *
+ * FRAME(frame);
+ * InternalGetCoreDump(&frame, 0, NULL, ap);
+ *
+ * it creates a core file that only contains information about the
+ * calling thread.
+ *
+ * Optionally, the caller can provide information about other threads
+ * by passing their process ids in "thread_pids". The process id of
+ * the caller should not be included in this array. All of the threads
+ * must have been attached to with ptrace(), prior to calling this
+ * function. They will be detached when "InternalGetCoreDump()" returns.
+ *
+ * This function either returns a file handle that can be read for obtaining
+ * a core dump, or "-1" in case of an error. In the latter case, "errno"
+ * will be set appropriately.
+ *
+ * While "InternalGetCoreDump()" is not technically async signal safe, you
+ * might be tempted to invoke it from a signal handler. The code goes to
+ * great lengths to make a best effort that this will actually work. But in
+ * any case, you must make sure that you preserve the value of "errno"
+ * yourself. It is guaranteed to be clobbered otherwise.
+ *
+ * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
+ * it makes a best effort to behave reasonably when called in a multi-
+ * threaded environment, but it is ultimately the caller's responsibility
+ * to provide locking.
+ */
+int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
+ va_list ap
+ /* const struct CoreDumpParameters *params,
+ const char *file_name,
+ const char *PATH
+ */);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ELFCORE_H */
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/googleinit.h b/chromium/third_party/tcmalloc/chromium/src/base/googleinit.h
new file mode 100644
index 00000000000..728d9beca91
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/googleinit.h
@@ -0,0 +1,88 @@
+// 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) {
+ // TODO(dmikurube): Re-enable the commented-out code.
+ // We commented out the following line, since Chromium does not have the
+ // proper includes to log using these macros.
+ //
+ // Commended-out code:
+ // RAW_VLOG(10, "<GoogleModuleObject> constructing: %s\n", name_);
+ //
+ // This googleinit.h is included from out of third_party/tcmalloc, such as
+ // net/tools/flip_server/balsa_headers.cc.
+ // "base/logging.h" (included above) indicates Chromium's base/logging.h
+ // when this googleinit.h is included from out of third_party/tcmalloc.
+ if (ctor)
+ ctor();
+ }
+ ~GoogleInitializer() {
+ // TODO(dmikurube): Re-enable the commented-out code.
+ // The same as above. The following line is commented out in Chromium.
+ //
+ // Commended-out code:
+ // RAW_VLOG(10, "<GoogleModuleObject> destroying: %s\n", name_);
+ if (destructor_)
+ destructor_();
+ }
+
+ private:
+ // TODO(dmikurube): Re-enable the commented-out code.
+ // 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/chromium/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h b/chromium/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
new file mode 100644
index 00000000000..ac1e797e1cf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
@@ -0,0 +1,2280 @@
+/* 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_futex1(
+ * sys_getcpu(
+ * sys_getdents(
+ * 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_getdents64
+ * sys_llseek
+ * sys_mmap2
+ * sys_openat
+ * 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, and 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)
+
+#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 <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#if defined(__ANDROID__)
+#include <sys/syscall.h>
+#ifndef ANDROID_NON_SDK_BUILD
+#include <sys/linux-syscalls.h>
+#endif
+#else
+#include <syscall.h>
+#endif
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <endian.h>
+
+#ifdef __mips__
+/* Include definitions of the ABI currently in use. */
+#include <sgidefs.h>
+#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__)
+
+/* 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
+#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,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}/stat.h */
+#ifdef __mips__
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+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_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned long long st_rdev;
+ unsigned short int __pad2;
+ long long st_size;
+ long st_blksize;
+ long 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 long __unused4;
+ unsigned long __unused5;
+};
+#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,i386,mips,x86_64,ppc}/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 st_dev;
+ unsigned long st_ino; // ino_t
+ unsigned long st_mode; // mode_t
+ unsigned short st_nlink; // nlink_t
+ unsigned st_uid; // uid_t
+ unsigned st_gid; // gid_t
+ unsigned st_rdev;
+ long st_size; // off_t
+ 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;
+};
+#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64)
+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];
+};
+#endif
+
+// ulong is not defined in Android while used to define __llseek.
+#if defined(__ANDROID__)
+typedef unsigned long int ulong;
+#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
+#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_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 defininitions */
+#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__))
+ /* 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 \
+ : "esp", "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)) \
+ : "esp", "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)) \
+ : "esp", "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)
+ : "esp", "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))
+ : "rsp", "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), "r" ((unsigned long)arg5), \
+ "r" ((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.3.6 clone.S */
+ /* TODO(csilvers): consider wrapping some args up in a struct, like we
+ * do for i386's _syscall6, so we can compile successfully on gcc 2.95
+ */
+ 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;
+ {
+ 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");
+ }
+ LSS_RETURN(int, __ret, __err);
+ }
+ #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)
+ LSS_INLINE _syscall3(int, fcntl, int, f,
+ int, c, long, a)
+ LSS_INLINE _syscall2(int, fstat, int, f,
+ struct kernel_stat*, b)
+ LSS_INLINE _syscall4(int, futex, int*, a,
+ int, o, int, v,
+ struct kernel_timespec*, t)
+ LSS_INLINE _syscall3(int, getdents, int, f,
+ struct kernel_dirent*, d, int, c)
+#ifdef __NR_getdents64
+ LSS_INLINE _syscall3(int, getdents64, int, f,
+ struct kernel_dirent64*, d, int, c)
+#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));
+ }
+ #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 _syscall3(int, open, const char*, p,
+ int, f, int, m)
+ 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)
+ LSS_INLINE _syscall2(int, stat, const char*, f,
+ struct kernel_stat*, b)
+ 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(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
+ LSS_INLINE _syscall3(int, socket, int, d,
+ int, t, int, p)
+ #endif
+ #if 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,
+ __off64_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));
+ }
+
+ LSS_INLINE int LSS_NAME(sigaction)(int signum,
+ const struct kernel_sigaction *act,
+ struct kernel_sigaction *oldact) {
+ /* 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 {
+ 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(__x86_64__) || \
+ defined(__arm__) || \
+ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
+ 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);
+ }
+ #endif
+ #if (defined(__i386__) || defined(__x86_64__) || defined(__arm__)) && \
+ !defined(__ANDROID__)
+ LSS_INLINE _syscall4(int, openat, int, d, 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__)
+ #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)
+#ifdef __PPC64__
+ LSS_INLINE _syscall6(void*, mmap, void*, s,
+ size_t, l, int, p,
+ int, f, int, d,
+ off_t, o)
+#else
+ #ifndef __ARM_EABI__
+ /* Not available on ARM EABI Linux. */
+ LSS_INLINE _syscall1(void*, mmap, void*, a)
+ #endif
+ 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(__PPC__)
+ #undef LSS_SC_LOADARGS_0
+ #define LSS_SC_LOADARGS_0(dummy...)
+ #undef LSS_SC_LOADARGS_1
+ #define LSS_SC_LOADARGS_1(arg1) \
+ __sc_4 = (unsigned long) (arg1)
+ #undef LSS_SC_LOADARGS_2
+ #define LSS_SC_LOADARGS_2(arg1, arg2) \
+ LSS_SC_LOADARGS_1(arg1); \
+ __sc_5 = (unsigned long) (arg2)
+ #undef LSS_SC_LOADARGS_3
+ #define LSS_SC_LOADARGS_3(arg1, arg2, arg3) \
+ LSS_SC_LOADARGS_2(arg1, arg2); \
+ __sc_6 = (unsigned long) (arg3)
+ #undef LSS_SC_LOADARGS_4
+ #define LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4) \
+ LSS_SC_LOADARGS_3(arg1, arg2, arg3); \
+ __sc_7 = (unsigned long) (arg4)
+ #undef LSS_SC_LOADARGS_5
+ #define LSS_SC_LOADARGS_5(arg1, arg2, arg3, arg4, arg5) \
+ LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4); \
+ __sc_8 = (unsigned long) (arg5)
+ #undef LSS_SC_BODY
+ #define LSS_SC_BODY(nr, type, opt, args...) \
+ long __sc_ret, __sc_err; \
+ { \
+ register unsigned long __sc_0 __asm__ ("r0") = __NR_socketcall; \
+ register unsigned long __sc_3 __asm__ ("r3") = opt; \
+ 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_SC_LOADARGS_##nr(args); \
+ __asm__ __volatile__ \
+ ("stwu 1, -48(1)\n\t" \
+ "stw 4, 20(1)\n\t" \
+ "stw 5, 24(1)\n\t" \
+ "stw 6, 28(1)\n\t" \
+ "stw 7, 32(1)\n\t" \
+ "stw 8, 36(1)\n\t" \
+ "addi 4, 1, 20\n\t" \
+ "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"); \
+ __sc_ret = __sc_3; \
+ __sc_err = __sc_0; \
+ } \
+ LSS_RETURN(type, __sc_ret, __sc_err)
+
+ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
+ LSS_SC_BODY(3, int, 1, domain, type, protocol);
+ }
+ #endif
+ #if defined(__i386__) || \
+ (defined(__arm__) && !defined(__ARM_EABI__)) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+
+ /* 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(long, 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(__i386__) || defined(__PPC__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+ LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p,
+ int*, s, int, o)
+ #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;
+ }
+ }
+ #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/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.cc b/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.cc
new file mode 100644
index 00000000000..19da4004b17
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.cc
@@ -0,0 +1,665 @@
+/* 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 <sched.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#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
+
+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 - 4096,
+ 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 ResumeAllProcessThreads(), then
+ * we are running a higher risk, though. So, try to avoid calling
+ * abort() after calling 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) {
+ 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;
+};
+
+
+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;
+
+ /* 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 = sys_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) {
+ 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 (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 */
+ 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 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
+ * 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 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;
+
+ 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;
+
+ /* 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
+
+ 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) {
+ 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;
+ }
+ } else {
+ args.result = -1;
+ args.err = clone_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
+ * 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 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/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.h b/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.h
new file mode 100644
index 00000000000..5c318fed7ec
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/linuxthreads.h
@@ -0,0 +1,53 @@
+/* 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 x86-32 and x86-64 on Linux. Porting to other
+ * related platforms should not be difficult.
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+ defined(__mips__) || defined(__PPC__)) && 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/chromium/third_party/tcmalloc/chromium/src/base/logging.cc b/chromium/third_party/tcmalloc/chromium/src/base/logging.cc
new file mode 100644
index 00000000000..4b97858a371
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/logging.cc
@@ -0,0 +1,107 @@
+// 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 <config.h>
+#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 <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#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/chromium/third_party/tcmalloc/chromium/src/base/logging.h b/chromium/third_party/tcmalloc/chromium/src/base/logging.h
new file mode 100644
index 00000000000..02f84f4348b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/logging.h
@@ -0,0 +1,288 @@
+// 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 <config.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#include <string.h> // for strlen(), strcmp()
+#include <assert.h>
+#include <errno.h> // for errno
+#include "base/abort.h"
+#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(__ANDROID__) || defined(ANDROID)
+#include <android/log.h>
+#define WRITE_TO_STDERR(buf, len) \
+ __android_log_write(ANDROID_LOG_ERROR, "gperftools", buf)
+#elif defined(HAVE_SYS_SYSCALL_H)
+#include <sys/syscall.h>
+#define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
+#else
+#define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
+#endif
+
+// 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); \
+ tcmalloc::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);\
+ tcmalloc::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); \
+ tcmalloc::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); \
+ tcmalloc::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[1600];
+ 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");
+ }
+#if defined(__ANDROID__) || defined(ANDROID)
+ android_LogPriority priority = ANDROID_LOG_UNKNOWN;
+ switch (severity) {
+ case INFO: {
+ priority = ANDROID_LOG_INFO;
+ break;
+ }
+ case WARNING: {
+ priority = ANDROID_LOG_WARN;
+ break;
+ }
+ case ERROR: {
+ priority = ANDROID_LOG_ERROR;
+ break;
+ }
+ case FATAL: {
+ priority = ANDROID_LOG_FATAL;
+ break;
+ }
+ }
+ __android_log_write(priority, "gperftools", buf);
+#else // defined(__ANDROID__) || defined(ANDROID)
+ WRITE_TO_STDERR(buf, strlen(buf));
+#endif // defined(__ANDROID__) || defined(ANDROID)
+ if ((severity) == FATAL) {
+ // LOG(FATAL) indicates a big problem, so don't run atexit() calls
+ tcmalloc::Abort();
+ }
+}
+
+// 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 <windows.h>
+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/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.cc b/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.cc
new file mode 100644
index 00000000000..c043cb68b6e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.cc
@@ -0,0 +1,522 @@
+/* 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 <gperftools/malloc_hook.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <new> // 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.
+
+// ---------------------------------------------------------------------------
+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 int32 r = 1; // no locking---it's not critical
+ ANNOTATE_BENIGN_RACE(&r, "benign race, 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<kMaxLevel and next[level-1] will fit in the node.
+// 0 < LLA_SkiplistLevels(x,y,false) <= LLA_SkiplistLevels(x,y,true) < kMaxLevel
+static int LLA_SkiplistLevels(size_t size, size_t base, bool random) {
+ // max_fit is the maximum number of levels that will fit in a node for the
+ // given size. We can't return more than max_fit, no matter what the
+ // random number generator says.
+ int max_fit = (size-OFFSETOF_MEMBER(AllocList, next)) / sizeof (AllocList *);
+ int level = IntLog2(size, base) + (random? Random() : 1);
+ if (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)
+};
+
+// 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;
+
+// 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<intptr_t>(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'.
+ }
+ }
+}
+
+// L < meta_data_arena->mu
+LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32 flags,
+ Arena *meta_data_arena) {
+ 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;
+ 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, &region->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<intptr_t>(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<char *>(prev) + prev->header.size <
+ reinterpret_cast<char *>(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<char *>(a) + a->header.size ==
+ reinterpret_cast<char *>(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<AllocList *>(
+ reinterpret_cast<char *>(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<AllocList *>(
+ reinterpret_cast<char *>(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;
+ if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
+ new_pages = MallocHook::UnhookedMMap(0, new_pages_size,
+ PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ } else {
+ new_pages = mmap(0, new_pages_size,
+ PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ }
+ RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
+ arena->mu.Lock();
+ s = reinterpret_cast<AllocList *>(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<AllocList *>
+ (req_rnd + reinterpret_cast<char *>(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;
+ }
+ ANNOTATE_NEW_MEMORY(result, request);
+ 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;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.h b/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.h
new file mode 100644
index 00000000000..393b3d25b8a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/low_level_alloc.h
@@ -0,0 +1,106 @@
+/* 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 <config.h>
+#include <stddef.h> // for size_t
+#include "base/basictypes.h"
+
+class LowLevelAlloc {
+ public:
+ 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);
+
+ // 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/chromium/third_party/tcmalloc/chromium/src/base/simple_mutex.h b/chromium/third_party/tcmalloc/chromium/src/base/simple_mutex.h
new file mode 100644
index 00000000000..1c4783d418c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/simple_mutex.h
@@ -0,0 +1,331 @@
+// 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 <config.h>
+
+#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 <windows.h>
+ 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 <pthread.h>
+ typedef pthread_rwlock_t MutexType;
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+ typedef pthread_mutex_t MutexType;
+#else
+# error Need to implement mutex.h for your architecture, or #define NO_THREADS
+#endif
+
+#include <assert.h>
+#include "base/abort.h"
+
+#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) tcmalloc::Abort(); \
+} while (0)
+
+Mutex::Mutex() : destroy_(true) {
+ SetIsSafe();
+ if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) tcmalloc::Abort();
+}
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
+ SetIsSafe();
+ if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) tcmalloc::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) tcmalloc::Abort(); \
+} while (0)
+
+Mutex::Mutex() : destroy_(true) {
+ SetIsSafe();
+ if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) tcmalloc::Abort();
+}
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
+ SetIsSafe();
+ if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) tcmalloc::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/chromium/third_party/tcmalloc/chromium/src/base/spinlock.cc b/chromium/third_party/tcmalloc/chromium/src/base/spinlock.cc
new file mode 100644
index 00000000000..1413923fef1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock.cc
@@ -0,0 +1,182 @@
+/* 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 <config.h>
+#include "base/spinlock.h"
+#include "base/synchronization_profiling.h"
+#include "base/spinlock_internal.h"
+#include "base/cycleclock.h"
+#include "base/sysinfo.h" /* for NumCPUs() */
+
+// NOTE on the Lock-state values:
+//
+// kSpinLockFree represents the unlocked state
+// kSpinLockHeld represents the locked state with no waiters
+//
+// Values greater than kSpinLockHeld represent the locked state with waiters,
+// where the value is the time the current lock holder had to
+// wait before obtaining the lock. The kSpinLockSleeper state is a special
+// "locked with waiters" state that indicates that a sleeper needs to
+// be woken, but the thread that just released the lock didn't wait.
+
+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 (NumCPUs() > 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;
+
+} // unnamed namespace
+
+// Monitor the lock to see if its value changes within some time period
+// (adaptive_spin_count loop iterations). A timestamp indicating
+// when the thread initially started waiting for the lock is passed in via
+// the initial_wait_timestamp value. The total wait time in cycles for the
+// lock is returned in the wait_cycles parameter. The last value read
+// from the lock is returned from the method.
+Atomic32 SpinLock::SpinLoop(int64 initial_wait_timestamp,
+ Atomic32* wait_cycles) {
+ int c = adaptive_spin_count;
+ while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) {
+ }
+ Atomic32 spin_loop_wait_cycles = CalculateWaitCycles(initial_wait_timestamp);
+ Atomic32 lock_value =
+ base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
+ spin_loop_wait_cycles);
+ *wait_cycles = spin_loop_wait_cycles;
+ return lock_value;
+}
+
+void SpinLock::SlowLock() {
+ // The lock was not obtained initially, so this thread needs to wait for
+ // it. Record the current timestamp in the local variable wait_start_time
+ // so the total wait time can be stored in the lockword once this thread
+ // obtains the lock.
+ int64 wait_start_time = CycleClock::Now();
+ Atomic32 wait_cycles;
+ Atomic32 lock_value = SpinLoop(wait_start_time, &wait_cycles);
+
+ 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 SpinLockWait routine to properly indicate
+ // the last lock_value observed.
+ lock_value = kSpinLockSleeper;
+ } else if (lock_value == kSpinLockFree) {
+ // Lock is free again, so try and aquire 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,
+ wait_cycles);
+ 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(wait_start_time, &wait_cycles);
+ }
+}
+
+// The wait time for contentionz lock profiling must fit into 32 bits.
+// However, the lower 32-bits of the cycle counter wrap around too quickly
+// with high frequency processors, so a right-shift by 7 is performed to
+// quickly divide the cycles by 128. Using these 32 bits, reduces the
+// granularity of time measurement to 128 cycles, and loses track
+// of wait time for waits greater than 109 seconds on a 5 GHz machine
+// [(2^32 cycles/5 Ghz)*128 = 109.95 seconds]. Waits this long should be
+// very rare and the reduced granularity should not be an issue given
+// processors in the Google fleet operate at a minimum of one billion
+// cycles/sec.
+enum { PROFILE_TIMESTAMP_SHIFT = 7 };
+
+void SpinLock::SlowUnlock(uint64 wait_cycles) {
+ base::internal::SpinLockWake(&lockword_, false); // wake waiter if necessary
+
+ // Collect contentionz profile info, expanding the wait_cycles back out to
+ // the full value. If wait_cycles is <= kSpinLockSleeper, then no wait
+ // was actually performed, so don't record the wait time. Note, that the
+ // CalculateWaitCycles method adds in kSpinLockSleeper cycles
+ // unconditionally to guarantee the wait time is not kSpinLockFree or
+ // kSpinLockHeld. The adding in of these small number of cycles may
+ // overestimate the contention by a slight amount 50% of the time. However,
+ // if this code tried to correct for that addition by subtracting out the
+ // kSpinLockSleeper amount that would underestimate the contention slightly
+ // 50% of the time. Both ways get the wrong answer, so the code
+ // overestimates to be more conservative. Overestimating also makes the code
+ // a little simpler.
+ //
+ if (wait_cycles > kSpinLockSleeper) {
+ base::SubmitSpinLockProfileData(this,
+ wait_cycles << PROFILE_TIMESTAMP_SHIFT);
+ }
+}
+
+inline int32 SpinLock::CalculateWaitCycles(int64 wait_start_time) {
+ int32 wait_cycles = ((CycleClock::Now() - wait_start_time) >>
+ PROFILE_TIMESTAMP_SHIFT);
+ // The number of cycles waiting for the lock is used as both the
+ // wait_cycles and lock value, so it can't be kSpinLockFree or
+ // kSpinLockHeld. Make sure the value returned is at least
+ // kSpinLockSleeper.
+ wait_cycles |= kSpinLockSleeper;
+ return wait_cycles;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/spinlock.h b/chromium/third_party/tcmalloc/chromium/src/base/spinlock.h
new file mode 100644
index 00000000000..c2be4fd7264
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock.h
@@ -0,0 +1,151 @@
+/* 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
+ */
+
+//
+// Fast spinlocks (at least on x86, a lock/unlock pair is approximately
+// half the cost of a Mutex because the unlock just does a store instead
+// of a compare-and-swap which is expensive).
+
+// 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 <config.h>
+#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.
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
+ if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
+ kSpinLockHeld) != kSpinLockFree) {
+ SlowLock();
+ }
+ ANNOTATE_RWLOCK_ACQUIRED(this, 1);
+ }
+
+ // 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);
+ if (res) {
+ ANNOTATE_RWLOCK_ACQUIRED(this, 1);
+ }
+ return res;
+ }
+
+ // Release this SpinLock, which must be held by the calling thread.
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ inline void Unlock() /*UNLOCK_FUNCTION()*/ {
+ uint64 wait_cycles =
+ static_cast<uint64>(base::subtle::NoBarrier_Load(&lockword_));
+ ANNOTATE_RWLOCK_RELEASED(this, 1);
+ base::subtle::Release_Store(&lockword_, kSpinLockFree);
+ if (wait_cycles != kSpinLockHeld) {
+ // Collect contentionz profile info, and speed the wakeup of any waiter.
+ // The wait_cycles value indicates how long this thread spent waiting
+ // for the lock.
+ SlowUnlock(wait_cycles);
+ }
+ }
+
+ // 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(uint64 wait_cycles);
+ Atomic32 SpinLoop(int64 initial_wait_timestamp, Atomic32* wait_cycles);
+ inline int32 CalculateWaitCycles(int64 wait_start_time);
+
+ 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();
+ }
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ 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/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.cc b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.cc
new file mode 100644
index 00000000000..b9faddef2c6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.cc
@@ -0,0 +1,102 @@
+/* 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 {
+
+// See spinlock_internal.h for spec.
+int32 SpinLockWait(volatile Atomic32 *w, int n,
+ const SpinLockWaitTransition trans[]) {
+ int32 v;
+ bool done = false;
+ for (int loop = 0; !done; loop++) {
+ v = base::subtle::Acquire_Load(w);
+ int i;
+ for (i = 0; i != n && v != trans[i].from; i++) {
+ }
+ if (i == n) {
+ SpinLockDelay(w, v, loop); // no matching transition
+ } else if (trans[i].to == v || // null transition
+ base::subtle::Acquire_CompareAndSwap(w, v, trans[i].to) == v) {
+ done = trans[i].done;
+ }
+ }
+ return v;
+}
+
+// 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.
+ 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));
+}
+
+} // namespace internal
+} // namespace base
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.h b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.h
new file mode 100644
index 00000000000..44942609f40
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_internal.h
@@ -0,0 +1,64 @@
+/* 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 <config.h>
+#include "base/basictypes.h"
+#include "base/atomicops.h"
+
+namespace base {
+namespace internal {
+
+// SpinLockWait() waits until it can perform one of several transitions from
+// "from" to "to". It returns when it performs a transition where done==true.
+struct SpinLockWaitTransition {
+ int32 from;
+ int32 to;
+ bool done;
+};
+
+// Wait until *w can transition from trans[i].from to trans[i].to for some i
+// satisfying 0<=i<n && trans[i].done, atomically make the transition,
+// then return the old value of *w. Make any other atomic tranistions
+// where !trans[i].done, but continue waiting.
+int32 SpinLockWait(volatile Atomic32 *w, int n,
+ const SpinLockWaitTransition trans[]);
+void SpinLockWake(volatile Atomic32 *w, bool all);
+void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop);
+
+} // namespace internal
+} // namespace base
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h
new file mode 100644
index 00000000000..4a1498db97c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h
@@ -0,0 +1,114 @@
+/* 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 <errno.h>
+#include <sched.h>
+#include <time.h>
+#include <limits.h>
+#include "base/linux_syscall_support.h"
+
+#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. This
+// is necessary to make the code compatible with the seccomp sandbox,
+// which needs to be able to find and patch all places where system
+// calls are made. Scanning through and patching glibc is fast, but
+// doing so on the entire Chrome binary would be prohibitively
+// expensive.
+// This is a notable change from the upstream version of tcmalloc,
+// which prefers direct system calls in order to improve compatibility
+// with older toolchains and runtime libraries.
+
+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.
+#ifdef __arm__
+ // ARM linux doesn't support sys_futex1(void*, int, int, struct timespec*);
+ have_futex = 0;
+#else
+ have_futex = (sizeof (Atomic32) == sizeof (int) &&
+ syscall(__NR_futex, &x, FUTEX_WAKE, 1, 0) >= 0);
+#endif
+ if (have_futex &&
+ syscall(__NR_futex, &x, FUTEX_WAKE | futex_private_flag, 1, 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) {
+ // Wait between 0-16ms.
+ tm.tv_nsec = base::internal::SuggestedDelayNS(loop);
+ // Note: since Unlock() is optimized to not do a compare-and-swap,
+ // we can't expect explicit wake-ups. Therefore we shouldn't wait too
+ // long here.
+ syscall(__NR_futex, reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAIT | futex_private_flag,
+ value, reinterpret_cast<struct kernel_timespec *>(&tm));
+ } else {
+ tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin
+ nanosleep(&tm, NULL);
+ }
+ errno = save_errno;
+ }
+}
+
+void SpinLockWake(volatile Atomic32 *w, bool all) {
+ if (have_futex) {
+ syscall(__NR_futex, reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAKE | futex_private_flag, 1, 0);
+ }
+}
+
+} // namespace internal
+} // namespace base
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h
new file mode 100644
index 00000000000..e1d43b7db29
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h
@@ -0,0 +1,62 @@
+/* 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 <config.h>
+#include <errno.h>
+#ifdef HAVE_SCHED_H
+#include <sched.h> /* For sched_yield() */
+#endif
+#include <time.h> /* 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/chromium/third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h
new file mode 100644
index 00000000000..9e77311c86a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h
@@ -0,0 +1,60 @@
+/* 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 <windows.h>
+
+namespace base {
+namespace internal {
+
+void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop) {
+ if (loop == 0) {
+ } else if (loop == 1) {
+ Sleep(0);
+ } else {
+ // TODO(dmikurube): Re-enable the commented-out code.
+ // We commented out the following line and used the old code "Sleep(1)"
+ // since base/atomicops-internals-windows.h doesn't support 64-bit
+ // operations.
+ //
+ // Commended-out code:
+ // Sleep(base::internal::SuggestedDelayNS(loop) / 1000000);
+ Sleep(1);
+ }
+}
+
+void SpinLockWake(volatile Atomic32 *w, bool all) {
+}
+
+} // namespace internal
+} // namespace base
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/stl_allocator.h b/chromium/third_party/tcmalloc/chromium/src/base/stl_allocator.h
new file mode 100644
index 00000000000..8276a83d77f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/stl_allocator.h
@@ -0,0 +1,97 @@
+/* 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 <config.h>
+
+#include <stddef.h> // for ptrdiff_t
+#include <limits>
+
+#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<T, MyAlloc> provides the same thread-safety
+// guarantees as MyAlloc.
+//
+// Usage example:
+// set<T, less<T>, STL_Allocator<T, MyAlloc> > 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 <typename T, class Alloc>
+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 <class T1> struct rebind {
+ typedef STL_Allocator<T1, Alloc> other;
+ };
+
+ STL_Allocator() { }
+ STL_Allocator(const STL_Allocator&) { }
+ template <class T1> STL_Allocator(const STL_Allocator<T1, Alloc>&) { }
+ ~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<T*>(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/chromium/third_party/tcmalloc/chromium/src/base/synchronization_profiling.h b/chromium/third_party/tcmalloc/chromium/src/base/synchronization_profiling.h
new file mode 100644
index 00000000000..cf02c218a11
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/synchronization_profiling.h
@@ -0,0 +1,50 @@
+/* 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.
+ *
+ * ---
+ * Author: Chris Ruemmler
+ */
+
+#ifndef BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
+#define BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
+
+#include "base/basictypes.h"
+
+namespace base {
+
+// We can do contention-profiling of SpinLocks, but the code is in
+// mutex.cc, which is not always linked in with spinlock. Hence we
+// provide a weak definition, which are used if mutex.cc isn't linked in.
+
+// Submit the number of cycles the spinlock spent contending.
+ATTRIBUTE_WEAK extern void SubmitSpinLockProfileData(const void *, int64);
+extern void SubmitSpinLockProfileData(const void *contendedlock,
+ int64 wait_cycles) {}
+}
+#endif // BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.cc b/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.cc
new file mode 100644
index 00000000000..e16d65a2f39
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.cc
@@ -0,0 +1,1144 @@
+// 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 <config.h>
+#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(__CYGWIN__) && !defined(__CYGWIN32)
+# define PLATFORM_WINDOWS 1
+#elif defined(__ANDROID__) || defined(ANDROID)
+# define PLATFORM_ANDROID 1
+#endif
+
+#include <ctype.h> // for isspace()
+#include <stdlib.h> // for getenv()
+#include <stdio.h> // for snprintf(), sscanf()
+#include <string.h> // for memmove(), memchr(), etc.
+#include <fcntl.h> // for open()
+#include <errno.h> // for errno
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for read()
+#endif
+#if defined __MACH__ // Mac OS X, almost certainly
+#include <mach-o/dyld.h> // for iterating over dll's in ProcMapsIter
+#include <mach-o/loader.h> // for iterating over dll's in ProcMapsIter
+#include <sys/types.h>
+#include <sys/sysctl.h> // how we figure out numcpu's on OS X
+#elif defined __FreeBSD__
+#include <sys/sysctl.h>
+#elif defined __sun__ // Solaris
+#include <procfs.h> // for, e.g., prmap_t
+#elif defined(PLATFORM_WINDOWS)
+#include <process.h> // for getpid() (actually, _getpid())
+#include <shlwapi.h> // for SHGetValueA()
+#include <tlhelp32.h> // for Module32First()
+#elif defined(PLATFORM_ANDROID)
+#include <sys/system_properties.h>
+#endif
+#include "base/sysinfo.h"
+#include "base/commandlineflags.h"
+#include "base/dynamic_annotations.h" // for RunningOnValgrind
+#include "base/logging.h"
+#include "base/cycleclock.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 <sys/syscall.h>
+#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.
+// ----------------------------------------------------------------------
+
+// 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) {
+#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
+ if (__environ) { // can exist but be NULL, if statically linked
+ const int namelen = strlen(name);
+ for (char** p = __environ; *p; p++) {
+ if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
+ return *p + namelen+1; // point after =
+ }
+ 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 int namelen = strlen(name);
+ 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*)memchr(p, '\0', sizeof(envbuf) - (p - envbuf));
+ if (endp == NULL) // this entry isn't NUL terminated
+ return NULL;
+ else if (!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
+}
+
+// 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.
+//
+// In Chromium this hack is intentionally disabled, because the path is not
+// re-initialized upon fork.
+bool GetUniquePathFromEnv(const char* env_name, char* path) {
+#if defined(PLATFORM_ANDROID)
+ char envval[PROP_VALUE_MAX];
+ __system_property_get(env_name, envval);
+#else
+ char* envval = getenv(env_name);
+#endif
+ 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);
+#if 0
+ envval[0] |= 128; // set high bit for kids to see
+#endif
+ }
+ return true;
+}
+
+// ----------------------------------------------------------------------
+// CyclesPerSecond()
+// NumCPUs()
+// It's important this not call malloc! -- they may be called at
+// global-construct time, before we've set up all our proper malloc
+// hooks and such.
+// ----------------------------------------------------------------------
+
+static double cpuinfo_cycles_per_second = 1.0; // 0.0 might be dangerous
+static int cpuinfo_num_cpus = 1; // Conservative guess
+
+void SleepForMilliseconds(int milliseconds) {
+#ifdef PLATFORM_WINDOWS
+ _sleep(milliseconds); // Windows's _sleep takes milliseconds argument
+#else
+ // Sleep for a few milliseconds
+ struct timespec sleep_time;
+ sleep_time.tv_sec = milliseconds / 1000;
+ sleep_time.tv_nsec = (milliseconds % 1000) * 1000000;
+ while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR)
+ ; // Ignore signals and wait for the full interval to elapse.
+#endif
+}
+
+// Helper function estimates cycles/sec by observing cycles elapsed during
+// sleep(). Using small sleep time decreases accuracy significantly.
+static int64 EstimateCyclesPerSecond(const int estimate_time_ms) {
+ assert(estimate_time_ms > 0);
+ if (estimate_time_ms <= 0)
+ return 1;
+ double multiplier = 1000.0 / (double)estimate_time_ms; // scale by this much
+
+ const int64 start_ticks = CycleClock::Now();
+ SleepForMilliseconds(estimate_time_ms);
+ const int64 guess = int64(multiplier * (CycleClock::Now() - start_ticks));
+ return guess;
+}
+
+// ReadIntFromFile is only called on linux and cygwin platforms.
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+// Helper function for reading an int from a file. Returns true if successful
+// and the memory location pointed to by value is set to the value read.
+static bool ReadIntFromFile(const char *file, int *value) {
+ bool ret = false;
+ int fd = open(file, O_RDONLY);
+ if (fd != -1) {
+ char line[1024];
+ char* err;
+ memset(line, '\0', sizeof(line));
+ read(fd, line, sizeof(line) - 1);
+ const int temp_value = strtol(line, &err, 10);
+ if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
+ *value = temp_value;
+ ret = true;
+ }
+ close(fd);
+ }
+ return ret;
+}
+#endif
+
+// WARNING: logging calls back to InitializeSystemInfo() so it must
+// not invoke any logging code. Also, InitializeSystemInfo() can be
+// called before main() -- in fact it *must* be since already_called
+// isn't protected -- before malloc hooks are properly set up, so
+// we make an effort not to call any routines which might allocate
+// memory.
+
+static void InitializeSystemInfo() {
+ static bool already_called = false; // safe if we run before threads
+ if (already_called) return;
+ already_called = true;
+
+ bool saw_mhz = false;
+
+ if (RunningOnValgrind()) {
+ // Valgrind may slow the progress of time artificially (--scale-time=N
+ // option). We thus can't rely on CPU Mhz info stored in /sys or /proc
+ // files. Thus, actually measure the cps.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(100);
+ saw_mhz = true;
+ }
+
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+ char line[1024];
+ char* err;
+ int freq;
+
+ // If the kernel is exporting the tsc frequency use that. There are issues
+ // where cpuinfo_max_freq cannot be relied on because the BIOS may be
+ // exporintg an invalid p-state (on x86) or p-states may be used to put the
+ // processor in a new mode (turbo mode). Essentially, those frequencies
+ // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
+ // well.
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
+ // The value is in kHz (as the file name suggests). For example, on a
+ // 2GHz warpstation, the file contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
+ }
+
+ // If CPU scaling is in effect, we want to use the *maximum* frequency,
+ // not whatever CPU speed some random processor happens to be using now.
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
+ &freq)) {
+ // The value is in kHz. For example, on a 2GHz machine, the file
+ // contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
+ }
+
+ // Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq.
+ const char* pname = "/proc/cpuinfo";
+ int fd = open(pname, O_RDONLY);
+ if (fd == -1) {
+ perror(pname);
+ if (!saw_mhz) {
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
+ return; // TODO: use generic tester instead?
+ }
+
+ double bogo_clock = 1.0;
+ bool saw_bogo = false;
+ int num_cpus = 0;
+ line[0] = line[1] = '\0';
+ int chars_read = 0;
+ do { // we'll exit when the last read didn't read anything
+ // Move the next line to the beginning of the buffer
+ const int oldlinelen = strlen(line);
+ if (sizeof(line) == oldlinelen + 1) // oldlinelen took up entire line
+ line[0] = '\0';
+ else // still other lines left to save
+ memmove(line, line + oldlinelen+1, sizeof(line) - (oldlinelen+1));
+ // Terminate the new line, reading more if we can't find the newline
+ char* newline = strchr(line, '\n');
+ if (newline == NULL) {
+ const int linelen = strlen(line);
+ const int bytes_to_read = sizeof(line)-1 - linelen;
+ assert(bytes_to_read > 0); // because the memmove recovered >=1 bytes
+ chars_read = read(fd, line + linelen, bytes_to_read);
+ line[linelen + chars_read] = '\0';
+ newline = strchr(line, '\n');
+ }
+ if (newline != NULL)
+ *newline = '\0';
+
+ // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
+ // accept postive values. Some environments (virtual machines) report zero,
+ // which would cause infinite looping in WallTime_Init.
+ if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
+ const char* freqstr = strchr(line, ':');
+ if (freqstr) {
+ cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
+ if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0)
+ saw_mhz = true;
+ }
+ } else if (strncasecmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
+ const char* freqstr = strchr(line, ':');
+ if (freqstr) {
+ bogo_clock = strtod(freqstr+1, &err) * 1000000.0;
+ if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0)
+ saw_bogo = true;
+ }
+ } else if (strncasecmp(line, "processor", sizeof("processor")-1) == 0) {
+ num_cpus++; // count up every time we see an "processor :" entry
+ }
+ } while (chars_read > 0);
+ close(fd);
+
+ if (!saw_mhz) {
+ if (saw_bogo) {
+ // If we didn't find anything better, we'll use bogomips, but
+ // we're not happy about it.
+ cpuinfo_cycles_per_second = bogo_clock;
+ } else {
+ // If we don't even have bogomips, we'll use the slow estimation.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
+ }
+ if (cpuinfo_cycles_per_second == 0.0) {
+ cpuinfo_cycles_per_second = 1.0; // maybe unnecessary, but safe
+ }
+ if (num_cpus > 0) {
+ cpuinfo_num_cpus = num_cpus;
+ }
+
+#elif defined __FreeBSD__
+ // For this sysctl to work, the machine must be configured without
+ // SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0
+ // and later. Before that, it's a 32-bit quantity (and gives the
+ // wrong answer on machines faster than 2^32 Hz). See
+ // http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html
+ // But also compare FreeBSD 7.0:
+ // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223
+ // 231 error = sysctl_handle_quad(oidp, &freq, 0, req);
+ // To FreeBSD 6.3 (it's the same in 6-STABLE):
+ // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131
+ // 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+#if __FreeBSD__ >= 7
+ uint64_t hz = 0;
+#else
+ unsigned int hz = 0;
+#endif
+ size_t sz = sizeof(hz);
+ const char *sysctl_path = "machdep.tsc_freq";
+ if ( sysctlbyname(sysctl_path, &hz, &sz, NULL, 0) != 0 ) {
+ fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
+ sysctl_path, strerror(errno));
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ } else {
+ cpuinfo_cycles_per_second = hz;
+ }
+ // TODO(csilvers): also figure out cpuinfo_num_cpus
+
+#elif defined(PLATFORM_WINDOWS)
+# pragma comment(lib, "shlwapi.lib") // for SHGetValue()
+ // In NT, read MHz from the registry. If we fail to do so or we're in win9x
+ // then make a crude estimate.
+ OSVERSIONINFO os;
+ os.dwOSVersionInfoSize = sizeof(os);
+ DWORD data, data_size = sizeof(data);
+ if (GetVersionEx(&os) &&
+ os.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ SUCCEEDED(SHGetValueA(HKEY_LOCAL_MACHINE,
+ "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
+ "~MHz", NULL, &data, &data_size)))
+ cpuinfo_cycles_per_second = (int64)data * (int64)(1000 * 1000); // was mhz
+ else
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(500); // TODO <500?
+
+ // Get the number of processors.
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ cpuinfo_num_cpus = info.dwNumberOfProcessors;
+
+#elif defined(__MACH__) && defined(__APPLE__)
+ // returning "mach time units" per second. the current number of elapsed
+ // mach time units can be found by calling uint64 mach_absolute_time();
+ // while not as precise as actual CPU cycles, it is accurate in the face
+ // of CPU frequency scaling and multi-cpu/core machines.
+ // Our mac users have these types of machines, and accuracy
+ // (i.e. correctness) trumps precision.
+ // See cycleclock.h: CycleClock::Now(), which returns number of mach time
+ // units on Mac OS X.
+ mach_timebase_info_data_t timebase_info;
+ mach_timebase_info(&timebase_info);
+ double mach_time_units_per_nanosecond =
+ static_cast<double>(timebase_info.denom) /
+ static_cast<double>(timebase_info.numer);
+ cpuinfo_cycles_per_second = mach_time_units_per_nanosecond * 1e9;
+
+ int num_cpus = 0;
+ size_t size = sizeof(num_cpus);
+ int numcpus_name[] = { CTL_HW, HW_NCPU };
+ if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, 0, 0)
+ == 0
+ && (size == sizeof(num_cpus)))
+ cpuinfo_num_cpus = num_cpus;
+
+#else
+ // Generic cycles per second counter
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+#endif
+}
+
+double CyclesPerSecond(void) {
+ InitializeSystemInfo();
+ return cpuinfo_cycles_per_second;
+}
+
+int NumCPUs(void) {
+ InitializeSystemInfo();
+ return cpuinfo_num_cpus;
+}
+
+// ----------------------------------------------------------------------
+// HasPosixThreads()
+// Return true if we're running POSIX (e.g., NPTL on Linux)
+// threads, as opposed to a non-POSIX thread libary. 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.
+// ----------------------------------------------------------------------
+bool HasPosixThreads() {
+// Android doesn't have confstr(), assume posix thread and fallback to
+// "other os".
+#if defined(__linux__) && !defined(__ANDROID__)
+#ifndef _CS_GNU_LIBPTHREAD_VERSION
+#define _CS_GNU_LIBPTHREAD_VERSION 3
+#endif
+ char buf[32];
+ // We assume that, if confstr() doesn't know about this name, then
+ // the same glibc is providing LinuxThreads.
+ if (confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)) == 0)
+ return false;
+ return strncmp(buf, "NPTL", 4) == 0;
+#elif defined(PLATFORM_WINDOWS) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+ return false;
+#else // other OS
+ return true; // Assume that everything else has Posix
+#endif // else OS_LINUX
+}
+
+// ----------------------------------------------------------------------
+
+#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<int>(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<uint32_t kMagic, uint32_t kLCSegment,
+ typename MachHeader, typename SegmentCommand>
+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<char*>(_dyld_get_image_name(current_image));
+ if (file_mapping) *file_mapping = 0;
+ if (file_pages) *file_pages = 0; // could we use sc->filesize?
+ if (anon_mapping) *anon_mapping = 0;
+ if (anon_pages) *anon_pages = 0;
+ if (dev) *dev = 0;
+ return true;
+ }
+
+ 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<class T>
+static T StringToInteger(char *text, char **endptr, int base) {
+ assert(false);
+ return T();
+}
+
+template<>
+int StringToInteger<int>(char *text, char **endptr, int base) {
+ return strtol(text, endptr, base);
+}
+
+template<>
+int64 StringToInteger<int64>(char *text, char **endptr, int base) {
+ return strtoll(text, endptr, base);
+}
+
+template<>
+uint64 StringToInteger<uint64>(char *text, char **endptr, int base) {
+ return strtoull(text, endptr, base);
+}
+
+template<typename T>
+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<T>(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<typename T>
+static bool StringToIntegerUntilCharWithCheck(
+ T *outptr, char *text, int base, int c, char **endptr) {
+ *outptr = StringToIntegerUntilChar<T>(*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<char *>(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<char *>(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<prmap_t*>(ibuf_);
+ // Best-effort attempt to get the inode from the filename. I think the
+ // two middle ints are major and minor device numbers, but I'm not sure.
+ sscanf(mapinfo->pr_mapname, "ufs.%*d.%*d.%ld", &inode_from_mapname);
+
+ if (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<int>(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<MH_MAGIC_64, LC_SEGMENT_64,
+ struct mach_header_64, struct segment_command_64>(
+ 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<MH_MAGIC, LC_SEGMENT,
+ struct mach_header, struct segment_command>(
+ 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<DWORD_PTR>(module_.modBaseAddr);
+ if (start) *start = base_addr;
+ if (end) *end = base_addr + module_.modBaseSize;
+ if (flags) *flags = kDefaultPerms;
+ if (offset) *offset = 0;
+ if (inode) *inode = 0;
+ if (filename) *filename = module_.szExePath;
+ if (file_mapping) *file_mapping = 0;
+ if (file_pages) *file_pages = 0;
+ if (anon_mapping) *anon_mapping = 0;
+ if (anon_pages) *anon_pages = 0;
+ if (dev) *dev = 0;
+ return true;
+ }
+#endif
+
+ // We didn't find anything
+ return false;
+}
+
+int ProcMapsIterator::FormatLine(char* buffer, int bufsize,
+ uint64 start, uint64 end, const char *flags,
+ uint64 offset, int64 inode,
+ const char *filename, dev_t dev) {
+ // We assume 'flags' looks like 'rwxp' or 'rwx'.
+ char r = (flags && flags[0] == 'r') ? 'r' : '-';
+ char w = (flags && flags[0] && flags[1] == 'w') ? 'w' : '-';
+ char x = (flags && flags[0] && flags[1] && flags[2] == 'x') ? 'x' : '-';
+ // p always seems set on linux, so we set the default to 'p', not '-'
+ char p = (flags && flags[0] && flags[1] && flags[2] && flags[3] != 'p')
+ ? '-' : 'p';
+
+ const int rc = snprintf(buffer, bufsize,
+ "%08" PRIx64 "-%08" PRIx64 " %c%c%c%c %08" PRIx64 " "
+ "%02x:%02x %-11" PRId64 " %s\n",
+ start, end, r,w,x,p, offset,
+ static_cast<int>(dev/256), static_cast<int>(dev%256),
+ inode, filename);
+ return (rc < 0 || rc >= bufsize) ? 0 : rc;
+}
+
+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/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.h b/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.h
new file mode 100644
index 00000000000..7935855d67f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/sysinfo.h
@@ -0,0 +1,235 @@
+// 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 <config.h>
+
+#include <time.h>
+#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
+#include <windows.h> // for DWORD
+#include <TlHelp32.h> // for CreateToolhelp32Snapshot
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for pid_t
+#endif
+#include <stddef.h> // for size_t
+#include <limits.h> // 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 NumCPUs();
+
+void SleepForMilliseconds(int milliseconds);
+
+// processor cycles per second of each processor. Thread-safe.
+extern double CyclesPerSecond(void);
+
+
+// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
+// as opposed to a non-POSIX thread libary. 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):
+ // <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
+ // <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
+ // eg
+ // 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
+ // If you don't have the dev_t (dev), feel free to pass in 0.
+ // (Next() doesn't return a dev_t, though NextExt does.)
+ //
+ // Note: if filename and flags were obtained via a call to Next(),
+ // then the output of this function is only valid if Next() returned
+ // true, and only until the iterator is destroyed or Next() is
+ // called again. (Since filename, at least, points into CurrentLine.)
+ static int FormatLine(char* buffer, int bufsize,
+ uint64 start, uint64 end, const char *flags,
+ uint64 offset, int64 inode, const char *filename,
+ dev_t dev);
+
+ // Find the next entry in /proc/maps; return true if found or false
+ // if at the end of the file.
+ //
+ // 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/chromium/third_party/tcmalloc/chromium/src/base/thread_annotations.h b/chromium/third_party/tcmalloc/chromium/src/base/thread_annotations.h
new file mode 100644
index 00000000000..f57b2999ee7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/thread_annotations.h
@@ -0,0 +1,134 @@
+// 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 GCC's "attributes" extension.
+// Using the macros defined here instead of the raw GCC 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(__GNUC__) \
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \
+ && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
+#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(x))
+
+#define SHARED_LOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x))
+
+#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x))
+
+#define SHARED_TRYLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x))
+
+#define UNLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock(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/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.c b/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.c
new file mode 100644
index 00000000000..bc180dba7a9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.c
@@ -0,0 +1,77 @@
+/* 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 <stdio.h> /* needed for NULL on some powerpc platforms (?!) */
+#ifdef HAVE_SYS_PRCTL
+# include <sys/prctl.h>
+#endif
+#include "base/thread_lister.h"
+#include "base/linuxthreads.h"
+/* Include other thread listers here that define THREADS macro
+ * 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 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 ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) {
+ return 1;
+}
+
+#endif /* ifndef THREADS */
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.h b/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.h
new file mode 100644
index 00000000000..6afe4dd1c72
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/thread_lister.h
@@ -0,0 +1,82 @@
+/* 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 <stdarg.h>
+#include <sys/types.h>
+
+#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 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
+ * 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 ListAllProcessThreads(void *parameter,
+ ListAllProcessThreadsCallBack callback, ...);
+
+/* This function resumes the list of all linux threads that
+ * 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 ResumeAllProcessThreads(int num_threads, pid_t *thread_pids);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _THREAD_LISTER_H */
diff --git a/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.cc b/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.cc
new file mode 100644
index 00000000000..767ee5f58f0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.cc
@@ -0,0 +1,189 @@
+// 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 <fcntl.h>
+#include <stddef.h> // for ptrdiff_t
+
+#include "base/atomicops.h" // for MemoryBarrier
+#include "base/linux_syscall_support.h"
+#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::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU;
+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;
+ getcpu_fn_ = &GetCPUViaSyscall;
+ return NULL;
+ }
+ int fd = open("/proc/self/auxv", O_RDONLY);
+ if (fd == -1) {
+ // Kernel too old to have a VDSO.
+ vdso_base_ = NULL;
+ getcpu_fn_ = &GetCPUViaSyscall;
+ 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<void *>(aux.a_un.a_val);
+ break;
+ }
+ }
+ close(fd);
+ if (vdso_base_ == ElfMemImage::kInvalidBase) {
+ // Didn't find AT_SYSINFO_EHDR in auxv[].
+ vdso_base_ = NULL;
+ }
+ }
+ GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present.
+ if (vdso_base_) {
+ VDSOSupport vdso;
+ SymbolInfo info;
+ if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) {
+ // Casting from an int to a pointer is not legal C++. To emphasize
+ // this, we use a C-style cast rather than a C++-style cast.
+ fn = (GetCpuFn)(info.address);
+ }
+ }
+ // Subtle: this code runs outside of any locks; prevent compiler
+ // from assigning to getcpu_fn_ more than once.
+ base::subtle::MemoryBarrier();
+ getcpu_fn_ = fn;
+ 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);
+ // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO.
+ getcpu_fn_ = &InitAndGetCPU;
+ 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);
+}
+
+// NOLINT on 'long' because this routine mimics kernel api.
+long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT
+#if defined(__NR_getcpu)
+ return sys_getcpu(cpu, NULL, NULL);
+#else
+ // x86_64 never implemented sys_getcpu(), except as a VDSO call.
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+// Use fast __vdso_getcpu if available.
+long VDSOSupport::InitAndGetCPU(unsigned *cpu, void *x, void *y) { // NOLINT
+ Init();
+ CHECK_NE(getcpu_fn_, &InitAndGetCPU); // << "Init() did not set getcpu_fn_";
+ return (*getcpu_fn_)(cpu, x, y);
+}
+
+// This function must be very fast, and may be called from very
+// low level (e.g. tcmalloc). Hence I avoid things like
+// GoogleOnceInit() and ::operator new.
+int GetCPU(void) {
+ unsigned cpu;
+ int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, NULL, NULL);
+ return ret_code == 0 ? cpu : ret_code;
+}
+
+// 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/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.h b/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.h
new file mode 100644
index 00000000000..b97ab254d38
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/base/vdso_support.h
@@ -0,0 +1,155 @@
+// 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<FN>(info.address);
+// }
+
+#ifndef BASE_VDSO_SUPPORT_H_
+#define BASE_VDSO_SUPPORT_H_
+
+#include <config.h>
+#include "base/basictypes.h"
+#include "base/elf_mem_image.h"
+
+#ifdef HAVE_ELF_MEM_IMAGE
+
+#define HAVE_VDSO_SUPPORT 1
+
+#include <stdlib.h> // 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_;
+
+ // NOLINT on 'long' because these routines mimic kernel api.
+ // The 'cache' parameter may be used by some versions of the kernel,
+ // and should be NULL or point to a static buffer containing at
+ // least two 'long's.
+ static long InitAndGetCPU(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+ static long GetCPUViaSyscall(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+ typedef long (*GetCpuFn)(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+
+ // This function pointer may point to InitAndGetCPU,
+ // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization.
+ static GetCpuFn getcpu_fn_;
+
+ friend int GetCPU(void); // Needs access to getcpu_fn_.
+
+ DISALLOW_COPY_AND_ASSIGN(VDSOSupport);
+};
+
+// Same as sched_getcpu() on later glibc versions.
+// Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present,
+// otherwise use syscall(SYS_getcpu,...).
+// May return -1 with errno == ENOSYS if the kernel doesn't
+// support SYS_getcpu.
+int GetCPU();
+} // namespace base
+
+#endif // HAVE_ELF_MEM_IMAGE
+
+#endif // BASE_VDSO_SUPPORT_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/central_freelist.cc b/chromium/third_party/tcmalloc/chromium/src/central_freelist.cc
new file mode 100644
index 00000000000..0f8a5c07eb6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/central_freelist.cc
@@ -0,0 +1,372 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include <algorithm>
+#include "central_freelist.h"
+#include "free_list.h" // for FL_Next, FL_Push, etc
+#include "internal_logging.h" // for ASSERT, MESSAGE
+#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 = FL_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<uintptr_t>(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);
+ Event(span, 'N', 0);
+ }
+
+ // 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 = FL_Next(p)){
+ ASSERT(p != object);
+ got++;
+ }
+ ASSERT(got + span->refcount ==
+ (span->length<<kPageShift) /
+ Static::sizemap()->ByteSizeForClass(span->sizeclass));
+ }
+
+ counter_++;
+ span->refcount--;
+ if (span->refcount == 0) {
+ Event(span, '#', 0);
+ counter_ -= ((span->length<<kPageShift) /
+ Static::sizemap()->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 {
+ FL_Push(&(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 >= kNumClasses) {
+ while (t >= kNumClasses) {
+ t -= kNumClasses;
+ }
+ race_counter = t;
+ }
+ ASSERT(t >= 0);
+ ASSERT(t < kNumClasses);
+ 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;
+ void* head = NULL;
+ void* tail = NULL;
+ // TODO: Prefetch multiple TCEntries?
+ tail = FetchFromSpansSafe();
+ if (tail != NULL) {
+ FL_Push(&head, tail);
+ result = 1;
+ while (result < N) {
+ void *t = FetchFromSpans();
+ if (!t) break;
+ FL_Push(&head, t);
+ result++;
+ }
+ }
+ lock_.Unlock();
+ *start = head;
+ *end = tail;
+ return result;
+}
+
+
+void* CentralFreeList::FetchFromSpansSafe() {
+ void *t = FetchFromSpans();
+ if (!t) {
+ Populate();
+ t = FetchFromSpans();
+ }
+ return t;
+}
+
+void* CentralFreeList::FetchFromSpans() {
+ if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL;
+ Span* span = nonempty_.next;
+
+ ASSERT(span->objects != NULL);
+ span->refcount++;
+ void *result = FL_Pop(&(span->objects));
+ if (span->objects == NULL) {
+ // Move to empty list
+ tcmalloc::DLL_Remove(span);
+ tcmalloc::DLL_Prepend(&empty_, span);
+ Event(span, 'E', 0);
+ }
+ counter_--;
+ 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()->CacheSizeClass(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* list = NULL;
+ char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
+ char* limit = ptr + (npages << kPageShift);
+ const size_t size = Static::sizemap()->ByteSizeForClass(size_class_);
+ int num = 0;
+ while (ptr + size <= limit) {
+ FL_Push(&list, ptr);
+ ptr += size;
+ num++;
+ }
+ ASSERT(ptr <= limit);
+ span->objects = list;
+ 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/chromium/third_party/tcmalloc/chromium/src/central_freelist.h b/chromium/third_party/tcmalloc/chromium/src/central_freelist.h
new file mode 100644
index 00000000000..4fd5799de9a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/central_freelist.h
@@ -0,0 +1,200 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_CENTRAL_FREELIST_H_
+#define TCMALLOC_CENTRAL_FREELIST_H_
+
+#include "config.h"
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // 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();
+
+ 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.
+ void* FetchFromSpans() 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.
+ void* FetchFromSpansSafe() 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<int kFreeListSizeMod64>
+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/chromium/third_party/tcmalloc/chromium/src/common.cc b/chromium/third_party/tcmalloc/chromium/src/common.cc
new file mode 100644
index 00000000000..5a55b390839
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/common.cc
@@ -0,0 +1,222 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include "common.h"
+#include "system-alloc.h"
+
+#if defined(HAVE_UNISTD_H) && defined(HAVE_GETPAGESIZE)
+#include <unistd.h> // for getpagesize
+#endif
+
+namespace tcmalloc {
+
+// 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 >= 16) {
+ // We need an alignment of at least 16 bytes to satisfy
+ // requirements for some SSE types.
+ alignment = 16;
+ }
+ // Maximum alignment allowed is page size alignment.
+ if (alignment > kPageSize) {
+ alignment = kPageSize;
+ }
+ CHECK_CONDITION(size < 16 || alignment >= 16);
+ 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<int>(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 > 32) num = 32;
+
+ return num;
+}
+
+// Initialize the mapping arrays
+void SizeMap::Init() {
+ // 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 <= 16);
+ for (size_t size = kMinClassSize; 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++;
+ }
+ if (sc != kNumClasses) {
+ Log(kCrash, __FILE__, __LINE__,
+ "wrong number of size classes: (found vs. expected )", sc, kNumClasses);
+ }
+
+ // Initialize the mapping arrays
+ int next_size = 0;
+ for (int c = 1; c < kNumClasses; 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; size++) {
+ const int sc = SizeClass(size);
+ if (sc <= 0 || sc >= kNumClasses) {
+ 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);
+ }
+ }
+
+ // Initialize the num_objects_to_move array.
+ for (size_t cl = 1; cl < kNumClasses; ++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 uint64_t metadata_unmapped_bytes_ = 0;
+
+void* MetaDataAlloc(size_t bytes) {
+ static size_t pagesize;
+#ifdef HAVE_GETPAGESIZE
+ if (pagesize == 0)
+ pagesize = getpagesize();
+#endif
+
+ void* result = TCMalloc_SystemAlloc(bytes, NULL, pagesize);
+ if (result != NULL) {
+ metadata_system_bytes_ += bytes;
+ }
+ return result;
+}
+
+uint64_t metadata_system_bytes() { return metadata_system_bytes_; }
+uint64_t metadata_unmapped_bytes() { return metadata_unmapped_bytes_; }
+
+void update_metadata_system_bytes(int diff) {
+ metadata_system_bytes_ += diff;
+}
+void update_metadata_unmapped_bytes(int diff) {
+ metadata_unmapped_bytes_ += diff;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/common.h b/chromium/third_party/tcmalloc/chromium/src/common.h
new file mode 100644
index 00000000000..c8ceb61ca6e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/common.h
@@ -0,0 +1,269 @@
+// 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 <opensource@google.com>
+//
+// Common definitions for tcmalloc code.
+
+#ifndef TCMALLOC_COMMON_H_
+#define TCMALLOC_COMMON_H_
+
+#include "config.h"
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t, uint64_t
+#endif
+#include "free_list.h" // for SIZE_CLASS macros
+#include "internal_logging.h" // for ASSERT, 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
+//-------------------------------------------------------------------
+
+// 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.
+
+static const size_t kAlignment = 8;
+
+// Constants dependant on tcmalloc configuration and archetecture. Chromium
+// tunes these constants.
+// We need to guarantee the smallest class size is big enough to hold the
+// pointers that form the free list.
+static const size_t kNumFreeListPointers =
+ (tcmalloc::kSupportsDoublyLinkedList ? 2 : 1);
+static const size_t kLinkSize = kNumFreeListPointers * sizeof(void *);
+static const size_t kMinClassSize =
+ (kLinkSize > kAlignment ? kLinkSize : kAlignment);
+static const size_t kSkippedClasses = (kAlignment < kMinClassSize ? 1 : 0);
+
+#if defined(TCMALLOC_LARGE_PAGES)
+static const size_t kPageShift = 15;
+static const size_t kNumClasses = 78 - kSkippedClasses;
+#else
+// Original TCMalloc code used kPageShift == 13. In Chromium, we changed
+// this to 12 (as was done in prior versions of TCMalloc).
+static const size_t kPageShift = 12;
+static const size_t kNumClasses = 54 - kSkippedClasses;
+#endif
+static const size_t kMaxThreadCacheSize = 4 << 20;
+
+static const size_t kPageSize = 1 << kPageShift;
+// Original TCMalloc code used kMaxSize == 256 * 1024. In Chromium, we
+// changed this to 32K, and represent it in terms of page size (as was done
+// in prior versions of TCMalloc).
+static const size_t kMaxSize = 8u * kPageSize;
+// For all span-lengths < kMaxPages we keep an exact-size list.
+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<Length>(0)) >> kPageShift;
+
+#if defined __x86_64__
+// All current and planned x86_64 processors only look at the lower 48 bits
+// in virtual to physical address translation. The top 16 are thus unused.
+// TODO(rus): Under what operating systems can we increase it safely to 17?
+// This lets us use smaller page maps. On first allocation, a 36-bit page map
+// uses only 96 KB instead of the 4.5 MB used by a 52-bit page map.
+static const int kAddressBits = (sizeof(void*) < 8 ? (8 * sizeof(void*)) : 48);
+#else
+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:
+ // 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_[kNumClasses];
+
+ //-------------------------------------------------------------------
+ // 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];
+
+ // Compute index of the class_array[] entry for a given size
+ static inline int ClassIndex(int s) {
+ ASSERT(0 <= s);
+ ASSERT(s <= kMaxSize);
+ const bool big = (s > kMaxSmallSize);
+ const int add_amount = big ? (127 + (120<<7)) : 7;
+ const int shift_amount = big ? 7 : 3;
+ return (s + add_amount) >> shift_amount;
+ }
+
+ int NumMoveSize(size_t size);
+
+ // Mapping from size class to max size storable in that class
+ size_t class_to_size_[kNumClasses];
+
+ // Mapping from size class to number of pages to allocate at a time
+ size_t class_to_pages_[kNumClasses];
+
+ public:
+ // 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(int size) {
+ return class_array_[ClassIndex(size)];
+ }
+
+ // Get the byte-size for a specified class
+ inline size_t ByteSizeForClass(size_t cl) {
+ return class_to_size_[cl];
+ }
+
+ // Mapping from size class to max size storable in that class
+ inline size_t class_to_size(size_t 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(size_t 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(size_t 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();
+uint64_t metadata_unmapped_bytes();
+
+// Adjust metadata_system_bytes to indicate that bytes are actually committed.
+// Requires pageheap_lock is held.
+void update_metadata_system_bytes(int diff);
+void update_metadata_unmapped_bytes(int diff);
+
+// 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/chromium/third_party/tcmalloc/chromium/src/config.h b/chromium/third_party/tcmalloc/chromium/src/config.h
new file mode 100644
index 00000000000..f2ac8f69e04
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONFIG_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "third_party/tcmalloc/chromium/src/config_win.h"
+#elif defined(OS_ANDROID)
+#include "third_party/tcmalloc/chromium/src/config_android.h"
+#elif defined(OS_LINUX)
+#include "third_party/tcmalloc/chromium/src/config_linux.h"
+#elif defined(OS_FREEBSD)
+#include "third_party/tcmalloc/chromium/src/config_freebsd.h"
+#endif
+
+#endif // CONFIG_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/config.h.in b/chromium/third_party/tcmalloc/chromium/src/config.h.in
new file mode 100644
index 00000000000..43f9f36f0f6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config.h.in
@@ -0,0 +1,277 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+
+#ifndef GPERFTOOLS_CONFIG_H_
+#define GPERFTOOLS_CONFIG_H_
+
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+#undef HAVE_BUILTIN_STACK_POINTER
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+#undef HAVE_CONFLICT_SIGNAL_H
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_UNAME
+
+/* 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 <dlfcn.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+#undef HAVE_LIBUNWIND_H
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#undef HAVE_LINUX_PTRACE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if the compiler implements namespaces */
+#undef HAVE_NAMESPACES
+
+/* Define to 1 if you have the <poll.h> 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
+
+/* Define to 1 if you have the <pwd.h> 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 <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if compiler supports __thread */
+#undef HAVE_TLS
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#undef HAVE_UNWIND_H
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+#undef HAVE___INT64
+
+/* 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 in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 'volatile' if __malloc_hook is declared volatile */
+#undef MALLOC_HOOK_MAYBE_VOLATILE
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* 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
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIdS
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIuS
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIxS
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#undef STL_NAMESPACE
+
+/* Version number of package */
+#undef VERSION
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
+
+#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
+
diff --git a/chromium/third_party/tcmalloc/chromium/src/config_android.h b/chromium/third_party/tcmalloc/chromium/src/config_android.h
new file mode 100644
index 00000000000..0743aade3ff
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config_android.h
@@ -0,0 +1,271 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+/* #undef HAVE_BUILTIN_STACK_POINTER */
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+/* #undef HAVE_CONFLICT_SIGNAL_H */
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
+ */
+#define HAVE_DECL_CFREE 1
+
+/* Define to 1 if you have the declaration of `memalign', and to 0 if you
+ don't. */
+#define HAVE_DECL_MEMALIGN 1
+
+/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
+ you don't. */
+#define HAVE_DECL_POSIX_MEMALIGN 1
+
+/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
+ don't. */
+#define HAVE_DECL_PVALLOC 1
+
+/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
+ */
+#define HAVE_DECL_UNAME 1
+
+/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
+ */
+#define HAVE_DECL_VALLOC 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if the system has the type `Elf32_Versym'. */
+#define HAVE_ELF32_VERSYM 1
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <features.h> header file. */
+#define HAVE_FEATURES_H 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+/* #undef HAVE_LIBUNWIND_H */
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#define HAVE_LINUX_PTRACE_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* define if libc has program_invocation_name */
+#undef HAVE_PROGRAM_INVOCATION_NAME
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK 1
+
+/* Define to 1 if you have the <sched.h> header file. */
+#define HAVE_SCHED_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct mallinfo'. */
+#define HAVE_STRUCT_MALLINFO 1
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#define HAVE_SYS_PRCTL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if compiler supports __thread */
+#undef HAVE_TLS
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#define HAVE_UNWIND_H 1
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+/* #undef HAVE___INT64 */
+
+/* prefix where we look for installed files */
+#define INSTALL_PREFIX "/usr/local"
+
+/* Define to 1 if int32_t is equivalent to intptr_t */
+/* #undef INT32_EQUALS_INTPTR */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "google-perftools"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "google-perftools"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "google-perftools 1.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "google-perftools"
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.7"
+
+/* How to access the PC from a struct ucontext */
+/* TODO(asharif): configure.ac should be changed such that this define gets
+ * generated automatically. That change should go to upstream and then pulled
+ * back here. */
+#if defined(__arm__)
+#define PC_FROM_UCONTEXT uc_mcontext.arm_pc
+#else
+#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
+#endif
+
+/* Always the empty-string on non-windows systems. On windows, should be
+ "__declspec(dllexport)". This way, when we compile the dll, we export our
+ functions/classes. It's safe to define this here because config.h is only
+ used internally, to compile the DLL, and every DLL source file #includes
+ "config.h" before anything else. */
+#define PERFTOOLS_DLL_DECL
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "zd"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "zu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "zx"
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#define VERSION "1.7"
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
+
+/* Android's NDK doesn't have std::set_new_handler */
+#define PREANSINEW 1
diff --git a/chromium/third_party/tcmalloc/chromium/src/config_for_unittests.h b/chromium/third_party/tcmalloc/chromium/src/config_for_unittests.h
new file mode 100644
index 00000000000..b418dbf2708
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config_for_unittests.h
@@ -0,0 +1,64 @@
+// 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/chromium/third_party/tcmalloc/chromium/src/config_freebsd.h b/chromium/third_party/tcmalloc/chromium/src/config_freebsd.h
new file mode 100644
index 00000000000..fbb917fc96c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config_freebsd.h
@@ -0,0 +1,278 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+/* #undef HAVE_BUILTIN_STACK_POINTER */
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+/* #undef HAVE_CONFLICT_SIGNAL_H */
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+/* #undef HAVE_CYGWIN_SIGNAL_H */
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#define HAVE_DECL_UNAME 1
+
+/* 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 <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if the system has the type `Elf32_Versym'. */
+#define HAVE_ELF32_VERSYM 1
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <features.h> header file. */
+/* #undef HAVE_FEATURES_H */
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the <glob.h> header file. */
+#define HAVE_GLOB_H 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+/* #undef HAVE_LIBUNWIND_H */
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+/* #undef HAVE_LINUX_PTRACE_H */
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* define if libc has program_invocation_name */
+/* #undef HAVE_PROGRAM_INVOCATION_NAME */
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK 1
+
+/* Define to 1 if you have the <sched.h> header file. */
+#define HAVE_SCHED_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+/* #undef HAVE_SYS_PRCTL_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#define HAVE_SYS_UCONTEXT_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if compiler supports __thread */
+#define HAVE_TLS 1
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+#define HAVE_UCONTEXT_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <unwind.h> header file. */
+/* #undef HAVE_UNWIND_H */
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+/* #undef HAVE_VALGRIND_H */
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if compiler supports __environ */
+/* #undef HAVE___ENVIRON */
+
+/* Define to 1 if the system has the type `__int64'. */
+/* #undef HAVE___INT64 */
+
+/* prefix where we look for installed files */
+#define INSTALL_PREFIX "/usr/local"
+
+/* Define to 1 if int32_t is equivalent to intptr_t */
+#if defined(__i386__)
+#define INT32_EQUALS_INTPTR 1
+#endif
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "google-perftools"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "google-perftools"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "google-perftools 1.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "google-perftools"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.7"
+
+/* How to access the PC from a struct ucontext */
+#if defined(__i386__)
+#define PC_FROM_UCONTEXT uc_mcontext.mc_eip
+#else
+#define PC_FROM_UCONTEXT uc_mcontext.mc_rip
+#endif
+
+/* Always the empty-string on non-windows systems. On windows, should be
+ "__declspec(dllexport)". This way, when we compile the dll, we export our
+ functions/classes. It's safe to define this here because config.h is only
+ used internally, to compile the DLL, and every DLL source file #includes
+ "config.h" before anything else. */
+#define PERFTOOLS_DLL_DECL /**/
+
+#if defined(__i386__)
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "d"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "u"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "x"
+#else
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "ld"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "lu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "lx"
+#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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#define VERSION "1.7"
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/config_linux.h b/chromium/third_party/tcmalloc/chromium/src/config_linux.h
new file mode 100644
index 00000000000..abf04426480
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config_linux.h
@@ -0,0 +1,268 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+/* #undef HAVE_BUILTIN_STACK_POINTER */
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+/* #undef HAVE_CONFLICT_SIGNAL_H */
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
+ */
+#define HAVE_DECL_CFREE 1
+
+/* Define to 1 if you have the declaration of `memalign', and to 0 if you
+ don't. */
+#define HAVE_DECL_MEMALIGN 1
+
+/* Define to 1 if you have the declaration of `posix_memalign', and to 0 if
+ you don't. */
+#define HAVE_DECL_POSIX_MEMALIGN 1
+
+/* Define to 1 if you have the declaration of `pvalloc', and to 0 if you
+ don't. */
+#define HAVE_DECL_PVALLOC 1
+
+/* Define to 1 if you have the declaration of `uname', and to 0 if you don't.
+ */
+#define HAVE_DECL_UNAME 1
+
+/* Define to 1 if you have the declaration of `valloc', and to 0 if you don't.
+ */
+#define HAVE_DECL_VALLOC 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if the system has the type `Elf32_Versym'. */
+#define HAVE_ELF32_VERSYM 1
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <features.h> header file. */
+#define HAVE_FEATURES_H 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the <glob.h> header file. */
+#define HAVE_GLOB_H 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+/* #undef HAVE_LIBUNWIND_H */
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#define HAVE_LINUX_PTRACE_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* define if libc has program_invocation_name */
+#define HAVE_PROGRAM_INVOCATION_NAME 1
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `sbrk' function. */
+#define HAVE_SBRK 1
+
+/* Define to 1 if you have the <sched.h> header file. */
+#define HAVE_SCHED_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `struct mallinfo'. */
+#define HAVE_STRUCT_MALLINFO 1
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#define HAVE_SYS_PRCTL_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if compiler supports __thread */
+#define HAVE_TLS 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#define HAVE_UCONTEXT_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#define HAVE_UNWIND_H 1
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+/* #undef HAVE___INT64 */
+
+/* prefix where we look for installed files */
+#define INSTALL_PREFIX "/usr/local"
+
+/* Define to 1 if int32_t is equivalent to intptr_t */
+/* #undef INT32_EQUALS_INTPTR */
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "google-perftools"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "google-perftools"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "google-perftools 1.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "google-perftools"
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.7"
+
+/* How to access the PC from a struct ucontext */
+/* TODO(asharif): configure.ac should be changed such that this define gets
+ * generated automatically. That change should go to upstream and then pulled
+ * back here. */
+#if defined(__arm__)
+#define PC_FROM_UCONTEXT uc_mcontext.arm_pc
+#else
+#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
+#endif
+
+/* Always the empty-string on non-windows systems. On windows, should be
+ "__declspec(dllexport)". This way, when we compile the dll, we export our
+ functions/classes. It's safe to define this here because config.h is only
+ used internally, to compile the DLL, and every DLL source file #includes
+ "config.h" before anything else. */
+#define PERFTOOLS_DLL_DECL
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "zd"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "zu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "zx"
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#define VERSION "1.7"
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/config_win.h b/chromium/third_party/tcmalloc/chromium/src/config_win.h
new file mode 100644
index 00000000000..e6506e44591
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/config_win.h
@@ -0,0 +1,311 @@
+/* A manual version of config.h fit for windows machines. */
+
+/* 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_
+
+/* define this if you are linking tcmalloc statically and overriding the
+ * default allocators.
+ * For instructions on how to use this mode, see
+ * http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
+ */
+#define WIN32_OVERRIDE_ALLOCATORS
+
+/* the location of <hash_map> */
+#define HASH_MAP_H <hash_map>
+
+/* the namespace of hash_map/hash_set */
+#define HASH_NAMESPACE stdext
+
+/* the location of <hash_set> */
+#define HASH_SET_H <hash_set>
+
+/* Define to 1 if your libc has a snprintf implementation */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+#undef HAVE_BUILTIN_STACK_POINTER
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+#undef HAVE_CONFLICT_SIGNAL_H
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_UNAME
+
+/* 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 <dlfcn.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1 /* we define it in windows/port.cc */
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* define if the compiler has hash_map */
+#define HAVE_HASH_MAP 1
+
+/* define if the compiler has hash_set */
+#define HAVE_HASH_SET 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+#undef HAVE_LIBUNWIND_H
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#undef HAVE_LINUX_PTRACE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> 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
+
+/* Define to 1 if you have the <pwd.h> 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 <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if compiler supports __thread */
+#undef HAVE_TLS
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#undef HAVE_UNWIND_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+#define HAVE___INT64 1
+
+/* 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 in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* 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. */
+#ifndef PERFTOOLS_DLL_DECL
+# define PERFTOOLS_IS_A_DLL 1 /* not set if you're statically linking */
+# define PERFTOOLS_DLL_DECL __declspec(dllexport)
+# define PERFTOOLS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
+#endif
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "Id"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "Iu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "Ix"
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#undef VERSION
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#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/chromium/third_party/tcmalloc/chromium/src/debugallocation.cc b/chromium/third_party/tcmalloc/chromium/src/debugallocation.cc
new file mode 100644
index 00000000000..7b09e412ec3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/debugallocation.cc
@@ -0,0 +1,1432 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#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 <malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# endif
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gperftools/malloc_extension.h>
+#include <gperftools/malloc_hook.h>
+#include <gperftools/stacktrace.h>
+#include "addressmap-inl.h"
+#include "base/abort.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"
+
+#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_FRANCE_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)");
+
+// ========================================================================= //
+
+// 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, ...)
+#ifdef __GNUC__
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+#else
+ ;
+#endif
+
+// The do_* functions are defined in tcmalloc/tcmalloc.cc,
+// which is included before this file
+// when TCMALLOC_FOR_DEBUGALLOCATION is defined
+// TODO(csilvers): get rid of these now that we are tied to tcmalloc.
+#define BASE_MALLOC_NEW do_malloc
+#define BASE_MALLOC do_malloc
+#define BASE_FREE do_free
+#define BASE_MALLOC_STATS do_malloc_stats
+#define BASE_MALLOPT do_mallopt
+#define BASE_MALLINFO do_mallinfo
+
+// ========================================================================= //
+
+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 <typename QueueEntry>
+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 =
+ GetStackTrace(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 BASE_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 int kMagicMalloc = 0xDEADBEEF;
+ static const int 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 BASE_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_;
+ int 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<int> 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<MallocBlockQueueEntry>* 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(int value) const {
+ return kMagicMMap == value || kMagicMalloc == value;
+ }
+
+ static size_t real_malloced_size(size_t size) {
+ return size + sizeof(MallocBlock);
+ }
+ static size_t real_mmapped_size(size_t size) {
+ return size + MallocBlock::data_offset();
+ }
+
+ 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_);
+ }
+
+ int* magic2_addr() { return (int*)(size2_addr() + 1); }
+ const int* magic2_addr() const { return (const int*)(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 = BASE_MALLOC(sizeof(AllocMap));
+ alloc_map_ = new(p) AllocMap(BASE_MALLOC, BASE_FREE);
+ }
+ alloc_map_->Insert(data_addr(), type);
+ // initialize us
+ size1_ = size;
+ offset_ = 0;
+ alloc_type_ = type;
+ if (!IsMMapped()) {
+ *magic2_addr() = magic1_;
+ *size2_addr() = size;
+ }
+ alloc_map_lock_.Unlock();
+ memset(data_addr(), kMagicUninitializedByte, size);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "should hold");
+ RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
+ }
+ }
+
+ size_t CheckAndClear(int type) {
+ alloc_map_lock_.Lock();
+ CheckLocked(type);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "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();
+ 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 (size1_ != *size2_addr()) {
+ RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
+ "has been corrupted", data_addr());
+ }
+ if (!IsValidMagicValue(*magic2_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: %"PRIuS"", 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*) (type == kMallocType ?
+ BASE_MALLOC(real_malloced_size(size)) :
+ BASE_MALLOC_NEW(real_malloced_size(size)));
+ }
+#else
+ b = (MallocBlock*) (type == kMallocType ?
+ BASE_MALLOC(real_malloced_size(size)) :
+ BASE_MALLOC_NEW(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) {
+ if (IsMMapped()) { // have to do this before CheckAndClear
+#ifdef HAVE_MMAP
+ int size = CheckAndClear(type);
+ 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);
+ 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<MallocBlockQueueEntry>;
+ 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]);
+ BASE_FREE(entries[i].block);
+ }
+ num_entries = 0;
+ free_queue_lock_.Lock();
+ }
+ }
+ RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
+ free_queue_lock_.Unlock();
+ for (int i = 0; i < num_entries; i++) {
+ CheckForDanglingWrites(entries[i]);
+ BASE_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) {
+ perftools_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<unsigned char*>(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<void*>(
+ 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<char*>(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<char*>(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<MallocBlock *>(
+ reinterpret_cast<char *>(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 memalign, and
+ // mb->offset_ is the distance backwards to the real header from mb,
+ // which is a fake header. The following subtraction works for both zero
+ // and non-zero values.
+ return reinterpret_cast<MallocBlock *>(
+ reinterpret_cast<char *>(mb) - mb->offset_);
+ }
+ static const MallocBlock* FromRawPointer(const void* p) {
+ // const-safe version: we just cast about
+ return FromRawPointer(const_cast<void*>(p));
+ }
+
+ // Return whether p points to memory returned by memalign.
+ // Requires that p be non-zero and has been checked for sanity with
+ // FromRawPointer().
+ static bool IsMemaligned(const void* p) {
+ const MallocBlock* mb = reinterpret_cast<const MallocBlock*>(
+ reinterpret_cast<const char*>(p) - MallocBlock::data_offset());
+ // If the offset is non-zero, the block was allocated by memalign
+ // (see FromRawPointer above).
+ return mb->offset_ != 0;
+ }
+
+ 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 int MallocBlock::kMagicMalloc;
+const int MallocBlock::kMagicMMap;
+
+MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
+SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
+
+FreeQueue<MallocBlockQueueEntry>* 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];
+ 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);
+ tcmalloc::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
+ trace_fd = open("/tmp/google.alloc", O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (trace_fd == -1) {
+ trace_fd = 2;
+ TracePrintf(trace_fd,
+ "Can't open /tmp/google.alloc. Logging to stderr.\n");
+ }
+ // Add a header to the log.
+ TracePrintf(trace_fd, "Trace started: %lu\n",
+ static_cast<unsigned long>(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%"PRIuS"\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) {
+ MALLOC_TRACE("free",
+ (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
+ ptr);
+ if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type);
+}
+
+// ========================================================================= //
+
+// 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) {
+ const MallocBlock* mb = MallocBlock::FromRawPointer(p);
+ return TCMallocImplementation::GetOwnership(mb);
+ }
+ return MallocExtension::kNotOwned; // nobody owns NULL
+ }
+
+ virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* 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<size_t>::max();
+ i.total_bytes_free = MallocBlock::FreeQueueSize();
+ v->push_back(i);
+ }
+
+ };
+
+static DebugMallocImplementation debug_malloc_implementation;
+
+REGISTER_MODULE_INITIALIZER(debugallocation, {
+ // 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()) {
+ MallocExtension::Register(&debug_malloc_implementation);
+ }
+});
+
+REGISTER_MODULE_DESTRUCTOR(debugallocation, {
+ if (!RunningOnValgrind()) {
+ // When the program exits, check all blocks still in the free
+ // queue for corruption.
+ DanglingWriteChecker();
+ }
+});
+
+// ========================================================================= //
+
+// 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) {
+ for (;;) {
+ void* p = DebugAllocate(size, new_type);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ 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 p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
+ return tc_new_mode ? debug_cpp_alloc(size, MallocBlock::kMallocType, true)
+ : DebugAllocate(size, MallocBlock::kMallocType);
+}
+
+// Exported routines
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) __THROW {
+ // 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW {
+ if (ptr == NULL) {
+ ptr = do_debug_malloc_or_debug_cpp_alloc(size);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+ }
+ MallocBlock* old = MallocBlock::FromRawPointer(ptr);
+ old->Check(MallocBlock::kMallocType);
+ if (MallocBlock::IsMemaligned(ptr)) {
+ RAW_LOG(FATAL, "realloc/memalign mismatch at %p: "
+ "non-NULL pointers passed to realloc must be obtained "
+ "from malloc, calloc, or realloc", ptr);
+ }
+ if (size == 0) {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+ return NULL;
+ }
+ 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;
+
+ memcpy(p->data_addr(), old->data_addr(),
+ (old->data_size() < size) ? old->data_size() : size);
+ MallocHook::InvokeDeleteHook(ptr);
+ MallocHook::InvokeNewHook(p->data_addr(), size);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+ 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 %"PRIuS" bytes: new failed.", size);
+ }
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+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 %"PRIuS" bytes: new[] failed.", size);
+ }
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
+ __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
+}
+
+// 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);
+}
+
+// This is mostly the same as do_memalign in tcmalloc.cc.
+static void *do_debug_memalign(size_t alignment, size_t size) {
+ // 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, MallocBlock::kMallocType);
+ if (p != 0) {
+ intptr_t orig_p = reinterpret_cast<intptr_t>(p);
+ // Leave data_offset bytes for fake header, and round up to meet
+ // alignment.
+ p = reinterpret_cast<void *>(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<MallocBlock *>(
+ reinterpret_cast<char *>(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.
+ fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
+ }
+ return p;
+}
+
+// This is mostly the same as cpp_memalign in tcmalloc.cc.
+static void* debug_cpp_memalign(size_t align, size_t size) {
+ for (;;) {
+ void* p = do_debug_memalign(align, size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh)
+ return 0;
+
+ // 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&) {
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
+ size_t size) {
+ return tc_new_mode ? debug_cpp_memalign(align, size)
+ : do_debug_memalign(align, size);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) __THROW {
+ void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ 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)
+ __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
+
+ void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ 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) __THROW {
+ // Allocate >= size bytes starting on a page boundary
+ void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
+ // 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);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+// malloc_stats just falls through to the base implementation.
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
+ BASE_MALLOC_STATS();
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
+ return BASE_MALLOPT(cmd, value);
+}
+
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
+ return BASE_MALLINFO();
+}
+#endif
+
+extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
+ return MallocExtension::instance()->GetAllocatedSize(ptr);
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.cc b/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.cc
new file mode 100644
index 00000000000..2b2d972e5ae
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.cc
@@ -0,0 +1,1128 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ---
+// Author: Sainbayar Sukhbaatar
+// Dai Mikurube
+//
+
+#include "deep-heap-profile.h"
+
+#ifdef USE_DEEP_HEAP_PROFILE
+#include <algorithm>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpagesize and getpid
+#endif // HAVE_UNISTD_H
+
+#if defined(__linux__)
+#include <endian.h>
+#if !defined(__LITTLE_ENDIAN__) and !defined(__BIG_ENDIAN__)
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define __BIG_ENDIAN__
+#endif // __BYTE_ORDER == __BIG_ENDIAN
+#endif // !defined(__LITTLE_ENDIAN__) and !defined(__BIG_ENDIAN__)
+#if defined(__BIG_ENDIAN__)
+#include <byteswap.h>
+#endif // defined(__BIG_ENDIAN__)
+#endif // defined(__linux__)
+
+#include "base/cycleclock.h"
+#include "base/sysinfo.h"
+#include "internal_logging.h" // for ASSERT, etc
+
+static const int kProfilerBufferSize = 1 << 20;
+static const int kHashTableSize = 179999; // Same as heap-profile-table.cc.
+
+static const int PAGEMAP_BYTES = 8;
+static const int KPAGECOUNT_BYTES = 8;
+static const uint64 MAX_ADDRESS = kuint64max;
+
+// Tag strings in heap profile dumps.
+static const char kProfileHeader[] = "heap profile: ";
+static const char kProfileVersion[] = "DUMP_DEEP_6";
+static const char kMetaInformationHeader[] = "META:\n";
+static const char kMMapListHeader[] = "MMAP_LIST:\n";
+static const char kGlobalStatsHeader[] = "GLOBAL_STATS:\n";
+static const char kStacktraceHeader[] = "STACKTRACES:\n";
+static const char kProcSelfMapsHeader[] = "\nMAPPED_LIBRARIES:\n";
+
+static const char kVirtualLabel[] = "virtual";
+static const char kCommittedLabel[] = "committed";
+
+#if defined(__linux__)
+
+bool DeepHeapProfile::AppendCommandLine(TextBuffer* buffer) {
+ RawFD fd;
+ char filename[100];
+ char cmdline[4096];
+ snprintf(filename, sizeof(filename), "/proc/%d/cmdline",
+ static_cast<int>(getpid()));
+ fd = open(filename, O_RDONLY);
+ if (fd == kIllegalRawFD) {
+ RAW_LOG(0, "Failed to open /proc/self/cmdline");
+ return false;
+ }
+
+ size_t length = read(fd, cmdline, sizeof(cmdline) - 1);
+ close(fd);
+
+ for (int i = 0; i < length; ++i)
+ if (cmdline[i] == '\0')
+ cmdline[i] = ' ';
+ cmdline[length] = '\0';
+
+ buffer->AppendString("CommandLine: ", 0);
+ buffer->AppendString(cmdline, 0);
+ buffer->AppendChar('\n');
+
+ return true;
+}
+
+#else // defined(__linux__)
+
+bool DeepHeapProfile::AppendCommandLine(TextBuffer* buffer) {
+ return false;
+}
+
+#endif // defined(__linux__)
+
+#if defined(__linux__)
+
+void DeepHeapProfile::MemoryInfoGetterLinux::Initialize() {
+ char filename[100];
+ snprintf(filename, sizeof(filename), "/proc/%d/pagemap",
+ static_cast<int>(getpid()));
+ pagemap_fd_ = open(filename, O_RDONLY);
+ RAW_CHECK(pagemap_fd_ != -1, "Failed to open /proc/self/pagemap");
+
+ if (pageframe_type_ == DUMP_PAGECOUNT) {
+ snprintf(filename, sizeof(filename), "/proc/kpagecount",
+ static_cast<int>(getpid()));
+ kpagecount_fd_ = open(filename, O_RDONLY);
+ if (kpagecount_fd_ == -1)
+ RAW_LOG(0, "Failed to open /proc/kpagecount");
+ }
+}
+
+size_t DeepHeapProfile::MemoryInfoGetterLinux::CommittedSize(
+ uint64 first_address,
+ uint64 last_address,
+ DeepHeapProfile::TextBuffer* buffer) const {
+ int page_size = getpagesize();
+ uint64 page_address = (first_address / page_size) * page_size;
+ size_t committed_size = 0;
+ size_t pageframe_list_length = 0;
+
+ Seek(first_address);
+
+ // Check every page on which the allocation resides.
+ while (page_address <= last_address) {
+ // Read corresponding physical page.
+ State state;
+ // TODO(dmikurube): Read pagemap in bulk for speed.
+ // TODO(dmikurube): Consider using mincore(2).
+ if (Read(&state, pageframe_type_ != DUMP_NO_PAGEFRAME) == false) {
+ // We can't read the last region (e.g vsyscall).
+#ifndef NDEBUG
+ RAW_LOG(0, "pagemap read failed @ %#llx %" PRId64 " bytes",
+ first_address, last_address - first_address + 1);
+#endif
+ return 0;
+ }
+
+ // Dump pageframes of resident pages. Non-resident pages are just skipped.
+ if (pageframe_type_ != DUMP_NO_PAGEFRAME &&
+ buffer != NULL && state.pfn != 0) {
+ if (pageframe_list_length == 0) {
+ buffer->AppendString(" PF:", 0);
+ pageframe_list_length = 5;
+ }
+ buffer->AppendChar(' ');
+ if (page_address < first_address)
+ buffer->AppendChar('<');
+ buffer->AppendBase64(state.pfn, 4);
+ pageframe_list_length += 5;
+ if (pageframe_type_ == DUMP_PAGECOUNT && IsPageCountAvailable()) {
+ uint64 pagecount = ReadPageCount(state.pfn);
+ // Assume pagecount == 63 if the pageframe is mapped more than 63 times.
+ if (pagecount > 63)
+ pagecount = 63;
+ buffer->AppendChar('#');
+ buffer->AppendBase64(pagecount, 1);
+ pageframe_list_length += 2;
+ }
+ if (last_address < page_address - 1 + page_size)
+ buffer->AppendChar('>');
+ // Begins a new line every 94 characters.
+ if (pageframe_list_length > 94) {
+ buffer->AppendChar('\n');
+ pageframe_list_length = 0;
+ }
+ }
+
+ if (state.is_committed) {
+ // Calculate the size of the allocation part in this page.
+ size_t bytes = page_size;
+
+ // If looking at the last page in a given region.
+ if (last_address <= page_address - 1 + page_size) {
+ bytes = last_address - page_address + 1;
+ }
+
+ // If looking at the first page in a given region.
+ if (page_address < first_address) {
+ bytes -= first_address - page_address;
+ }
+
+ committed_size += bytes;
+ }
+ if (page_address > MAX_ADDRESS - page_size) {
+ break;
+ }
+ page_address += page_size;
+ }
+
+ if (pageframe_type_ != DUMP_NO_PAGEFRAME &&
+ buffer != NULL && pageframe_list_length != 0) {
+ buffer->AppendChar('\n');
+ }
+
+ return committed_size;
+}
+
+uint64 DeepHeapProfile::MemoryInfoGetterLinux::ReadPageCount(uint64 pfn) const {
+ int64 index = pfn * KPAGECOUNT_BYTES;
+ int64 offset = lseek64(kpagecount_fd_, index, SEEK_SET);
+ RAW_DCHECK(offset == index, "Failed in seeking in kpagecount.");
+
+ uint64 kpagecount_value;
+ int result = read(kpagecount_fd_, &kpagecount_value, KPAGECOUNT_BYTES);
+ if (result != KPAGECOUNT_BYTES)
+ return 0;
+
+ return kpagecount_value;
+}
+
+bool DeepHeapProfile::MemoryInfoGetterLinux::Seek(uint64 address) const {
+ int64 index = (address / getpagesize()) * PAGEMAP_BYTES;
+ RAW_DCHECK(pagemap_fd_ != -1, "Failed to seek in /proc/self/pagemap");
+ int64 offset = lseek64(pagemap_fd_, index, SEEK_SET);
+ RAW_DCHECK(offset == index, "Failed in seeking.");
+ return offset >= 0;
+}
+
+bool DeepHeapProfile::MemoryInfoGetterLinux::Read(
+ State* state, bool get_pfn) const {
+ static const uint64 U64_1 = 1;
+ static const uint64 PFN_FILTER = (U64_1 << 55) - U64_1;
+ static const uint64 PAGE_PRESENT = U64_1 << 63;
+ static const uint64 PAGE_SWAP = U64_1 << 62;
+ static const uint64 PAGE_RESERVED = U64_1 << 61;
+ static const uint64 FLAG_NOPAGE = U64_1 << 20;
+ static const uint64 FLAG_KSM = U64_1 << 21;
+ static const uint64 FLAG_MMAP = U64_1 << 11;
+
+ uint64 pagemap_value;
+ RAW_DCHECK(pagemap_fd_ != -1, "Failed to read from /proc/self/pagemap");
+ int result = read(pagemap_fd_, &pagemap_value, PAGEMAP_BYTES);
+ if (result != PAGEMAP_BYTES) {
+ return false;
+ }
+
+ // Check if the page is committed.
+ state->is_committed = (pagemap_value & (PAGE_PRESENT | PAGE_SWAP));
+
+ state->is_present = (pagemap_value & PAGE_PRESENT);
+ state->is_swapped = (pagemap_value & PAGE_SWAP);
+ state->is_shared = false;
+
+ if (get_pfn && state->is_present && !state->is_swapped)
+ state->pfn = (pagemap_value & PFN_FILTER);
+ else
+ state->pfn = 0;
+
+ return true;
+}
+
+bool DeepHeapProfile::MemoryInfoGetterLinux::IsPageCountAvailable() const {
+ return kpagecount_fd_ != -1;
+}
+
+#endif // defined(__linux__)
+
+DeepHeapProfile::MemoryResidenceInfoGetterInterface::
+ MemoryResidenceInfoGetterInterface() {}
+
+DeepHeapProfile::MemoryResidenceInfoGetterInterface::
+ ~MemoryResidenceInfoGetterInterface() {}
+
+DeepHeapProfile::MemoryResidenceInfoGetterInterface*
+ DeepHeapProfile::MemoryResidenceInfoGetterInterface::Create(
+ PageFrameType pageframe_type) {
+#if defined(__linux__)
+ return new MemoryInfoGetterLinux(pageframe_type);
+#else
+ return NULL;
+#endif
+}
+
+DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile,
+ const char* prefix,
+ enum PageFrameType pageframe_type)
+ : memory_residence_info_getter_(
+ MemoryResidenceInfoGetterInterface::Create(pageframe_type)),
+ most_recent_pid_(-1),
+ stats_(),
+ dump_count_(0),
+ filename_prefix_(NULL),
+ deep_table_(kHashTableSize, heap_profile->alloc_, heap_profile->dealloc_),
+ pageframe_type_(pageframe_type),
+ heap_profile_(heap_profile) {
+ // Copy filename prefix.
+ const int prefix_length = strlen(prefix);
+ filename_prefix_ =
+ reinterpret_cast<char*>(heap_profile_->alloc_(prefix_length + 1));
+ memcpy(filename_prefix_, prefix, prefix_length);
+ filename_prefix_[prefix_length] = '\0';
+
+ strncpy(run_id_, "undetermined-run-id", sizeof(run_id_));
+}
+
+DeepHeapProfile::~DeepHeapProfile() {
+ heap_profile_->dealloc_(filename_prefix_);
+ delete memory_residence_info_getter_;
+}
+
+// Global malloc() should not be used in this function.
+// Use LowLevelAlloc if required.
+void DeepHeapProfile::DumpOrderedProfile(const char* reason,
+ char raw_buffer[],
+ int buffer_size,
+ RawFD fd) {
+ TextBuffer buffer(raw_buffer, buffer_size, fd);
+
+#ifndef NDEBUG
+ int64 starting_cycles = CycleClock::Now();
+#endif
+
+ // Get the time before starting snapshot.
+ // TODO(dmikurube): Consider gettimeofday if available.
+ time_t time_value = time(NULL);
+
+ ++dump_count_;
+
+ // Re-open files in /proc/pid/ if the process is newly forked one.
+ if (most_recent_pid_ != getpid()) {
+ char hostname[64];
+ if (0 == gethostname(hostname, sizeof(hostname))) {
+ char* dot = strchr(hostname, '.');
+ if (dot != NULL)
+ *dot = '\0';
+ } else {
+ strcpy(hostname, "unknown");
+ }
+
+ most_recent_pid_ = getpid();
+
+ snprintf(run_id_, sizeof(run_id_), "%s-linux-%d-%lu",
+ hostname, most_recent_pid_, time(NULL));
+
+ memory_residence_info_getter_->Initialize();
+ deep_table_.ResetIsLogged();
+
+ // Write maps into "|filename_prefix_|.<pid>.maps".
+ WriteProcMaps(filename_prefix_, raw_buffer, buffer_size);
+ }
+
+ // Reset committed sizes of buckets.
+ deep_table_.ResetCommittedSize();
+
+ // Record committed sizes.
+ stats_.SnapshotAllocations(this);
+
+ // TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
+ // glibc's snprintf internally allocates memory by alloca normally, but it
+ // allocates memory by malloc if large memory is required.
+
+ buffer.AppendString(kProfileHeader, 0);
+ buffer.AppendString(kProfileVersion, 0);
+ buffer.AppendString("\n", 0);
+
+ // Fill buffer with meta information.
+ buffer.AppendString(kMetaInformationHeader, 0);
+
+ buffer.AppendString("Time: ", 0);
+ buffer.AppendUnsignedLong(time_value, 0);
+ buffer.AppendChar('\n');
+
+ if (reason != NULL) {
+ buffer.AppendString("Reason: ", 0);
+ buffer.AppendString(reason, 0);
+ buffer.AppendChar('\n');
+ }
+
+ AppendCommandLine(&buffer);
+
+ buffer.AppendString("RunID: ", 0);
+ buffer.AppendString(run_id_, 0);
+ buffer.AppendChar('\n');
+
+ buffer.AppendString("PageSize: ", 0);
+ buffer.AppendInt(getpagesize(), 0, 0);
+ buffer.AppendChar('\n');
+
+ // Assumes the physical memory <= 64GB (PFN < 2^24).
+ if (pageframe_type_ == DUMP_PAGECOUNT &&
+ memory_residence_info_getter_->IsPageCountAvailable()) {
+ buffer.AppendString("PageFrame: 24,Base64,PageCount", 0);
+ buffer.AppendChar('\n');
+ } else if (pageframe_type_ != DUMP_NO_PAGEFRAME) {
+ buffer.AppendString("PageFrame: 24,Base64", 0);
+ buffer.AppendChar('\n');
+ }
+
+ // Fill buffer with the global stats.
+ buffer.AppendString(kMMapListHeader, 0);
+
+ stats_.SnapshotMaps(memory_residence_info_getter_, this, &buffer);
+
+ // Fill buffer with the global stats.
+ buffer.AppendString(kGlobalStatsHeader, 0);
+
+ stats_.Unparse(&buffer);
+
+ buffer.AppendString(kStacktraceHeader, 0);
+ buffer.AppendString(kVirtualLabel, 10);
+ buffer.AppendChar(' ');
+ buffer.AppendString(kCommittedLabel, 10);
+ buffer.AppendString("\n", 0);
+
+ // Fill buffer.
+ deep_table_.UnparseForStats(&buffer);
+
+ buffer.Flush();
+
+ // Write the bucket listing into a .bucket file.
+ deep_table_.WriteForBucketFile(
+ filename_prefix_, dump_count_, raw_buffer, buffer_size);
+
+#ifndef NDEBUG
+ int64 elapsed_cycles = CycleClock::Now() - starting_cycles;
+ double elapsed_seconds = elapsed_cycles / CyclesPerSecond();
+ RAW_LOG(0, "Time spent on DeepProfiler: %.3f sec\n", elapsed_seconds);
+#endif
+}
+
+int DeepHeapProfile::TextBuffer::Size() {
+ return size_;
+}
+
+int DeepHeapProfile::TextBuffer::FilledBytes() {
+ return cursor_;
+}
+
+void DeepHeapProfile::TextBuffer::Clear() {
+ cursor_ = 0;
+}
+
+void DeepHeapProfile::TextBuffer::Flush() {
+ RawWrite(fd_, buffer_, cursor_);
+ cursor_ = 0;
+}
+
+// TODO(dmikurube): These Append* functions should not use snprintf.
+bool DeepHeapProfile::TextBuffer::AppendChar(char value) {
+ return ForwardCursor(snprintf(buffer_ + cursor_, size_ - cursor_,
+ "%c", value));
+}
+
+bool DeepHeapProfile::TextBuffer::AppendString(const char* value, int width) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%s", value);
+ else
+ appended = snprintf(position, available, "%*s",
+ width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendInt(int value, int width,
+ bool leading_zero) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%d", value);
+ else if (leading_zero)
+ appended = snprintf(position, available, "%0*d", width, value);
+ else
+ appended = snprintf(position, available, "%*d", width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendLong(long value, int width) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%ld", value);
+ else
+ appended = snprintf(position, available, "%*ld", width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendUnsignedLong(unsigned long value,
+ int width) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%lu", value);
+ else
+ appended = snprintf(position, available, "%*lu", width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendInt64(int64 value, int width) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%" PRId64, value);
+ else
+ appended = snprintf(position, available, "%*" PRId64, width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendPtr(uint64 value, int width) {
+ char* position = buffer_ + cursor_;
+ int available = size_ - cursor_;
+ int appended;
+ if (width == 0)
+ appended = snprintf(position, available, "%" PRIx64, value);
+ else
+ appended = snprintf(position, available, "%0*" PRIx64, width, value);
+ return ForwardCursor(appended);
+}
+
+bool DeepHeapProfile::TextBuffer::AppendBase64(uint64 value, int width) {
+ static const char base64[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#if defined(__BIG_ENDIAN__)
+ value = bswap_64(value);
+#endif
+ for (int shift = (width - 1) * 6; shift >= 0; shift -= 6) {
+ if (!AppendChar(base64[(value >> shift) & 0x3f]))
+ return false;
+ }
+ return true;
+}
+
+bool DeepHeapProfile::TextBuffer::ForwardCursor(int appended) {
+ if (appended < 0 || appended >= size_ - cursor_)
+ return false;
+ cursor_ += appended;
+ if (cursor_ > size_ * 4 / 5)
+ Flush();
+ return true;
+}
+
+void DeepHeapProfile::DeepBucket::UnparseForStats(TextBuffer* buffer) {
+ buffer->AppendInt64(bucket->alloc_size - bucket->free_size, 10);
+ buffer->AppendChar(' ');
+ buffer->AppendInt64(committed_size, 10);
+ buffer->AppendChar(' ');
+ buffer->AppendInt(bucket->allocs, 6, false);
+ buffer->AppendChar(' ');
+ buffer->AppendInt(bucket->frees, 6, false);
+ buffer->AppendString(" @ ", 0);
+ buffer->AppendInt(id, 0, false);
+ buffer->AppendString("\n", 0);
+}
+
+void DeepHeapProfile::DeepBucket::UnparseForBucketFile(TextBuffer* buffer) {
+ buffer->AppendInt(id, 0, false);
+ buffer->AppendChar(' ');
+ buffer->AppendString(is_mmap ? "mmap" : "malloc", 0);
+
+#if defined(TYPE_PROFILING)
+ buffer->AppendString(" t0x", 0);
+ buffer->AppendPtr(reinterpret_cast<uintptr_t>(type), 0);
+ if (type == NULL) {
+ buffer->AppendString(" nno_typeinfo", 0);
+ } else {
+ buffer->AppendString(" n", 0);
+ buffer->AppendString(type->name(), 0);
+ }
+#endif
+
+ for (int depth = 0; depth < bucket->depth; depth++) {
+ buffer->AppendString(" 0x", 0);
+ buffer->AppendPtr(reinterpret_cast<uintptr_t>(bucket->stack[depth]), 8);
+ }
+ buffer->AppendString("\n", 0);
+}
+
+DeepHeapProfile::DeepBucketTable::DeepBucketTable(
+ int table_size,
+ HeapProfileTable::Allocator alloc,
+ HeapProfileTable::DeAllocator dealloc)
+ : table_(NULL),
+ table_size_(table_size),
+ alloc_(alloc),
+ dealloc_(dealloc),
+ bucket_id_(0) {
+ const int bytes = table_size * sizeof(DeepBucket*);
+ table_ = reinterpret_cast<DeepBucket**>(alloc(bytes));
+ memset(table_, 0, bytes);
+}
+
+DeepHeapProfile::DeepBucketTable::~DeepBucketTable() {
+ ASSERT(table_ != NULL);
+ for (int db = 0; db < table_size_; db++) {
+ for (DeepBucket* x = table_[db]; x != 0; /**/) {
+ DeepBucket* db = x;
+ x = x->next;
+ dealloc_(db);
+ }
+ }
+ dealloc_(table_);
+}
+
+DeepHeapProfile::DeepBucket* DeepHeapProfile::DeepBucketTable::Lookup(
+ Bucket* bucket,
+#if defined(TYPE_PROFILING)
+ const std::type_info* type,
+#endif
+ bool is_mmap) {
+ // Make hash-value
+ uintptr_t h = 0;
+
+ AddToHashValue(reinterpret_cast<uintptr_t>(bucket), &h);
+ if (is_mmap) {
+ AddToHashValue(1, &h);
+ } else {
+ AddToHashValue(0, &h);
+ }
+
+#if defined(TYPE_PROFILING)
+ if (type == NULL) {
+ AddToHashValue(0, &h);
+ } else {
+ AddToHashValue(reinterpret_cast<uintptr_t>(type->name()), &h);
+ }
+#endif
+
+ FinishHashValue(&h);
+
+ // Lookup stack trace in table
+ unsigned int buck = ((unsigned int) h) % table_size_;
+ for (DeepBucket* db = table_[buck]; db != 0; db = db->next) {
+ if (db->bucket == bucket) {
+ return db;
+ }
+ }
+
+ // Create a new bucket
+ DeepBucket* db = reinterpret_cast<DeepBucket*>(alloc_(sizeof(DeepBucket)));
+ memset(db, 0, sizeof(*db));
+ db->bucket = bucket;
+#if defined(TYPE_PROFILING)
+ db->type = type;
+#endif
+ db->committed_size = 0;
+ db->is_mmap = is_mmap;
+ db->id = (bucket_id_++);
+ db->is_logged = false;
+ db->next = table_[buck];
+ table_[buck] = db;
+ return db;
+}
+
+// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
+void DeepHeapProfile::DeepBucketTable::UnparseForStats(TextBuffer* buffer) {
+ for (int i = 0; i < table_size_; i++) {
+ for (DeepBucket* deep_bucket = table_[i];
+ deep_bucket != NULL;
+ deep_bucket = deep_bucket->next) {
+ Bucket* bucket = deep_bucket->bucket;
+ if (bucket->alloc_size - bucket->free_size == 0) {
+ continue; // Skip empty buckets.
+ }
+ deep_bucket->UnparseForStats(buffer);
+ }
+ }
+}
+
+void DeepHeapProfile::DeepBucketTable::WriteForBucketFile(
+ const char* prefix, int dump_count, char raw_buffer[], int buffer_size) {
+ char filename[100];
+ snprintf(filename, sizeof(filename),
+ "%s.%05d.%04d.buckets", prefix, getpid(), dump_count);
+ RawFD fd = RawOpenForWriting(filename);
+ RAW_DCHECK(fd != kIllegalRawFD, "");
+
+ TextBuffer buffer(raw_buffer, buffer_size, fd);
+
+ for (int i = 0; i < table_size_; i++) {
+ for (DeepBucket* deep_bucket = table_[i];
+ deep_bucket != NULL;
+ deep_bucket = deep_bucket->next) {
+ Bucket* bucket = deep_bucket->bucket;
+ if (deep_bucket->is_logged) {
+ continue; // Skip the bucket if it is already logged.
+ }
+ if (!deep_bucket->is_mmap &&
+ bucket->alloc_size - bucket->free_size <= 64) {
+ continue; // Skip small malloc buckets.
+ }
+
+ deep_bucket->UnparseForBucketFile(&buffer);
+ deep_bucket->is_logged = true;
+ }
+ }
+
+ buffer.Flush();
+ RawClose(fd);
+}
+
+void DeepHeapProfile::DeepBucketTable::ResetCommittedSize() {
+ for (int i = 0; i < table_size_; i++) {
+ for (DeepBucket* deep_bucket = table_[i];
+ deep_bucket != NULL;
+ deep_bucket = deep_bucket->next) {
+ deep_bucket->committed_size = 0;
+ }
+ }
+}
+
+void DeepHeapProfile::DeepBucketTable::ResetIsLogged() {
+ for (int i = 0; i < table_size_; i++) {
+ for (DeepBucket* deep_bucket = table_[i];
+ deep_bucket != NULL;
+ deep_bucket = deep_bucket->next) {
+ deep_bucket->is_logged = false;
+ }
+ }
+}
+
+// This hash function is from HeapProfileTable::GetBucket.
+// static
+void DeepHeapProfile::DeepBucketTable::AddToHashValue(
+ uintptr_t add, uintptr_t* hash_value) {
+ *hash_value += add;
+ *hash_value += *hash_value << 10;
+ *hash_value ^= *hash_value >> 6;
+}
+
+// This hash function is from HeapProfileTable::GetBucket.
+// static
+void DeepHeapProfile::DeepBucketTable::FinishHashValue(uintptr_t* hash_value) {
+ *hash_value += *hash_value << 3;
+ *hash_value ^= *hash_value >> 11;
+}
+
+void DeepHeapProfile::RegionStats::Initialize() {
+ virtual_bytes_ = 0;
+ committed_bytes_ = 0;
+}
+
+uint64 DeepHeapProfile::RegionStats::Record(
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ uint64 first_address,
+ uint64 last_address,
+ TextBuffer* buffer) {
+ uint64 committed;
+ virtual_bytes_ += static_cast<size_t>(last_address - first_address + 1);
+ committed = memory_residence_info_getter->CommittedSize(first_address,
+ last_address,
+ buffer);
+ committed_bytes_ += committed;
+ return committed;
+}
+
+void DeepHeapProfile::RegionStats::Unparse(const char* name,
+ TextBuffer* buffer) {
+ buffer->AppendString(name, 25);
+ buffer->AppendChar(' ');
+ buffer->AppendLong(virtual_bytes_, 12);
+ buffer->AppendChar(' ');
+ buffer->AppendLong(committed_bytes_, 12);
+ buffer->AppendString("\n", 0);
+}
+
+// Snapshots all virtual memory mappging stats by merging mmap(2) records from
+// MemoryRegionMap and /proc/maps, the OS-level memory mapping information.
+// Memory regions described in /proc/maps, but which are not created by mmap,
+// are accounted as "unhooked" memory regions.
+//
+// This function assumes that every memory region created by mmap is covered
+// by VMA(s) described in /proc/maps except for http://crbug.com/189114.
+// Note that memory regions created with mmap don't align with borders of VMAs
+// in /proc/maps. In other words, a memory region by mmap can cut across many
+// VMAs. Also, of course a VMA can include many memory regions by mmap.
+// It means that the following situation happens:
+//
+// => Virtual address
+// <----- VMA #1 -----><----- VMA #2 ----->...<----- VMA #3 -----><- VMA #4 ->
+// ..< mmap #1 >.<- mmap #2 -><- mmap #3 ->...<- mmap #4 ->..<-- mmap #5 -->..
+//
+// It can happen easily as permission can be changed by mprotect(2) for a part
+// of a memory region. A change in permission splits VMA(s).
+//
+// To deal with the situation, this function iterates over MemoryRegionMap and
+// /proc/maps independently. The iterator for MemoryRegionMap is initialized
+// at the top outside the loop for /proc/maps, and it goes forward inside the
+// loop while comparing their addresses.
+//
+// TODO(dmikurube): Eliminate dynamic memory allocation caused by snprintf.
+void DeepHeapProfile::GlobalStats::SnapshotMaps(
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ DeepHeapProfile* deep_profile,
+ TextBuffer* mmap_dump_buffer) {
+ MemoryRegionMap::LockHolder lock_holder;
+ ProcMapsIterator::Buffer procmaps_iter_buffer;
+ ProcMapsIterator procmaps_iter(0, &procmaps_iter_buffer);
+ uint64 vma_start_addr, vma_last_addr, offset;
+ int64 inode;
+ char* flags;
+ char* filename;
+ enum MapsRegionType type;
+ for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
+ all_[i].Initialize();
+ unhooked_[i].Initialize();
+ }
+ profiled_mmap_.Initialize();
+
+ MemoryRegionMap::RegionIterator mmap_iter =
+ MemoryRegionMap::BeginRegionLocked();
+ DeepBucket* deep_bucket = NULL;
+ if (mmap_iter != MemoryRegionMap::EndRegionLocked()) {
+ deep_bucket = GetInformationOfMemoryRegion(
+ mmap_iter, memory_residence_info_getter, deep_profile);
+ }
+
+ while (procmaps_iter.Next(&vma_start_addr, &vma_last_addr,
+ &flags, &offset, &inode, &filename)) {
+ if (mmap_dump_buffer) {
+ char buffer[1024];
+ int written = procmaps_iter.FormatLine(buffer, sizeof(buffer),
+ vma_start_addr, vma_last_addr,
+ flags, offset, inode, filename, 0);
+ mmap_dump_buffer->AppendString(buffer, 0);
+ }
+
+ // 'vma_last_addr' should be the last inclusive address of the region.
+ vma_last_addr -= 1;
+ if (strcmp("[vsyscall]", filename) == 0) {
+ continue; // Reading pagemap will fail in [vsyscall].
+ }
+
+ // TODO(dmikurube): |type| will be deprecated in the dump.
+ // See http://crbug.com/245603.
+ type = ABSENT;
+ if (filename[0] == '/') {
+ if (flags[2] == 'x')
+ type = FILE_EXEC;
+ else
+ type = FILE_NONEXEC;
+ } else if (filename[0] == '\0' || filename[0] == '\n') {
+ type = ANONYMOUS;
+ } else if (strcmp(filename, "[stack]") == 0) {
+ type = STACK;
+ } else {
+ type = OTHER;
+ }
+ // TODO(dmikurube): This |all_| count should be removed in future soon.
+ // See http://crbug.com/245603.
+ uint64 vma_total = all_[type].Record(
+ memory_residence_info_getter, vma_start_addr, vma_last_addr, NULL);
+ uint64 vma_subtotal = 0;
+
+ // TODO(dmikurube): Stop double-counting pagemap.
+ // It will be fixed when http://crbug.com/245603 finishes.
+ if (MemoryRegionMap::IsRecordingLocked()) {
+ uint64 cursor = vma_start_addr;
+ bool first = true;
+
+ // Iterates over MemoryRegionMap until the iterator moves out of the VMA.
+ do {
+ if (!first) {
+ cursor = mmap_iter->end_addr;
+ ++mmap_iter;
+ // Don't break here even if mmap_iter == EndRegionLocked().
+
+ if (mmap_iter != MemoryRegionMap::EndRegionLocked()) {
+ deep_bucket = GetInformationOfMemoryRegion(
+ mmap_iter, memory_residence_info_getter, deep_profile);
+ }
+ }
+ first = false;
+
+ uint64 last_address_of_unhooked;
+ // If the next mmap entry is away from the current VMA.
+ if (mmap_iter == MemoryRegionMap::EndRegionLocked() ||
+ mmap_iter->start_addr > vma_last_addr) {
+ last_address_of_unhooked = vma_last_addr;
+ } else {
+ last_address_of_unhooked = mmap_iter->start_addr - 1;
+ }
+
+ if (last_address_of_unhooked + 1 > cursor) {
+ RAW_CHECK(cursor >= vma_start_addr,
+ "Wrong calculation for unhooked");
+ RAW_CHECK(last_address_of_unhooked <= vma_last_addr,
+ "Wrong calculation for unhooked");
+ uint64 committed_size = unhooked_[type].Record(
+ memory_residence_info_getter,
+ cursor,
+ last_address_of_unhooked,
+ mmap_dump_buffer);
+ vma_subtotal += committed_size;
+ if (mmap_dump_buffer) {
+ mmap_dump_buffer->AppendString(" ", 0);
+ mmap_dump_buffer->AppendPtr(cursor, 0);
+ mmap_dump_buffer->AppendString(" - ", 0);
+ mmap_dump_buffer->AppendPtr(last_address_of_unhooked + 1, 0);
+ mmap_dump_buffer->AppendString(" unhooked ", 0);
+ mmap_dump_buffer->AppendInt64(committed_size, 0);
+ mmap_dump_buffer->AppendString(" / ", 0);
+ mmap_dump_buffer->AppendInt64(
+ last_address_of_unhooked - cursor + 1, 0);
+ mmap_dump_buffer->AppendString("\n", 0);
+ }
+ cursor = last_address_of_unhooked + 1;
+ }
+
+ if (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
+ mmap_iter->start_addr <= vma_last_addr &&
+ mmap_dump_buffer) {
+ bool trailing = mmap_iter->start_addr < vma_start_addr;
+ bool continued = mmap_iter->end_addr - 1 > vma_last_addr;
+ uint64 partial_first_address, partial_last_address;
+ if (trailing)
+ partial_first_address = vma_start_addr;
+ else
+ partial_first_address = mmap_iter->start_addr;
+ if (continued)
+ partial_last_address = vma_last_addr;
+ else
+ partial_last_address = mmap_iter->end_addr - 1;
+ uint64 committed_size = memory_residence_info_getter->CommittedSize(
+ partial_first_address, partial_last_address, mmap_dump_buffer);
+ vma_subtotal += committed_size;
+ mmap_dump_buffer->AppendString(trailing ? " (" : " ", 0);
+ mmap_dump_buffer->AppendPtr(mmap_iter->start_addr, 0);
+ mmap_dump_buffer->AppendString(trailing ? ")" : " ", 0);
+ mmap_dump_buffer->AppendString("-", 0);
+ mmap_dump_buffer->AppendString(continued ? "(" : " ", 0);
+ mmap_dump_buffer->AppendPtr(mmap_iter->end_addr, 0);
+ mmap_dump_buffer->AppendString(continued ? ")" : " ", 0);
+ mmap_dump_buffer->AppendString(" hooked ", 0);
+ mmap_dump_buffer->AppendInt64(committed_size, 0);
+ mmap_dump_buffer->AppendString(" / ", 0);
+ mmap_dump_buffer->AppendInt64(
+ partial_last_address - partial_first_address + 1, 0);
+ mmap_dump_buffer->AppendString(" @ ", 0);
+ if (deep_bucket != NULL) {
+ mmap_dump_buffer->AppendInt(deep_bucket->id, 0, false);
+ } else {
+ mmap_dump_buffer->AppendInt(0, 0, false);
+ }
+ mmap_dump_buffer->AppendString("\n", 0);
+ }
+ } while (mmap_iter != MemoryRegionMap::EndRegionLocked() &&
+ mmap_iter->end_addr - 1 <= vma_last_addr);
+ }
+
+ if (vma_total != vma_subtotal) {
+ char buffer[1024];
+ int written = procmaps_iter.FormatLine(buffer, sizeof(buffer),
+ vma_start_addr, vma_last_addr,
+ flags, offset, inode, filename, 0);
+ RAW_LOG(0, "[%d] Mismatched total in VMA %" PRId64 ":"
+ "%" PRId64 " (%" PRId64 ")",
+ getpid(), vma_total, vma_subtotal, vma_total - vma_subtotal);
+ RAW_LOG(0, "[%d] in %s", getpid(), buffer);
+ }
+ }
+
+ // TODO(dmikurube): Investigate and fix http://crbug.com/189114.
+ //
+ // The total committed memory usage in all_ (from /proc/<pid>/maps) is
+ // sometimes smaller than the sum of the committed mmap'ed addresses and
+ // unhooked regions. Within our observation, the difference was only 4KB
+ // in committed usage, zero in reserved virtual addresses
+ //
+ // A guess is that an uncommitted (but reserved) page may become committed
+ // during counting memory usage in the loop above.
+ //
+ // The difference is accounted as "ABSENT" to investigate such cases.
+ //
+ // It will be fixed when http://crbug.com/245603 finishes (no double count).
+
+ RegionStats all_total;
+ RegionStats unhooked_total;
+ for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
+ all_total.AddAnotherRegionStat(all_[i]);
+ unhooked_total.AddAnotherRegionStat(unhooked_[i]);
+ }
+
+ size_t absent_virtual = profiled_mmap_.virtual_bytes() +
+ unhooked_total.virtual_bytes() -
+ all_total.virtual_bytes();
+ if (absent_virtual > 0)
+ all_[ABSENT].AddToVirtualBytes(absent_virtual);
+
+ size_t absent_committed = profiled_mmap_.committed_bytes() +
+ unhooked_total.committed_bytes() -
+ all_total.committed_bytes();
+ if (absent_committed > 0)
+ all_[ABSENT].AddToCommittedBytes(absent_committed);
+}
+
+void DeepHeapProfile::GlobalStats::SnapshotAllocations(
+ DeepHeapProfile* deep_profile) {
+ profiled_malloc_.Initialize();
+
+ deep_profile->heap_profile_->address_map_->Iterate(RecordAlloc, deep_profile);
+}
+
+void DeepHeapProfile::GlobalStats::Unparse(TextBuffer* buffer) {
+ RegionStats all_total;
+ RegionStats unhooked_total;
+ for (int i = 0; i < NUMBER_OF_MAPS_REGION_TYPES; ++i) {
+ all_total.AddAnotherRegionStat(all_[i]);
+ unhooked_total.AddAnotherRegionStat(unhooked_[i]);
+ }
+
+ // "# total (%lu) %c= profiled-mmap (%lu) + nonprofiled-* (%lu)\n"
+ buffer->AppendString("# total (", 0);
+ buffer->AppendUnsignedLong(all_total.committed_bytes(), 0);
+ buffer->AppendString(") ", 0);
+ buffer->AppendChar(all_total.committed_bytes() ==
+ profiled_mmap_.committed_bytes() +
+ unhooked_total.committed_bytes() ? '=' : '!');
+ buffer->AppendString("= profiled-mmap (", 0);
+ buffer->AppendUnsignedLong(profiled_mmap_.committed_bytes(), 0);
+ buffer->AppendString(") + nonprofiled-* (", 0);
+ buffer->AppendUnsignedLong(unhooked_total.committed_bytes(), 0);
+ buffer->AppendString(")\n", 0);
+
+ // " virtual committed"
+ buffer->AppendString("", 26);
+ buffer->AppendString(kVirtualLabel, 12);
+ buffer->AppendChar(' ');
+ buffer->AppendString(kCommittedLabel, 12);
+ buffer->AppendString("\n", 0);
+
+ all_total.Unparse("total", buffer);
+ all_[ABSENT].Unparse("absent", buffer);
+ all_[FILE_EXEC].Unparse("file-exec", buffer);
+ all_[FILE_NONEXEC].Unparse("file-nonexec", buffer);
+ all_[ANONYMOUS].Unparse("anonymous", buffer);
+ all_[STACK].Unparse("stack", buffer);
+ all_[OTHER].Unparse("other", buffer);
+ unhooked_total.Unparse("nonprofiled-total", buffer);
+ unhooked_[ABSENT].Unparse("nonprofiled-absent", buffer);
+ unhooked_[ANONYMOUS].Unparse("nonprofiled-anonymous", buffer);
+ unhooked_[FILE_EXEC].Unparse("nonprofiled-file-exec", buffer);
+ unhooked_[FILE_NONEXEC].Unparse("nonprofiled-file-nonexec", buffer);
+ unhooked_[STACK].Unparse("nonprofiled-stack", buffer);
+ unhooked_[OTHER].Unparse("nonprofiled-other", buffer);
+ profiled_mmap_.Unparse("profiled-mmap", buffer);
+ profiled_malloc_.Unparse("profiled-malloc", buffer);
+}
+
+// static
+void DeepHeapProfile::GlobalStats::RecordAlloc(const void* pointer,
+ AllocValue* alloc_value,
+ DeepHeapProfile* deep_profile) {
+ uint64 address = reinterpret_cast<uintptr_t>(pointer);
+ size_t committed = deep_profile->memory_residence_info_getter_->CommittedSize(
+ address, address + alloc_value->bytes - 1, NULL);
+
+ DeepBucket* deep_bucket = deep_profile->deep_table_.Lookup(
+ alloc_value->bucket(),
+#if defined(TYPE_PROFILING)
+ LookupType(pointer),
+#endif
+ /* is_mmap */ false);
+ deep_bucket->committed_size += committed;
+ deep_profile->stats_.profiled_malloc_.AddToVirtualBytes(alloc_value->bytes);
+ deep_profile->stats_.profiled_malloc_.AddToCommittedBytes(committed);
+}
+
+DeepHeapProfile::DeepBucket*
+ DeepHeapProfile::GlobalStats::GetInformationOfMemoryRegion(
+ const MemoryRegionMap::RegionIterator& mmap_iter,
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ DeepHeapProfile* deep_profile) {
+ size_t committed = deep_profile->memory_residence_info_getter_->
+ CommittedSize(mmap_iter->start_addr, mmap_iter->end_addr - 1, NULL);
+
+ // TODO(dmikurube): Store a reference to the bucket in region.
+ Bucket* bucket = MemoryRegionMap::GetBucket(
+ mmap_iter->call_stack_depth, mmap_iter->call_stack);
+ DeepBucket* deep_bucket = NULL;
+ if (bucket != NULL) {
+ deep_bucket = deep_profile->deep_table_.Lookup(
+ bucket,
+#if defined(TYPE_PROFILING)
+ NULL, // No type information for memory regions by mmap.
+#endif
+ /* is_mmap */ true);
+ if (deep_bucket != NULL)
+ deep_bucket->committed_size += committed;
+ }
+
+ profiled_mmap_.AddToVirtualBytes(
+ mmap_iter->end_addr - mmap_iter->start_addr);
+ profiled_mmap_.AddToCommittedBytes(committed);
+
+ return deep_bucket;
+}
+
+// static
+void DeepHeapProfile::WriteProcMaps(const char* prefix,
+ char raw_buffer[],
+ int buffer_size) {
+ char filename[100];
+ snprintf(filename, sizeof(filename),
+ "%s.%05d.maps", prefix, static_cast<int>(getpid()));
+
+ RawFD fd = RawOpenForWriting(filename);
+ RAW_DCHECK(fd != kIllegalRawFD, "");
+
+ int length;
+ bool wrote_all;
+ length = tcmalloc::FillProcSelfMaps(raw_buffer, buffer_size, &wrote_all);
+ RAW_DCHECK(wrote_all, "");
+ RAW_DCHECK(length <= buffer_size, "");
+ RawWrite(fd, raw_buffer, length);
+ RawClose(fd);
+}
+#else // USE_DEEP_HEAP_PROFILE
+
+DeepHeapProfile::DeepHeapProfile(HeapProfileTable* heap_profile,
+ const char* prefix)
+ : heap_profile_(heap_profile) {
+}
+
+DeepHeapProfile::~DeepHeapProfile() {
+}
+
+int DeepHeapProfile::DumpOrderedProfile(const char* reason,
+ char raw_buffer[],
+ int buffer_size,
+ RawFD fd) {
+}
+
+#endif // USE_DEEP_HEAP_PROFILE
diff --git a/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.h b/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.h
new file mode 100644
index 00000000000..c2ee897eb7e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/deep-heap-profile.h
@@ -0,0 +1,390 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ---
+// Author: Sainbayar Sukhbaatar
+// Dai Mikurube
+//
+// This file contains a class DeepHeapProfile and its public function
+// DeepHeapProfile::DumpOrderedProfile(). The function works like
+// HeapProfileTable::FillOrderedProfile(), but dumps directory to files.
+//
+// DeepHeapProfile::DumpOrderedProfile() dumps more detailed information about
+// heap usage, which includes OS-level information such as memory residency and
+// type information if the type profiler is available.
+//
+// DeepHeapProfile::DumpOrderedProfile() uses data stored in HeapProfileTable.
+// Any code in DeepHeapProfile runs only when DumpOrderedProfile() is called.
+// It has overhead in dumping, but no overhead in logging.
+//
+// It currently works only on Linux including Android. It does nothing in
+// non-Linux environments.
+
+// Note that uint64 is used to represent addresses instead of uintptr_t, and
+// int is used to represent buffer sizes instead of size_t.
+// It's for consistency with other TCMalloc functions. ProcMapsIterator uses
+// uint64 for addresses, and HeapProfileTable::DumpOrderedProfile uses int
+// for buffer sizes.
+
+#ifndef BASE_DEEP_HEAP_PROFILE_H_
+#define BASE_DEEP_HEAP_PROFILE_H_
+
+#include "config.h"
+
+#if defined(TYPE_PROFILING)
+#include <typeinfo>
+#endif
+
+#if defined(__linux__)
+#define USE_DEEP_HEAP_PROFILE 1
+#endif
+
+#include "addressmap-inl.h"
+#include "heap-profile-table.h"
+#include "memory_region_map.h"
+
+class DeepHeapProfile {
+ public:
+ enum PageFrameType {
+ DUMP_NO_PAGEFRAME = 0, // Dumps nothing about pageframes
+ DUMP_PFN = 1, // Dumps only pageframe numbers (PFNs)
+ DUMP_PAGECOUNT = 2, // Dumps PFNs and pagecounts
+ };
+
+ // Constructs a DeepHeapProfile instance. It works as a wrapper of
+ // HeapProfileTable.
+ //
+ // |heap_profile| is a pointer to HeapProfileTable. DeepHeapProfile reads
+ // data in |heap_profile| and forwards operations to |heap_profile| if
+ // DeepHeapProfile is not available (non-Linux).
+ // |prefix| is a prefix of dumped file names.
+ // |pageframe_type| means what information is dumped for pageframes.
+ DeepHeapProfile(HeapProfileTable* heap_profile,
+ const char* prefix,
+ enum PageFrameType pageframe_type);
+ ~DeepHeapProfile();
+
+ // Dumps a deep profile into |fd| with using |raw_buffer| of |buffer_size|.
+ //
+ // In addition, a list of buckets is dumped into a ".buckets" file in
+ // descending order of allocated bytes.
+ void DumpOrderedProfile(const char* reason,
+ char raw_buffer[],
+ int buffer_size,
+ RawFD fd);
+
+ private:
+#ifdef USE_DEEP_HEAP_PROFILE
+ typedef HeapProfileTable::Stats Stats;
+ typedef HeapProfileTable::Bucket Bucket;
+ typedef HeapProfileTable::AllocValue AllocValue;
+ typedef HeapProfileTable::AllocationMap AllocationMap;
+
+ enum MapsRegionType {
+ // Bytes of memory which were not recognized with /proc/<pid>/maps.
+ // This size should be 0.
+ ABSENT,
+
+ // Bytes of memory which is mapped anonymously.
+ // Regions which contain nothing in the last column of /proc/<pid>/maps.
+ ANONYMOUS,
+
+ // Bytes of memory which is mapped to a executable/non-executable file.
+ // Regions which contain file paths in the last column of /proc/<pid>/maps.
+ FILE_EXEC,
+ FILE_NONEXEC,
+
+ // Bytes of memory which is labeled [stack] in /proc/<pid>/maps.
+ STACK,
+
+ // Bytes of memory which is labeled, but not mapped to any file.
+ // Regions which contain non-path strings in the last column of
+ // /proc/<pid>/maps.
+ OTHER,
+
+ NUMBER_OF_MAPS_REGION_TYPES
+ };
+
+ static const char* kMapsRegionTypeDict[NUMBER_OF_MAPS_REGION_TYPES];
+
+ // Manages a buffer to keep a text to be dumped to a file.
+ class TextBuffer {
+ public:
+ TextBuffer(char *raw_buffer, int size, RawFD fd)
+ : buffer_(raw_buffer),
+ size_(size),
+ cursor_(0),
+ fd_(fd) {
+ }
+
+ int Size();
+ int FilledBytes();
+ void Clear();
+ void Flush();
+
+ bool AppendChar(char value);
+ bool AppendString(const char* value, int width);
+ bool AppendInt(int value, int width, bool leading_zero);
+ bool AppendLong(long value, int width);
+ bool AppendUnsignedLong(unsigned long value, int width);
+ bool AppendInt64(int64 value, int width);
+ bool AppendBase64(uint64 value, int width);
+ bool AppendPtr(uint64 value, int width);
+
+ private:
+ bool ForwardCursor(int appended);
+
+ char *buffer_;
+ int size_;
+ int cursor_;
+ RawFD fd_;
+ DISALLOW_COPY_AND_ASSIGN(TextBuffer);
+ };
+
+ // Defines an interface for getting info about memory residence.
+ class MemoryResidenceInfoGetterInterface {
+ public:
+ virtual ~MemoryResidenceInfoGetterInterface();
+
+ // Initializes the instance.
+ virtual void Initialize() = 0;
+
+ // Returns the number of resident (including swapped) bytes of the given
+ // memory region from |first_address| to |last_address| inclusive.
+ virtual size_t CommittedSize(uint64 first_address,
+ uint64 last_address,
+ TextBuffer* buffer) const = 0;
+
+ // Creates a new platform specific MemoryResidenceInfoGetterInterface.
+ static MemoryResidenceInfoGetterInterface* Create(
+ PageFrameType pageframe_type);
+
+ virtual bool IsPageCountAvailable() const = 0;
+
+ protected:
+ MemoryResidenceInfoGetterInterface();
+ };
+
+#if defined(__linux__)
+ // Implements MemoryResidenceInfoGetterInterface for Linux.
+ class MemoryInfoGetterLinux : public MemoryResidenceInfoGetterInterface {
+ public:
+ MemoryInfoGetterLinux(PageFrameType pageframe_type)
+ : pageframe_type_(pageframe_type),
+ pagemap_fd_(kIllegalRawFD),
+ kpagecount_fd_(kIllegalRawFD) {}
+ virtual ~MemoryInfoGetterLinux() {}
+
+ // Opens /proc/<pid>/pagemap and stores its file descriptor.
+ // It keeps open while the process is running.
+ //
+ // Note that file descriptors need to be refreshed after fork.
+ virtual void Initialize();
+
+ // Returns the number of resident (including swapped) bytes of the given
+ // memory region from |first_address| to |last_address| inclusive.
+ virtual size_t CommittedSize(uint64 first_address,
+ uint64 last_address,
+ TextBuffer* buffer) const;
+
+ virtual bool IsPageCountAvailable() const;
+
+ private:
+ struct State {
+ uint64 pfn;
+ bool is_committed; // Currently, we use only this
+ bool is_present;
+ bool is_swapped;
+ bool is_shared;
+ bool is_mmap;
+ };
+
+ uint64 ReadPageCount(uint64 pfn) const;
+
+ // Seeks to the offset of the open pagemap file.
+ // It returns true if succeeded.
+ bool Seek(uint64 address) const;
+
+ // Reads a pagemap state from the current offset.
+ // It returns true if succeeded.
+ bool Read(State* state, bool get_pfn) const;
+
+ PageFrameType pageframe_type_;
+ RawFD pagemap_fd_;
+ RawFD kpagecount_fd_;
+ };
+#endif // defined(__linux__)
+
+ // Contains extended information for HeapProfileTable::Bucket. These objects
+ // are managed in a hash table (DeepBucketTable) whose key is an address of
+ // a Bucket and other additional information.
+ struct DeepBucket {
+ public:
+ void UnparseForStats(TextBuffer* buffer);
+ void UnparseForBucketFile(TextBuffer* buffer);
+
+ Bucket* bucket;
+#if defined(TYPE_PROFILING)
+ const std::type_info* type; // A type of the object
+#endif
+ size_t committed_size; // A resident size of this bucket
+ bool is_mmap; // True if the bucket represents a mmap region
+ int id; // A unique ID of the bucket
+ bool is_logged; // True if the stracktrace is logged to a file
+ DeepBucket* next; // A reference to the next entry in the hash table
+ };
+
+ // Manages a hash table for DeepBucket.
+ class DeepBucketTable {
+ public:
+ DeepBucketTable(int size,
+ HeapProfileTable::Allocator alloc,
+ HeapProfileTable::DeAllocator dealloc);
+ ~DeepBucketTable();
+
+ // Finds a DeepBucket instance corresponding to the given |bucket|, or
+ // creates a new DeepBucket object if it doesn't exist.
+ DeepBucket* Lookup(Bucket* bucket,
+#if defined(TYPE_PROFILING)
+ const std::type_info* type,
+#endif
+ bool is_mmap);
+
+ // Writes stats of the hash table to |buffer| for DumpOrderedProfile.
+ void UnparseForStats(TextBuffer* buffer);
+
+ // Writes all buckets for a bucket file with using |buffer|.
+ void WriteForBucketFile(const char* prefix,
+ int dump_count,
+ char raw_buffer[],
+ int buffer_size);
+
+ // Resets 'committed_size' members in DeepBucket objects.
+ void ResetCommittedSize();
+
+ // Resets all 'is_loggeed' flags in DeepBucket objects.
+ void ResetIsLogged();
+
+ private:
+ // Adds |add| to a |hash_value| for Lookup.
+ inline static void AddToHashValue(uintptr_t add, uintptr_t* hash_value);
+ inline static void FinishHashValue(uintptr_t* hash_value);
+
+ DeepBucket** table_;
+ size_t table_size_;
+ HeapProfileTable::Allocator alloc_;
+ HeapProfileTable::DeAllocator dealloc_;
+ int bucket_id_;
+ };
+
+ class RegionStats {
+ public:
+ RegionStats(): virtual_bytes_(0), committed_bytes_(0) {}
+ ~RegionStats() {}
+
+ // Initializes 'virtual_bytes_' and 'committed_bytes_'.
+ void Initialize();
+
+ // Updates itself to contain the tallies of 'virtual_bytes' and
+ // 'committed_bytes' in the region from |first_adress| to |last_address|
+ // inclusive.
+ uint64 Record(
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ uint64 first_address,
+ uint64 last_address,
+ TextBuffer* buffer);
+
+ // Writes stats of the region into |buffer| with |name|.
+ void Unparse(const char* name, TextBuffer* buffer);
+
+ size_t virtual_bytes() const { return virtual_bytes_; }
+ size_t committed_bytes() const { return committed_bytes_; }
+ void AddToVirtualBytes(size_t additional_virtual_bytes) {
+ virtual_bytes_ += additional_virtual_bytes;
+ }
+ void AddToCommittedBytes(size_t additional_committed_bytes) {
+ committed_bytes_ += additional_committed_bytes;
+ }
+ void AddAnotherRegionStat(const RegionStats& other) {
+ virtual_bytes_ += other.virtual_bytes_;
+ committed_bytes_ += other.committed_bytes_;
+ }
+
+ private:
+ size_t virtual_bytes_;
+ size_t committed_bytes_;
+ DISALLOW_COPY_AND_ASSIGN(RegionStats);
+ };
+
+ class GlobalStats {
+ public:
+ // Snapshots and calculates global stats from /proc/<pid>/maps and pagemap.
+ void SnapshotMaps(
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ DeepHeapProfile* deep_profile,
+ TextBuffer* mmap_dump_buffer);
+
+ // Snapshots allocations by malloc and mmap.
+ void SnapshotAllocations(DeepHeapProfile* deep_profile);
+
+ // Writes global stats into |buffer|.
+ void Unparse(TextBuffer* buffer);
+
+ private:
+ // Records both virtual and committed byte counts of malloc and mmap regions
+ // as callback functions for AllocationMap::Iterate().
+ static void RecordAlloc(const void* pointer,
+ AllocValue* alloc_value,
+ DeepHeapProfile* deep_profile);
+
+ DeepBucket* GetInformationOfMemoryRegion(
+ const MemoryRegionMap::RegionIterator& mmap_iter,
+ const MemoryResidenceInfoGetterInterface* memory_residence_info_getter,
+ DeepHeapProfile* deep_profile);
+
+ // All RegionStats members in this class contain the bytes of virtual
+ // memory and committed memory.
+ // TODO(dmikurube): These regions should be classified more precisely later
+ // for more detailed analysis.
+ RegionStats all_[NUMBER_OF_MAPS_REGION_TYPES];
+
+ RegionStats unhooked_[NUMBER_OF_MAPS_REGION_TYPES];
+
+ // Total bytes of malloc'ed regions.
+ RegionStats profiled_malloc_;
+
+ // Total bytes of mmap'ed regions.
+ RegionStats profiled_mmap_;
+ };
+
+ // Writes reformatted /proc/<pid>/maps into a file "|prefix|.<pid>.maps"
+ // with using |raw_buffer| of |buffer_size|.
+ static void WriteProcMaps(const char* prefix,
+ char raw_buffer[],
+ int buffer_size);
+
+ // Appends the command line (/proc/pid/cmdline on Linux) into |buffer|.
+ bool AppendCommandLine(TextBuffer* buffer);
+
+ MemoryResidenceInfoGetterInterface* memory_residence_info_getter_;
+
+ // Process ID of the last dump. This can change by fork.
+ pid_t most_recent_pid_;
+
+ GlobalStats stats_; // Stats about total memory.
+ int dump_count_; // The number of dumps.
+ char* filename_prefix_; // Output file prefix.
+ char run_id_[128];
+
+ DeepBucketTable deep_table_;
+
+ enum PageFrameType pageframe_type_;
+#endif // USE_DEEP_HEAP_PROFILE
+
+ HeapProfileTable* heap_profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeepHeapProfile);
+};
+
+#endif // BASE_DEEP_HEAP_PROFILE_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/free_list.cc b/chromium/third_party/tcmalloc/chromium/src/free_list.cc
new file mode 100644
index 00000000000..cab54068082
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/free_list.cc
@@ -0,0 +1,145 @@
+// 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: Rebecca Shapiro <bxx@google.com>
+//
+// This file contains functions that implement doubly linked and
+// singly linked lists. The singly linked lists are null terminated,
+// use raw pointers to link neighboring elements, and these pointers
+// are stored at the start of each element, independently of the
+// elements's size. Because pointers are stored within each element,
+// each element must be large enough to store two raw pointers if
+// doubly linked lists are employed, or one raw pointer if singly
+// linked lists are employed. On machines with 64 bit pointers, this
+// means elements must be at least 16 bytes in size for doubly linked
+// list support, and 8 bytes for singly linked list support. No
+// attempts are made to preserve the data in elements stored in the
+// list.
+//
+// Given a machine with pointers of size N (on a 64bit machine N=8, on
+// a 32bit machine, N=4), the list pointers are stored in the
+// following manner:
+// -In doubly linked lists, the |next| pointer is stored in the first N
+// bytes of the node and the |previous| pointer is writtend into the
+// second N bytes.
+// -In singly linked lists, the |next| pointer is stored in the first N
+// bytes of the node.
+//
+// For both types of lists: when a pop operation is performed on a non
+// empty list, the new list head becomes that which is pointed to by
+// the former head's |next| pointer. If the list is doubly linked, the
+// new head |previous| pointer gets changed from pointing to the former
+// head to NULL.
+
+
+#include <limits>
+#include <stddef.h>
+#include "free_list.h"
+
+#if defined(TCMALLOC_USE_DOUBLYLINKED_FREELIST)
+
+namespace tcmalloc {
+
+// Remove |n| elements from linked list at whose first element is at
+// |*head|. |head| will be modified to point to the new head.
+// |start| will point to the first node of the range, |end| will point
+// to the last node in the range. |n| must be <= FL_Size(|*head|)
+// If |n| > 0, |head| must not be NULL.
+void FL_PopRange(void **head, int n, void **start, void **end) {
+ if (n == 0) {
+ *start = NULL;
+ *end = NULL;
+ return;
+ }
+
+ *start = *head; // Remember the first node in the range.
+ void *tmp = *head;
+ for (int i = 1; i < n; ++i) { // Find end of range.
+ tmp = FL_Next(tmp);
+ }
+ *end = tmp; // |end| now set to point to last node in range.
+ *head = FL_Next(*end);
+ FL_SetNext(*end, NULL); // Unlink range from list.
+
+ if (*head ) { // Fixup popped list.
+ FL_SetPrevious(*head, NULL);
+ }
+}
+
+// Pushes the nodes in the list begginning at |start| whose last node
+// is |end| into the linked list at |*head|. |*head| is updated to
+// point be the new head of the list. |head| must not be NULL.
+void FL_PushRange(void **head, void *start, void *end) {
+ if (!start) return;
+
+ // Sanity checking of ends of list to push is done by calling
+ // FL_Next and FL_Previous.
+ FL_Next(start);
+ FL_Previous(end);
+ ASSERT(FL_Previous_No_Check(start) == NULL);
+ ASSERT(FL_Next_No_Check(end) == NULL);
+
+ if (*head) {
+ FL_EqualityCheck(FL_Previous_No_Check(*head), (void*)NULL,
+ __FILE__, __LINE__);
+ FL_SetNext(end, *head);
+ FL_SetPrevious(*head, end);
+ }
+ *head = start;
+}
+
+// Calculates the size of the list that begins at |head|.
+size_t FL_Size(void *head){
+ int count = 0;
+ if (head) {
+ FL_EqualityCheck(FL_Previous_No_Check(head), (void*)NULL,
+ __FILE__, __LINE__);
+ }
+ while (head) {
+ count++;
+ head = FL_Next(head);
+ }
+ return count;
+}
+
+} // namespace tcmalloc
+
+#else
+#include "linked_list.h" // for SLL_SetNext
+
+namespace {
+
+inline void FL_SetNext(void *t, void *n) {
+ tcmalloc::SLL_SetNext(t,n);
+}
+
+}
+
+#endif // TCMALLOC_USE_DOUBLYLINKED_FREELIST
diff --git a/chromium/third_party/tcmalloc/chromium/src/free_list.h b/chromium/third_party/tcmalloc/chromium/src/free_list.h
new file mode 100644
index 00000000000..a5b5a063d83
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/free_list.h
@@ -0,0 +1,202 @@
+// 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: Rebecca Shapiro <bxx@google.com>
+//
+// This file contains declarations of functions that implement doubly
+// linked lists and definitions of functions that implement singly
+// linked lists. It also contains macros to tell the SizeMap class
+// how much space a node in the freelist needs so that SizeMap can
+// create large enough size classes.
+
+#ifndef TCMALLOC_FREE_LIST_H_
+#define TCMALLOC_FREE_LIST_H_
+
+#include <stddef.h>
+#include "internal_logging.h"
+#include "linked_list.h"
+#include "system-alloc.h"
+
+// Remove to enable singly linked lists (the default for open source tcmalloc).
+#define TCMALLOC_USE_DOUBLYLINKED_FREELIST
+
+namespace tcmalloc {
+
+#if defined(TCMALLOC_USE_DOUBLYLINKED_FREELIST)
+
+// size class information for common.h.
+static const bool kSupportsDoublyLinkedList = true;
+
+void FL_PopRange(void **head, int n, void **start, void **end);
+void FL_PushRange(void **head, void *start, void *end);
+size_t FL_Size(void *head);
+
+template <typename T> inline void FL_EqualityCheck(const T& v0,
+ const T& v1,
+ const char* file,
+ int line) {
+ if (v0 != v1) Log(kCrash, file, line, "Memory corruption detected.");
+}
+
+inline void EnsureNonLoop(void* node, void* next) {
+ // We only have time to do minimal checking. We don't traverse the list, but
+ // only look for an immediate loop (cycle back to ourself).
+ if (node != next) return;
+ Log(kCrash, __FILE__, __LINE__, "Circular loop in list detected: ", next);
+}
+
+inline void* MaskPtr(void* p) {
+ // Maximize ASLR entropy and guarantee the result is an invalid address.
+ const uintptr_t mask = ~(reinterpret_cast<uintptr_t>(TCMalloc_SystemAlloc)
+ >> 13);
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) ^ mask);
+}
+
+inline void* UnmaskPtr(void* p) {
+ return MaskPtr(p);
+}
+
+// Returns value of the |previous| pointer w/out running a sanity
+// check.
+inline void *FL_Previous_No_Check(void *t) {
+ return UnmaskPtr(reinterpret_cast<void**>(t)[1]);
+}
+
+// Returns value of the |next| pointer w/out running a sanity check.
+inline void *FL_Next_No_Check(void *t) {
+ return UnmaskPtr(reinterpret_cast<void**>(t)[0]);
+}
+
+inline void *FL_Previous(void *t) {
+ void *previous = FL_Previous_No_Check(t);
+ if (previous) {
+ FL_EqualityCheck(FL_Next_No_Check(previous), t, __FILE__, __LINE__);
+ }
+ return previous;
+}
+
+inline void FL_SetPrevious(void *t, void *n) {
+ EnsureNonLoop(t, n);
+ reinterpret_cast<void**>(t)[1] = MaskPtr(n);
+}
+
+inline void FL_SetNext(void *t, void *n) {
+ EnsureNonLoop(t, n);
+ reinterpret_cast<void**>(t)[0] = MaskPtr(n);
+}
+
+inline void *FL_Next(void *t) {
+ void *next = FL_Next_No_Check(t);
+ if (next) {
+ FL_EqualityCheck(FL_Previous_No_Check(next), t, __FILE__, __LINE__);
+ }
+ return next;
+}
+
+// Pops the top element off the linked list whose first element is at
+// |*list|, and updates |*list| to point to the next element in the
+// list. Returns the address of the element that was removed from the
+// linked list. |list| must not be NULL.
+inline void *FL_Pop(void **list) {
+ void *result = *list;
+ ASSERT(FL_Previous_No_Check(result) == NULL);
+ *list = FL_Next(result);
+ if (*list != NULL) {
+ FL_SetPrevious(*list, NULL);
+ }
+ return result;
+}
+
+// Makes the element at |t| a singleton doubly linked list.
+inline void FL_Init(void *t) {
+ FL_SetPrevious(t, NULL);
+ FL_SetNext(t, NULL);
+}
+
+// Pushes element to a linked list whose first element is at
+// |*list|. When this call returns, |list| will point to the new head
+// of the linked list.
+inline void FL_Push(void **list, void *element) {
+ void *old = *list;
+ if (old == NULL) { // Builds singleton list.
+ FL_Init(element);
+ } else {
+ ASSERT(FL_Previous_No_Check(old) == NULL);
+ FL_SetNext(element, old);
+ FL_SetPrevious(old, element);
+ FL_SetPrevious(element, NULL);
+ }
+ *list = element;
+}
+
+#else // TCMALLOC_USE_DOUBLYLINKED_FREELIST not defined
+static const bool kSupportsDoublyLinkedList = false;
+
+inline void *FL_Next(void *t) {
+ return SLL_Next(t);
+}
+
+inline void FL_Init(void *t) {
+ SLL_SetNext(t, NULL);
+}
+
+inline void FL_Push(void **list, void *element) {
+ if(*list != element) {
+ SLL_Push(list,element);
+ return;
+ }
+ Log(kCrash, __FILE__, __LINE__, "Double Free of %p detected", element);
+}
+
+inline void *FL_Pop(void **list) {
+ return SLL_Pop(list);
+}
+
+// Removes |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 FL_PopRange(void **head, int n, void **start, void **end) {
+ SLL_PopRange(head, n, start, end);
+}
+
+inline void FL_PushRange(void **head, void *start, void *end) {
+ SLL_PushRange(head,start,end);
+}
+
+inline size_t FL_Size(void *head) {
+ return SLL_Size(head);
+}
+
+#endif // TCMALLOC_USE_DOUBLYLINKED_FREELIST
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_FREE_LIST_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/getpc.h b/chromium/third_party/tcmalloc/chromium/src/getpc.h
new file mode 100644
index 00000000000..c5183bf0adb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/getpc.h
@@ -0,0 +1,198 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This is an internal header file used by profiler.cc. It defines
+// the single (inline) function GetPC. GetPC is used in a signal
+// handler to figure out the instruction that was being executed when
+// the signal-handler was triggered.
+//
+// To get this, we use the ucontext_t argument to the signal-handler
+// callback, which holds the full context of what was going on when
+// the signal triggered. How to get from a ucontext_t to a Program
+// Counter is OS-dependent.
+
+#ifndef BASE_GETPC_H_
+#define BASE_GETPC_H_
+
+#include "config.h"
+
+// On many linux systems, we may need _GNU_SOURCE to get access to
+// the defined constants that define the register we want to see (eg
+// REG_EIP). Note this #define must come first!
+#define _GNU_SOURCE 1
+// If #define _GNU_SOURCE causes problems, this might work instead.
+// It will cause problems for FreeBSD though!, because it turns off
+// the needed __BSD_VISIBLE.
+//#define _XOPEN_SOURCE 500
+
+#include <string.h> // for memcmp
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h> // for ucontext_t (and also mcontext_t)
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
+#elif defined(__ANDROID__)
+#include <unwind.h>
+#endif
+
+
+// Take the example where function Foo() calls function Bar(). For
+// many architectures, Bar() is responsible for setting up and tearing
+// down its own stack frame. In that case, it's possible for the
+// interrupt to happen when execution is in Bar(), but the stack frame
+// is not properly set up (either before it's done being set up, or
+// after it's been torn down but before Bar() returns). In those
+// cases, the stack trace cannot see the caller function anymore.
+//
+// GetPC can try to identify this situation, on architectures where it
+// might occur, and unwind the current function call in that case to
+// avoid false edges in the profile graph (that is, edges that appear
+// to show a call skipping over a function). To do this, we hard-code
+// in the asm instructions we might see when setting up or tearing
+// down a stack frame.
+//
+// This is difficult to get right: the instructions depend on the
+// processor, the compiler ABI, and even the optimization level. This
+// is a best effort patch -- if we fail to detect such a situation, or
+// mess up the PC, nothing happens; the returned PC is not used for
+// any further processing.
+struct CallUnrollInfo {
+ // Offset from (e)ip register where this instruction sequence
+ // should be matched. Interpreted as bytes. Offset 0 is the next
+ // instruction to execute. Be extra careful with negative offsets in
+ // architectures of variable instruction length (like x86) - it is
+ // not that easy as taking an offset to step one instruction back!
+ int pc_offset;
+ // The actual instruction bytes. Feel free to make it larger if you
+ // need a longer sequence.
+ char ins[16];
+ // How many bytes to match from ins array?
+ int ins_size;
+ // The offset from the stack pointer (e)sp where to look for the
+ // call return address. Interpreted as bytes.
+ int return_sp_offset;
+};
+
+
+// The dereferences needed to get the PC from a struct ucontext were
+// determined at configure time, and stored in the macro
+// PC_FROM_UCONTEXT in config.h. The only thing we need to do here,
+// then, is to do the magic call-unrolling for systems that support it.
+
+// -- Special case 1: linux x86, for which we have CallUnrollInfo
+#if defined(__linux) && defined(__i386) && defined(__GNUC__) && \
+ !defined(__ANDROID__)
+static const CallUnrollInfo callunrollinfo[] = {
+ // Entry to a function: push %ebp; mov %esp,%ebp
+ // Top-of-stack contains the caller IP.
+ { 0,
+ {0x55, 0x89, 0xe5}, 3,
+ 0
+ },
+ // Entry to a function, second instruction: push %ebp; mov %esp,%ebp
+ // Top-of-stack contains the old frame, caller IP is +4.
+ { -1,
+ {0x55, 0x89, 0xe5}, 3,
+ 4
+ },
+ // Return from a function: RET.
+ // Top-of-stack contains the caller IP.
+ { 0,
+ {0xc3}, 1,
+ 0
+ }
+};
+
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+ // See comment above struct CallUnrollInfo. Only try instruction
+ // flow matching if both eip and esp looks reasonable.
+ const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP];
+ const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP];
+ if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 &&
+ (esp & 0xffff0000) != 0) {
+ char* eip_char = reinterpret_cast<char*>(eip);
+ for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) {
+ if (!memcmp(eip_char + callunrollinfo[i].pc_offset,
+ callunrollinfo[i].ins, callunrollinfo[i].ins_size)) {
+ // We have a match.
+ void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset);
+ return *retaddr;
+ }
+ }
+ }
+ return (void*)eip;
+}
+
+// Special case #2: Windows, which has to do something totally different.
+#elif defined(_WIN32) || 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;
+}
+#elif defined(__ANDROID__)
+typedef struct _Unwind_Context ucontext_t;
+
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+ // Bionic doesn't export ucontext, see
+ // https://code.google.com/p/android/issues/detail?id=34784.
+ return reinterpret_cast<void*>(_Unwind_GetIP(
+ const_cast<ucontext_t*>(&signal_ucontext)));
+}
+//
+// Normal cases. If this doesn't compile, it's probably because
+// PC_FROM_UCONTEXT is the empty string. You need to figure out
+// the right value for your system, and add it to the list in
+// configure.ac (or set it manually in your config.h).
+#else
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+ return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h
+}
+
+#endif
+
+#endif // BASE_GETPC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/heap-checker.h b/chromium/third_party/tcmalloc/chromium/src/google/heap-checker.h
new file mode 100644
index 00000000000..8aa5ea49ca9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/heap-checker.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/heap-checker.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/heap-profiler.h b/chromium/third_party/tcmalloc/chromium/src/google/heap-profiler.h
new file mode 100644
index 00000000000..be4395964f4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/heap-profiler.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/heap-profiler.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension.h b/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension.h
new file mode 100644
index 00000000000..55150e5a49a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/malloc_extension.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension_c.h b/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension_c.h
new file mode 100644
index 00000000000..87d727b3943
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/malloc_extension_c.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/malloc_extension_c.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook.h b/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook.h
new file mode 100644
index 00000000000..e5b8e7cb001
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/malloc_hook.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook_c.h b/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook_c.h
new file mode 100644
index 00000000000..e3ac0a49997
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/malloc_hook_c.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/malloc_hook_c.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/profiler.h b/chromium/third_party/tcmalloc/chromium/src/google/profiler.h
new file mode 100644
index 00000000000..67a89c198b1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/profiler.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/profiler.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/stacktrace.h b/chromium/third_party/tcmalloc/chromium/src/google/stacktrace.h
new file mode 100644
index 00000000000..eb761cab4e0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/stacktrace.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/stacktrace.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/google/tcmalloc.h b/chromium/third_party/tcmalloc/chromium/src/google/tcmalloc.h
new file mode 100644
index 00000000000..c7db6319426
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/google/tcmalloc.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/tcmalloc.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-checker.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-checker.h
new file mode 100644
index 00000000000..32ed10a8232
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-checker.h
@@ -0,0 +1,424 @@
+// 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 doc/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 <sys/types.h> // 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 <stdint.h> // for uintptr_t
+#endif
+#include <stdarg.h> // for va_list
+#include <vector>
+
+// 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 <typename T>
+ static T* IgnoreObject(T* ptr) {
+ DoIgnoreObject(static_cast<const void*>(const_cast<const T*>(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();
+ // TODO(csilvers): remove this one, at least
+ friend int main(int, char**);
+
+
+ // 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 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 ListAllProcessThreads.
+ // Here we only use num_threads and thread_pids, that 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 T>
+class HiddenPointer {
+ public:
+ explicit HiddenPointer(T* t)
+ : masked_t_(reinterpret_cast<uintptr_t>(t) ^ kHideMask) {
+ }
+ // Returns unhidden pointer. Be careful where you save the result.
+ T* get() const { return reinterpret_cast<T*>(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<uintptr_t>(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<void_function>* 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/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h
new file mode 100644
index 00000000000..c2f16997aa5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h
@@ -0,0 +1,131 @@
+/* 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 doc/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 <stddef.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
+
+/* 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", ...
+ *
+ * If |prefix| is NULL then dumps will not be written to disk. Applications
+ * can use GetHeapProfile() to get profile data, but HeapProfilerDump() will do
+ * nothing.
+ */
+PERFTOOLS_DLL_DECL void HeapProfilerStart(const char* prefix);
+
+/* Start profiling with a callback function that returns application-generated
+ * stacks. Profiles are not written to disk, but may be obtained via
+ * GetHeapProfile(). The callback:
+ * 1. May optionally skip the first |skip_count| items on the stack.
+ * 2. Must provide a |stack| buffer of at least size 32 * sizeof(void*).
+ * 3. Must return the number of items copied or zero.
+ */
+typedef int (*StackGeneratorFunction)(int skip_count, void** stack);
+PERFTOOLS_DLL_DECL void HeapProfilerWithPseudoStackStart(
+ StackGeneratorFunction callback);
+
+/* 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();
+
+/* Callback function for iterating through all allocated objects. Accepts
+ * pointer to user data passed into IterateAllocatedObjects and pointer
+ * to the object being visited.
+ */
+typedef void (*AddressVisitor)(void* data, const void* ptr);
+
+/* Iterate over all live allocated objects. For each allocation the
+ * callback will be invoked with the data argument and allocation pointer.
+ */
+PERFTOOLS_DLL_DECL void IterateAllocatedObjects(AddressVisitor callback,
+ void* data);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* BASE_HEAP_PROFILER_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h
new file mode 100644
index 00000000000..950b60335b0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h
@@ -0,0 +1,404 @@
+// 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: Sanjay Ghemawat <opensource@google.com>
+//
+// 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 <stddef.h>
+// 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 <stdint.h>
+#endif
+#include <string>
+#include <vector>
+
+// 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 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 current state of the malloc
+ // data structures. 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.
+ // 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.
+ //
+ // 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.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);
+
+ // On the current thread, return the total number of bytes allocated.
+ // (Currently only implemented in tcmalloc.)
+ static unsigned int GetBytesAllocatedOnCurrentThread();
+
+ // 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<FreeListInfo>* 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();
+};
+
+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/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h
new file mode 100644
index 00000000000..72a0a7c1733
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h
@@ -0,0 +1,99 @@
+/* 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 <stddef.h>
+#include <sys/types.h>
+
+/* 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);
+
+/*
+ * 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/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h
new file mode 100644
index 00000000000..b99c047cd5d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h
@@ -0,0 +1,358 @@
+// 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 <stddef.h>
+#include <sys/types.h>
+extern "C" {
+#include <gperftools/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/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook_c.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/malloc_hook_c.h
new file mode 100644
index 00000000000..56337e15e83
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/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 <stddef.h>
+#include <sys/types.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
+
+#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/chromium/third_party/tcmalloc/chromium/src/gperftools/profiler.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/profiler.h
new file mode 100644
index 00000000000..07323e450bf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/profiler.h
@@ -0,0 +1,166 @@
+/* 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 doc/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
+ * "PROFILE" 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 <path_to_executable> <profile_file_name>
+ * % pprof --gv <path_to_executable> <profile_file_name>
+ *
+ * These functions are thread-safe.
+ */
+
+#ifndef BASE_PROFILER_H_
+#define BASE_PROFILER_H_
+
+#include <time.h> /* 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.
+ *
+ * This is equivalent to calling ProfilerStartWithOptions(fname, NULL).
+ */
+PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname);
+
+/* Start profiling and write profile into fname.
+ *
+ * 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 sucessfully, 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();
+
+/* 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();
+
+
+/* DEPRECATED: these functions were used to enable/disable profiling
+ * in the current thread, but no longer do anything.
+ */
+PERFTOOLS_DLL_DECL void ProfilerEnable();
+PERFTOOLS_DLL_DECL void ProfilerDisable();
+
+/* Returns nonzero if profile is currently enabled, zero if it's not. */
+PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads();
+
+/* Routine for registering new threads with the profiler.
+ */
+PERFTOOLS_DLL_DECL void ProfilerRegisterThread();
+
+/* 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);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* BASE_PROFILER_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/gperftools/stacktrace.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/stacktrace.h
new file mode 100644
index 00000000000..fd186d63a1b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/stacktrace.h
@@ -0,0 +1,116 @@
+// 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/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h
new file mode 100644
index 00000000000..a3f036fec52
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h
@@ -0,0 +1,133 @@
+/* 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 <opensource@google.com>
+ * .h file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR 2
+#define TC_VERSION_MINOR 0
+#define TC_VERSION_PATCH ""
+#define TC_VERSION_STRING "gperftools 2.0"
+
+// For struct mallinfo, it it's defined.
+#ifdef HAVE_STRUCT_MALLINFO
+// Malloc can be in several places on older versions of OS X.
+# if defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# endif
+#endif
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#ifdef HAVE_STRUCT_MALLINFO
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in b/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in
new file mode 100644
index 00000000000..dbca6ec07fe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// 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@"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if @ac_cv_have_struct_mallinfo@
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h b/chromium/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h
new file mode 100644
index 00000000000..1236258f6b5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/gperftools/type_profiler_map.h
@@ -0,0 +1,20 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TYPE_PROFILER_MAP_H_
+#define TYPE_PROFILER_MAP_H_
+
+#if defined(TYPE_PROFILING)
+
+#include <typeinfo>
+
+// PERFTOOLS_DLL_DECL is unnecessary, as it is Windows specific.
+
+void InsertType(void* address, size_t size, const std::type_info& type);
+void EraseType(void* address);
+const std::type_info* LookupType(const void* address);
+
+#endif // defined(TYPE_PROFILING)
+
+#endif // TYPE_PROFILER_MAP_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/heap-checker-bcad.cc b/chromium/third_party/tcmalloc/chromium/src/heap-checker-bcad.cc
new file mode 100644
index 00000000000..c736245559f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-checker-bcad.cc
@@ -0,0 +1,92 @@
+// 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 <gperftools/malloc_extension.h>
+#include "base/abort.h"
+
+// 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) tcmalloc::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/chromium/third_party/tcmalloc/chromium/src/heap-checker.cc b/chromium/third_party/tcmalloc/chromium/src/heap-checker.cc
new file mode 100644
index 00000000000..1400c8e32dc
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-checker.cc
@@ -0,0 +1,2378 @@
+// 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 <fcntl.h> // for O_RDONLY (we use syscall to do actual reads)
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <assert.h>
+
+#if defined(HAVE_LINUX_PTRACE_H)
+#include <linux/ptrace.h>
+#endif
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
+#include <wtypes.h>
+#include <winbase.h>
+#undef ERROR // windows defines these as macros, which can cause trouble
+#undef max
+#undef min
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <algorithm>
+#include <functional>
+
+#include <gperftools/heap-checker.h>
+
+#include "base/basictypes.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include <gperftools/stacktrace.h>
+#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 <gperftools/malloc_hook.h>
+#include <gperftools/malloc_extension.h>
+#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 bool ProfilingIsEnabledForAllThreads();
+bool 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_int32(heap_check_error_exit_code,
+ EnvToInt("HEAP_CHECK_ERROR_EXIT_CODE", 1),
+ "Exit code to return if any leaks were detected.");
+
+//----------------------------------------------------------------------
+
+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 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<typename T> static void DeleteAndNull(T** p) {
+ (*p)->~T();
+ Free(*p);
+ *p = NULL;
+ }
+ template<typename T> 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<uintptr_t, size_t, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, size_t>,
+ 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<AllocObject,
+ STL_Allocator<AllocObject, HeapLeakChecker::Allocator>
+ > LiveObjectsStack;
+static LiveObjectsStack* live_objects = NULL;
+
+// A special string type that uses my allocator
+typedef basic_string<char, char_traits<char>,
+ STL_Allocator<char, HeapLeakChecker::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<HCL_string, LiveObjectsStack, less<HCL_string>,
+ STL_Allocator<pair<const HCL_string, LiveObjectsStack>,
+ 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<uintptr_t, HeapLeakChecker::RangeValue, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, HeapLeakChecker::RangeValue>,
+ 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<uintptr_t, less<uintptr_t>,
+ STL_Allocator<uintptr_t, HeapLeakChecker::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<uintptr_t, uintptr_t, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, uintptr_t>,
+ 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*)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<typename T>
+inline static const void* AsPtr(T addr) {
+ return reinterpret_cast<void*>(addr);
+}
+inline static uintptr_t AsInt(const void* ptr) {
+ return reinterpret_cast<uintptr_t>(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 %"PRIuS "; %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 %"PRIuS"", 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, &region)) {
+ // 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 %"PRIuS" bytes at %p"
+ ": have stack inside: %p",
+ (stack_disable ? "stack" : "range"),
+ info.object_size, ptr, AsPtr(*iter));
+ return;
+ }
+ }
+ RAW_VLOG(11, "%s-disabling %"PRIuS" 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).
+//
+/*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<void*, STL_Allocator<void*, Allocator> > 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]);
+#if (defined(__i386__) || defined(__x86_64)) && \
+ defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER)
+ i386_regs thread_regs;
+#define sys_ptrace(r, p, a, d) syscall(SYS_ptrace, (r), (p), (a), (d))
+ // We use sys_ptrace to avoid thread locking
+ // because this is called from 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<void*>(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<void**>(&thread_regs);
+ p < reinterpret_cast<void**>(&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 %"PRIuS" 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:
+ 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 %"PRIuS" 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 %"PRIuS" 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<uintptr_t>(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 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!");
+ }
+ 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
+ // ListAllProcessThreads, so that CPU profiler can collect all its samples.
+ // The machinery of 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() &&
+ ListAllProcessThreads(NULL, IsOneThread) == 1;
+ // When the normal path of 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)
+ : 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<const char*>(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 %"PRIuS" 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<uintptr_t>(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<char*>(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<const uintptr_t*>(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<const void*>(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 %"PRIuS" bytes at %p "
+ "inside %p of size %"PRIuS"",
+ 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;
+ bool r = heap_profile->FindAllocDetails(ptr, &alloc);
+ r = r; // suppress compiler warning in non-debug mode
+ RAW_DCHECK(r, ""); // sanity
+ 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 %"PRIuS" 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 %"PRIuS" 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<char*>(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: %"PRIuS" bytes "
+ "in %"PRIuS" 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
+extern char* program_invocation_name;
+extern char* program_invocation_short_name;
+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 "<your binary>"; }
+static string invocation_path() { return "<your binary>"; }
+#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<HeapProfileTable::Snapshot*>(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<ssize_t>(leaks->total().alloc_size);
+ inuse_allocs_increase_ = static_cast<ssize_t>(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<HeapProfileTable::Snapshot*>(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::void_function>* 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<HeapCleaner::void_function>;
+ 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=<mode>.");
+ }
+ }
+
+ // 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.
+#ifdef __FreeBSD__
+ FLAGS_heap_check_after_destructors = true;
+#endif
+
+ { 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 <this_binary> | 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");
+ // We don't want to call atexit() routines!
+ _exit(FLAGS_heap_check_error_exit_code);
+ }
+ 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/chromium/third_party/tcmalloc/chromium/src/heap-profile-stats.h b/chromium/third_party/tcmalloc/chromium/src/heap-profile-stats.h
new file mode 100644
index 00000000000..e65cce20f06
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-profile-stats.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// 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/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.cc b/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.cc
new file mode 100644
index 00000000000..bcf8edd81b2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.cc
@@ -0,0 +1,751 @@
+// 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 <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#include <fcntl.h> // for open()
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#ifndef GLOB_NOMATCH // true on some old cygwins
+# define GLOB_NOMATCH 0
+#endif
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // for PRIxPTR
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#include <errno.h>
+#include <stdarg.h>
+#include <string>
+#include <map>
+#include <algorithm> // for sort(), equal(), and copy()
+
+#include "heap-profile-table.h"
+
+#include "base/logging.h"
+#include "raw_printer.h"
+#include "symbolize.h"
+#include <gperftools/stacktrace.h>
+#include <gperftools/malloc_hook.h>
+#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";
+#if defined(TYPE_PROFILING)
+static const char kTypeProfileStatsHeader[] = "type statistics:\n";
+#endif // defined(TYPE_PROFILING)
+
+//----------------------------------------------------------------------
+
+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),
+ bucket_table_(NULL),
+ profile_mmap_(profile_mmap),
+ num_buckets_(0),
+ address_map_(NULL) {
+ // Make a hash table for buckets.
+ const int table_bytes = kHashTableSize * sizeof(*bucket_table_);
+ bucket_table_ = static_cast<Bucket**>(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<uintptr_t>(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<const void**>(alloc_(key_size));
+ copy(key, key + depth, kcopy);
+ Bucket* b = reinterpret_cast<Bucket*>(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);
+ }
+}
+
+void HeapProfileTable::IterateAllocationAddresses(AddressIterator f,
+ void* data) {
+ const AllocationAddressIteratorArgs args(f, data);
+ address_map_->Iterate<const AllocationAddressIteratorArgs&>(
+ AllocationAddressesIterator, args);
+}
+
+void HeapProfileTable::MarkCurrentAllocations(AllocationMark mark) {
+ const MarkArgs args(mark, true);
+ address_map_->Iterate<const MarkArgs&>(MarkIterator, args);
+}
+
+void HeapProfileTable::MarkUnmarkedAllocations(AllocationMark mark) {
+ const MarkArgs args(mark, true);
+ address_map_->Iterate<const MarkArgs&>(MarkIterator, args);
+}
+
+// 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<uintptr_t>(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<Bucket**>(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::DumpMarkedObjects(AllocationMark mark,
+ const char* file_name) {
+ RawFD fd = RawOpenForWriting(file_name);
+ if (fd == kIllegalRawFD) {
+ RAW_LOG(ERROR, "Failed dumping live objects to %s", file_name);
+ return;
+ }
+ const DumpMarkedArgs args(fd, mark);
+ address_map_->Iterate<const DumpMarkedArgs&>(DumpMarkedIterator, args);
+ RawClose(fd);
+}
+
+#if defined(TYPE_PROFILING)
+void HeapProfileTable::DumpTypeStatistics(const char* file_name) const {
+ RawFD fd = RawOpenForWriting(file_name);
+ if (fd == kIllegalRawFD) {
+ RAW_LOG(ERROR, "Failed dumping type statistics to %s", file_name);
+ return;
+ }
+
+ AddressMap<TypeCount>* type_size_map;
+ type_size_map = new(alloc_(sizeof(AddressMap<TypeCount>)))
+ AddressMap<TypeCount>(alloc_, dealloc_);
+ address_map_->Iterate(TallyTypesItererator, type_size_map);
+
+ RawWrite(fd, kTypeProfileStatsHeader, strlen(kTypeProfileStatsHeader));
+ const DumpArgs args(fd, NULL);
+ type_size_map->Iterate<const DumpArgs&>(DumpTypesIterator, args);
+ RawClose(fd);
+
+ type_size_map->~AddressMap<TypeCount>();
+ dealloc_(type_size_map);
+}
+#endif // defined(TYPE_PROFILING)
+
+void HeapProfileTable::IterateOrderedAllocContexts(
+ AllocContextIterator callback) const {
+ Bucket** list = MakeSortedBucketList();
+ AllocContextInfo info;
+ for (int i = 0; i < num_buckets_; ++i) {
+ *static_cast<Stats*>(&info) = *static_cast<Stats*>(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) 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) 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<BufferArgs*>(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);
+}
+
+#if defined(TYPE_PROFILING)
+// static
+void HeapProfileTable::TallyTypesItererator(
+ const void* ptr,
+ AllocValue* value,
+ AddressMap<TypeCount>* type_size_map) {
+ const std::type_info* type = LookupType(ptr);
+
+ const void* key = NULL;
+ if (type)
+ key = type->name();
+
+ TypeCount* count = type_size_map->FindMutable(key);
+ if (count) {
+ count->bytes += value->bytes;
+ ++count->objects;
+ } else {
+ type_size_map->Insert(key, TypeCount(value->bytes, 1));
+ }
+}
+
+// static
+void HeapProfileTable::DumpTypesIterator(const void* ptr,
+ TypeCount* count,
+ const DumpArgs& args) {
+ char buf[1024];
+ int len;
+ const char* mangled_type_name = static_cast<const char*>(ptr);
+ len = snprintf(buf, sizeof(buf), "%6d: %8" PRId64 " @ %s\n",
+ count->objects, count->bytes,
+ mangled_type_name ? mangled_type_name : "(no_typeinfo)");
+ RawWrite(args.fd, buf, len);
+}
+#endif // defined(TYPE_PROFILING)
+
+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);
+}
+
+inline
+void HeapProfileTable::DumpMarkedIterator(const void* ptr, AllocValue* v,
+ const DumpMarkedArgs& args) {
+ if (v->mark() != args.mark)
+ 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 addr[16];
+ snprintf(addr, 16, "0x%08" PRIxPTR, ptr);
+ char buf[1024];
+ int len = UnparseBucket(b, buf, 0, sizeof(buf), addr, NULL);
+ RawWrite(args.fd, buf, len);
+}
+
+inline
+void HeapProfileTable::AllocationAddressesIterator(
+ const void* ptr,
+ AllocValue* v,
+ const AllocationAddressIteratorArgs& args) {
+ args.callback(args.data, ptr);
+}
+
+inline
+void HeapProfileTable::MarkIterator(const void* ptr, AllocValue* v,
+ const MarkArgs& args) {
+ if (!args.mark_all && v->mark() != UNMARKED)
+ return;
+ v->set_mark(args.mark);
+}
+
+// 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<const DumpArgs&>(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;
+ char buf[1000];
+ snprintf(buf, 1000,"%s.%05d.", prefix, getpid());
+ string pattern = string(buf) + ".*" + 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<AddNonLiveArgs*>(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<Bucket*, Entry> 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 %" PRIuS " bytes "
+ "in %" PRIuS " 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<Bucket*,Entry>::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<uintptr_t>(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 %" PRIuS " byte object %p", v->bytes, ptr);
+}
+
+void HeapProfileTable::Snapshot::ReportIndividualObjects() {
+ char unused;
+ map_.Iterate(ReportObject, &unused);
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.h b/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.h
new file mode 100644
index 00000000000..c2ad39f9138
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-profile-table.h
@@ -0,0 +1,525 @@
+// 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"
+
+#if defined(TYPE_PROFILING)
+#include <gperftools/type_profiler_map.h>
+#endif // defined(TYPE_PROFILING)
+
+// 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;
+
+ // Possible marks for MarkCurrentAllocations and MarkUnmarkedAllocations. New
+ // allocations are marked with UNMARKED by default.
+ enum AllocationMark {
+ UNMARKED = 0,
+ MARK_ONE,
+ MARK_TWO,
+ MARK_THREE
+ };
+
+ // 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);
+
+ // Mark all currently known allocations with the given AllocationMark.
+ void MarkCurrentAllocations(AllocationMark mark);
+
+ // Mark all unmarked (i.e. marked with AllocationMark::UNMARKED) with the
+ // given mark.
+ void MarkUnmarkedAllocations(AllocationMark mark);
+
+ // 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);
+ }
+
+ // Callback for iterating through addresses of all allocated objects. Accepts
+ // pointer to user data and object pointer.
+ typedef void (*AddressIterator)(void* data, const void* ptr);
+
+ // Iterate over the addresses of all allocated objects.
+ void IterateAllocationAddresses(AddressIterator, void* data);
+
+ // 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);
+
+ // Dump a list of allocations marked as "live" along with their creation
+ // stack traces and sizes to a file named |file_name|. Together with
+ // MarkCurrentAllocatiosn and MarkUnmarkedAllocations this can be used
+ // to find objects that are created in a certain time span:
+ // 1. Invoke MarkCurrentAllocations(MARK_ONE) to mark the start of the
+ // timespan.
+ // 2. Perform whatever action you suspect allocates memory that is not
+ // correctly freed.
+ // 3. Invoke MarkUnmarkedAllocations(MARK_TWO).
+ // 4. Perform whatever action is supposed to free the memory again. New
+ // allocations are not marked. So all allocations that are marked as
+ // "live" where created during step 2.
+ // 5. Invoke DumpMarkedObjects(MARK_TWO) to get the list of allocations that
+ // were created during step 2, but survived step 4.
+ //
+ // Note that this functionality cannot be used if the HeapProfileTable is
+ // used for leak checking (using HeapLeakChecker).
+ void DumpMarkedObjects(AllocationMark mark, const char* file_name);
+
+#if defined(TYPE_PROFILING)
+ void DumpTypeStatistics(const char* file_name) const;
+#endif // defined(TYPE_PROFILING)
+
+ private:
+ friend class DeepHeapProfile;
+
+ // 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*>(bucket_rep & ~uintptr_t(kMask));
+ }
+ // This also does set_live(false).
+ void set_bucket(Bucket* b) { bucket_rep = reinterpret_cast<uintptr_t>(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);
+ }
+ AllocationMark mark() const {
+ return static_cast<AllocationMark>(bucket_rep & uintptr_t(kMask));
+ }
+ void set_mark(AllocationMark mark) {
+ bucket_rep = (bucket_rep & ~uintptr_t(kMask)) | uintptr_t(mark);
+ }
+
+ 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<AllocValue> 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)
+ };
+
+ // Arguments that need to be passed DumpMarkedIterator callback below.
+ struct DumpMarkedArgs {
+ DumpMarkedArgs(RawFD fd_arg, AllocationMark mark_arg)
+ : fd(fd_arg),
+ mark(mark_arg) {
+ }
+
+ RawFD fd; // file to write to.
+ AllocationMark mark; // The mark of the allocations to process.
+ };
+
+ // Arguments that need to be passed MarkIterator callback below.
+ struct MarkArgs {
+ MarkArgs(AllocationMark mark_arg, bool mark_all_arg)
+ : mark(mark_arg),
+ mark_all(mark_all_arg) {
+ }
+
+ AllocationMark mark; // The mark to put on allocations.
+ bool mark_all; // True if all allocations should be marked. Otherwise just
+ // mark unmarked allocations.
+ };
+
+#if defined(TYPE_PROFILING)
+ struct TypeCount {
+ TypeCount(size_t bytes_arg, unsigned int objects_arg)
+ : bytes(bytes_arg),
+ objects(objects_arg) {
+ }
+
+ size_t bytes;
+ unsigned int objects;
+ };
+#endif // defined(TYPE_PROFILING)
+
+ struct AllocationAddressIteratorArgs {
+ AllocationAddressIteratorArgs(AddressIterator callback_arg, void* data_arg)
+ : callback(callback_arg),
+ data(data_arg) {
+ }
+
+ AddressIterator callback;
+ void* data;
+ };
+
+ // 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 IterateAllocationAddresses.
+ inline static void AllocationAddressesIterator(
+ const void* ptr,
+ AllocValue* v,
+ const AllocationAddressIteratorArgs& args);
+
+ // Helper for MarkCurrentAllocations and MarkUnmarkedAllocations.
+ inline static void MarkIterator(const void* ptr, AllocValue* v,
+ const MarkArgs& 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 DumpMarkedObjects to dump all allocations with a given mark. It
+ // gets passed to AllocationMap::Iterate.
+ inline static void DumpMarkedIterator(const void* ptr, AllocValue* v,
+ const DumpMarkedArgs& args);
+
+#if defined(TYPE_PROFILING)
+ inline static void TallyTypesItererator(const void* ptr,
+ AllocValue* value,
+ AddressMap<TypeCount>* type_size_map);
+
+ inline static void DumpTypesIterator(const void* ptr,
+ TypeCount* size,
+ const DumpArgs& args);
+#endif // defined(TYPE_PROFILING)
+
+ // 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/chromium/third_party/tcmalloc/chromium/src/heap-profiler.cc b/chromium/third_party/tcmalloc/chromium/src/heap-profiler.cc
new file mode 100644
index 00000000000..dd94e360898
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/heap-profiler.cc
@@ -0,0 +1,695 @@
+// 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 <config.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h> // for open()
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+
+#include <algorithm>
+#include <string>
+
+#include <gperftools/heap-profiler.h>
+
+#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 <gperftools/malloc_hook.h>
+#include <gperftools/malloc_extension.h>
+#include "base/spinlock.h"
+#include "base/low_level_alloc.h"
+#include "base/sysinfo.h" // for GetUniquePathFromEnv()
+#include "deep-heap-profile.h"
+#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
+
+#if defined(__ANDROID__) || defined(ANDROID)
+// On android, there are no environment variables.
+// Instead, we use system properties, set via:
+// adb shell setprop prop_name prop_value
+// From <sys/system_properties.h>,
+// PROP_NAME_MAX 32
+// PROP_VALUE_MAX 92
+#define HEAPPROFILE "heapprof"
+#define HEAP_PROFILE_ALLOCATION_INTERVAL "heapprof.allocation_interval"
+#define HEAP_PROFILE_DEALLOCATION_INTERVAL "heapprof.deallocation_interval"
+#define HEAP_PROFILE_INUSE_INTERVAL "heapprof.inuse_interval"
+#define HEAP_PROFILE_TIME_INTERVAL "heapprof.time_interval"
+#define HEAP_PROFILE_MMAP_LOG "heapprof.mmap_log"
+#define HEAP_PROFILE_MMAP "heapprof.mmap"
+#define HEAP_PROFILE_ONLY_MMAP "heapprof.only_mmap"
+#define DEEP_HEAP_PROFILE "heapprof.deep_heap_profile"
+#define DEEP_HEAP_PROFILE_PAGEFRAME "heapprof.deep.pageframe"
+#define HEAP_PROFILE_TYPE_STATISTICS "heapprof.type_statistics"
+#else // defined(__ANDROID__) || defined(ANDROID)
+#define HEAPPROFILE "HEAPPROFILE"
+#define HEAP_PROFILE_ALLOCATION_INTERVAL "HEAP_PROFILE_ALLOCATION_INTERVAL"
+#define HEAP_PROFILE_DEALLOCATION_INTERVAL "HEAP_PROFILE_DEALLOCATION_INTERVAL"
+#define HEAP_PROFILE_INUSE_INTERVAL "HEAP_PROFILE_INUSE_INTERVAL"
+#define HEAP_PROFILE_TIME_INTERVAL "HEAP_PROFILE_TIME_INTERVAL"
+#define HEAP_PROFILE_MMAP_LOG "HEAP_PROFILE_MMAP_LOG"
+#define HEAP_PROFILE_MMAP "HEAP_PROFILE_MMAP"
+#define HEAP_PROFILE_ONLY_MMAP "HEAP_PROFILE_ONLY_MMAP"
+#define DEEP_HEAP_PROFILE "DEEP_HEAP_PROFILE"
+#define DEEP_HEAP_PROFILE_PAGEFRAME "DEEP_HEAP_PROFILE_PAGEFRAME"
+#define HEAP_PROFILE_TYPE_STATISTICS "HEAP_PROFILE_TYPE_STATISTICS"
+#endif // defined(__ANDROID__) || defined(ANDROID)
+
+using STL_NAMESPACE::string;
+using STL_NAMESPACE::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");
+DEFINE_bool(deep_heap_profile,
+ EnvToBool(DEEP_HEAP_PROFILE, false),
+ "If heap-profiling is on, profile deeper (Linux and Android)");
+DEFINE_int32(deep_heap_profile_pageframe,
+ EnvToInt(DEEP_HEAP_PROFILE_PAGEFRAME, 0),
+ "Needs deeper profile. If 1, dump page frame numbers (PFNs). "
+ "If 2, dump page counts (/proc/kpagecount) with PFNs.");
+#if defined(TYPE_PROFILING)
+DEFINE_bool(heap_profile_type_statistics,
+ EnvToBool(HEAP_PROFILE_TYPE_STATISTICS, false),
+ "If heap-profiling is on, dump type statistics.");
+#endif // defined(TYPE_PROFILING)
+
+
+//----------------------------------------------------------------------
+// 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
+static DeepHeapProfile* deep_profile = NULL; // deep memory profiler
+
+// Callback to generate a stack trace for an allocation. May be overriden
+// by an application to provide its own pseudo-stacks.
+static StackGeneratorFunction stack_generator_function =
+ HeapProfileTable::GetCallerStackTrace;
+
+//----------------------------------------------------------------------
+// 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<char*>(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.%05d.%04d%s",
+ filename_prefix, getpid(), 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<char*>(ProfilerMalloc(kProfileBufferSize));
+ }
+
+ if (deep_profile) {
+ deep_profile->DumpOrderedProfile(reason, global_profiler_buffer,
+ kProfileBufferSize, fd);
+ } else {
+ char* profile = DoGetHeapProfileLocked(global_profiler_buffer,
+ kProfileBufferSize);
+ RawWrite(fd, profile, strlen(profile));
+ }
+ RawClose(fd);
+
+#if defined(TYPE_PROFILING)
+ if (FLAGS_heap_profile_type_statistics) {
+ snprintf(file_name, sizeof(file_name), "%s.%05d.%04d.type",
+ filename_prefix, getpid(), dump_count);
+ RAW_VLOG(0, "Dumping type statistics to %s", file_name);
+ heap_profile->DumpTypeStatistics(file_name);
+ }
+#endif // defined(TYPE_PROFILING)
+
+ 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];
+ int64 current_time = time(NULL);
+ 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 &&
+ current_time - last_dump_time >=
+ FLAGS_heap_profile_time_interval) {
+ snprintf(buf, sizeof(buf), "%d 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 = stack_generator_function(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<int>(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 PRIxS 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=%" PRIuS ", 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 PRIxS 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=%" PRIuS ", "
+ "new_size=%" PRIuS ", 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 PRIxS 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=%" PRIuS ")",
+ (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=%" PRIdS ") = 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<char*>(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;
+
+ if (FLAGS_deep_heap_profile) {
+ // Initialize deep memory profiler
+ RAW_VLOG(0, "[%d] Starting a deep memory profiler", getpid());
+ deep_profile = new(ProfilerMalloc(sizeof(DeepHeapProfile)))
+ DeepHeapProfile(heap_profile, prefix, DeepHeapProfile::PageFrameType(
+ FLAGS_deep_heap_profile_pageframe));
+ }
+
+ // 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 only if provided.
+ if (!prefix)
+ return;
+ RAW_DCHECK(filename_prefix == NULL, "");
+ const int prefix_length = strlen(prefix);
+ filename_prefix = reinterpret_cast<char*>(ProfilerMalloc(prefix_length + 1));
+ memcpy(filename_prefix, prefix, prefix_length);
+ filename_prefix[prefix_length] = '\0';
+}
+
+extern "C" void HeapProfilerWithPseudoStackStart(
+ StackGeneratorFunction callback) {
+ {
+ // Ensure the callback is set before allocations can be recorded.
+ SpinLockHolder l(&heap_lock);
+ stack_generator_function = callback;
+ }
+ HeapProfilerStart(NULL);
+}
+
+extern "C" void IterateAllocatedObjects(AddressVisitor visitor, void* data) {
+ SpinLockHolder l(&heap_lock);
+
+ if (!is_on) return;
+
+ heap_profile->IterateAllocationAddresses(visitor, data);
+}
+
+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), "");
+ }
+
+ if (deep_profile) {
+ // free deep memory profiler
+ deep_profile->~DeepHeapProfile();
+ ProfilerFree(deep_profile);
+ deep_profile = NULL;
+ }
+
+ // 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);
+ }
+}
+
+extern "C" void HeapProfilerMarkBaseline() {
+ SpinLockHolder l(&heap_lock);
+
+ if (!is_on) return;
+
+ heap_profile->MarkCurrentAllocations(HeapProfileTable::MARK_ONE);
+}
+
+extern "C" void HeapProfilerMarkInteresting() {
+ SpinLockHolder l(&heap_lock);
+
+ if (!is_on) return;
+
+ heap_profile->MarkUnmarkedAllocations(HeapProfileTable::MARK_TWO);
+}
+
+extern "C" void HeapProfilerDumpAliveObjects(const char* filename) {
+ SpinLockHolder l(&heap_lock);
+
+ if (!is_on) return;
+
+ heap_profile->DumpMarkedObjects(HeapProfileTable::MARK_TWO, filename);
+}
+
+//----------------------------------------------------------------------
+// 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.
+#if !defined(__ANDROID__) && defined(HAVE_GETEUID)
+ if (getuid() != geteuid()) {
+ RAW_LOG(WARNING, ("HeapProfiler: ignoring " HEAPPROFILE " because "
+ "program seems to be setuid\n"));
+ return;
+ }
+#endif
+
+ HeapProfileTable::CleanupOldProfiles(fname);
+
+ HeapProfilerStart(fname);
+}
+
+// class used for finalization -- dumps the heap-profile at program exit
+struct HeapProfileEndWriter {
+ ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); }
+};
+
+// 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/chromium/third_party/tcmalloc/chromium/src/internal_logging.cc b/chromium/third_party/tcmalloc/chromium/src/internal_logging.cc
new file mode 100644
index 00000000000..0e95c2ccd65
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/internal_logging.cc
@@ -0,0 +1,194 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#include "internal_logging.h"
+#include <stdarg.h> // for va_end, va_start
+#include <stdio.h> // for vsnprintf, va_list, etc
+#include <stdlib.h> // for abort
+#include <string.h> // for strlen, memcpy
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+
+#include <gperftools/malloc_extension.h>
+#include "base/abort.h"
+#include "base/logging.h" // for perftools_vsnprintf
+#include "base/spinlock.h" // for SpinLockHolder, SpinLock
+
+static const int kLogBufSize = 800;
+
+// 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<uint64_t>(item.u_.snum), 10);
+ } else {
+ return AddNum(static_cast<uint64_t>(item.u_.snum), 10);
+ }
+ case LogItem::kPtr:
+ return AddStr("0x", 2)
+ && AddNum(reinterpret_cast<uintptr_t>(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/chromium/third_party/tcmalloc/chromium/src/internal_logging.h b/chromium/third_party/tcmalloc/chromium/src/internal_logging.h
new file mode 100644
index 00000000000..55e18085ddd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/internal_logging.h
@@ -0,0 +1,152 @@
+// 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 <opensource@google.com>
+//
+// Internal logging and related utility routines.
+
+#ifndef TCMALLOC_INTERNAL_LOGGING_H_
+#define TCMALLOC_INTERNAL_LOGGING_H_
+
+#include <config.h>
+#include <stddef.h> // for size_t
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#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)
+
+#define CHECK_CONDITION_PRINT(cond, str) \
+do { \
+ if (!(cond)) { \
+ ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, str); \
+ } \
+} 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)
+#define ASSERT_PRINT(cond, str) CHECK_CONDITION_PRINT(cond, str)
+#else
+#define ASSERT(cond) ((void) 0)
+#define ASSERT_PRINT(cond, str) ((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/chromium/third_party/tcmalloc/chromium/src/libc_override.h b/chromium/third_party/tcmalloc/chromium/src/libc_override.h
new file mode 100644
index 00000000000..089084a2e49
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/libc_override.h
@@ -0,0 +1,94 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h> // for __GLIBC__
+#endif
+#include <gperftools/tcmalloc.h>
+
+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)
+// "libc_override_redefine.h" is included in the original gperftools. But,
+// we define allocator functions in Chromium's base/allocator/allocator_shim.cc
+// on Windows. We don't include libc_override_redefine.h here.
+// ReplaceSystemAlloc() is defined here instead.
+static void ReplaceSystemAlloc() { }
+
+#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/chromium/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h b/chromium/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
new file mode 100644
index 00000000000..feefe0ca45f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
@@ -0,0 +1,111 @@
+// 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 <opensource@google.com>
+//
+// 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 <sys/cdefs.h> // for __THROW
+#endif
+#include <gperftools/tcmalloc.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)))
+
+#if defined(__ANDROID__)
+// Android's bionic doesn't have std::bad_alloc.
+#define STD_BAD_ALLOC
+#else
+#define STD_BAD_ALLOC std::bad_alloc
+#endif
+
+void* operator new(size_t size) throw (STD_BAD_ALLOC)
+ ALIAS(tc_new);
+void operator delete(void* p) __THROW
+ ALIAS(tc_delete);
+void* operator new[](size_t size) throw (STD_BAD_ALLOC)
+ ALIAS(tc_newarray);
+void operator delete[](void* p) __THROW
+ ALIAS(tc_deletearray);
+void* operator new(size_t size, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_new_nothrow);
+void* operator new[](size_t size, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_newarray_nothrow);
+void operator delete(void* p, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_delete_nothrow);
+void operator delete[](void* p, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_deletearray_nothrow);
+
+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* 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);
+ void malloc_stats(void) __THROW ALIAS(tc_malloc_stats);
+ 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__) && defined(ANDROID_NON_SDK_BUILD)
+ // In Android tree this function is defined differently than in the NDK.
+ 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/chromium/third_party/tcmalloc/chromium/src/libc_override_glibc.h b/chromium/third_party/tcmalloc/chromium/src/libc_override_glibc.h
new file mode 100644
index 00000000000..7cdbe976339
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/libc_override_glibc.h
@@ -0,0 +1,159 @@
+// 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 <opensource@google.com>
+//
+// 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_
+
+// MALLOC_HOOK_MAYBE_VOLATILE is defined at config.h in the original gperftools.
+// Chromium does this check with the macro __MALLOC_HOOK_VOLATILE.
+// GLibc 2.14+ requires the hook functions be declared volatile, based on the
+// value of the define __MALLOC_HOOK_VOLATILE. For compatibility with
+// older/non-GLibc implementations, provide an empty definition.
+#if !defined(__MALLOC_HOOK_VOLATILE)
+#define MALLOC_HOOK_MAYBE_VOLATILE /**/
+#else
+#define MALLOC_HOOK_MAYBE_VOLATILE __MALLOC_HOOK_VOLATILE
+#endif
+
+#include <config.h>
+#include <features.h> // for __GLIBC__
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+#include <gperftools/tcmalloc.h>
+
+#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__)
+
+
+// We also have to hook libc malloc. While our work with weak symbols
+// should make sure libc malloc is never called in most situations, it
+// can be worked around by shared libraries with the DEEPBIND
+// environment variable set. The below hooks libc to call our malloc
+// routines even in that situation. In other situations, this hook
+// should never be called.
+extern "C" {
+static void* glibc_override_malloc(size_t size, const void *caller) {
+ return tc_malloc(size);
+}
+static void* glibc_override_realloc(void *ptr, size_t size,
+ const void *caller) {
+ return tc_realloc(ptr, size);
+}
+static void glibc_override_free(void *ptr, const void *caller) {
+ tc_free(ptr);
+}
+static void* glibc_override_memalign(size_t align, size_t size,
+ const void *caller) {
+ return tc_memalign(align, size);
+}
+
+// We should be using __malloc_initialize_hook here, like the #if 0
+// code below. (See http://swoolley.org/man.cgi/3/malloc_hook.)
+// However, this causes weird linker errors with programs that link
+// with -static, so instead we just assign the vars directly at
+// static-constructor time. That should serve the same effect of
+// making sure the hooks are set before the first malloc call the
+// program makes.
+#if 0
+#include <malloc.h> // for __malloc_hook, etc.
+void glibc_override_malloc_init_hook(void) {
+ __malloc_hook = glibc_override_malloc;
+ __realloc_hook = glibc_override_realloc;
+ __free_hook = glibc_override_free;
+ __memalign_hook = glibc_override_memalign;
+}
+
+void (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_initialize_hook)(void)
+ = &glibc_override_malloc_init_hook;
+#endif
+
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_hook)(size_t, const void*)
+ = &glibc_override_malloc;
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __realloc_hook)(void*, size_t, const void*)
+ = &glibc_override_realloc;
+void (* MALLOC_HOOK_MAYBE_VOLATILE __free_hook)(void*, const void*)
+ = &glibc_override_free;
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __memalign_hook)(size_t,size_t, const void*)
+ = &glibc_override_memalign;
+
+} // extern "C"
+
+// No need to write ReplaceSystemAlloc(); one of the #includes above
+// did it for us.
+
+#endif // TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/libc_override_osx.h b/chromium/third_party/tcmalloc/chromium/src/libc_override_osx.h
new file mode 100644
index 00000000000..78a0ef2f959
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/libc_override_osx.h
@@ -0,0 +1,275 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+#include <gperftools/tcmalloc.h>
+
+#if !defined(__APPLE__)
+# error libc_override_glibc-osx.h is for OS X distributions only.
+#endif
+
+#include <AvailabilityMacros.h>
+#include <malloc/malloc.h>
+
+// 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
+ // <malloc/malloc.h> 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<void*>(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) {
+ // Hopefully unneeded by us!
+}
+
+void mi_force_unlock(malloc_zone_t *zone) {
+ // Hopefully unneeded by us!
+}
+
+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 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 = malloc_default_zone();
+ malloc_zone_unregister(default_zone);
+ malloc_zone_register(default_zone);
+}
+
+#endif // TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/libc_override_redefine.h b/chromium/third_party/tcmalloc/chromium/src/libc_override_redefine.h
new file mode 100644
index 00000000000..d8d999ce7bb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/libc_override_redefine.h
@@ -0,0 +1,93 @@
+// 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 <opensource@google.com>
+//
+// 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_
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+
+#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
+
+void* operator new(size_t size) { return tc_new(size); }
+void operator delete(void* p) __THROW { tc_delete(p); }
+void* operator new[](size_t size) { return tc_newarray(size); }
+void operator delete[](void* p) __THROW { tc_deletearray(p); }
+void* operator new(size_t size, const std::nothrow_t& nt) __THROW {
+ return tc_new_nothrow(size, nt);
+}
+void* operator new[](size_t size, const std::nothrow_t& nt) __THROW {
+ return tc_newarray_nothrow(size, nt);
+}
+void operator delete(void* ptr, const std::nothrow_t& nt) __THROW {
+ return tc_delete_nothrow(ptr, nt);
+}
+void operator delete[](void* ptr, const std::nothrow_t& nt) __THROW {
+ return tc_deletearray_nothrow(ptr, nt);
+}
+extern "C" {
+ void* malloc(size_t s) __THROW { return tc_malloc(s); }
+ void free(void* p) __THROW { tc_free(p); }
+ void* realloc(void* p, size_t s) __THROW { return tc_realloc(p, s); }
+ void* calloc(size_t n, size_t s) __THROW { return tc_calloc(n, s); }
+ void cfree(void* p) __THROW { tc_cfree(p); }
+ void* memalign(size_t a, size_t s) __THROW { return tc_memalign(a, s); }
+ void* valloc(size_t s) __THROW { return tc_valloc(s); }
+ void* pvalloc(size_t s) __THROW { return tc_pvalloc(s); }
+ int posix_memalign(void** r, size_t a, size_t s) __THROW {
+ return tc_posix_memalign(r, a, s);
+ }
+ void malloc_stats(void) __THROW { tc_malloc_stats(); }
+ int mallopt(int cmd, int v) __THROW { return tc_mallopt(cmd, v); }
+#ifdef HAVE_STRUCT_MALLINFO
+ struct mallinfo mallinfo(void) __THROW { return tc_mallinfo(); }
+#endif
+ size_t malloc_size(void* p) __THROW { return tc_malloc_size(p); }
+ size_t malloc_usable_size(void* p) __THROW { 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/chromium/third_party/tcmalloc/chromium/src/linked_list.h b/chromium/third_party/tcmalloc/chromium/src/linked_list.h
new file mode 100644
index 00000000000..4b0af1b9f63
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/linked_list.h
@@ -0,0 +1,102 @@
+// 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 <opensource@google.com>
+//
+// Some very basic linked list functions for dealing with using void * as
+// storage.
+
+#ifndef TCMALLOC_LINKED_LIST_H_
+#define TCMALLOC_LINKED_LIST_H_
+
+#include <stddef.h>
+
+namespace tcmalloc {
+
+inline void *SLL_Next(void *t) {
+ return *(reinterpret_cast<void**>(t));
+}
+
+inline void SLL_SetNext(void *t, void *n) {
+ *(reinterpret_cast<void**>(t)) = n;
+}
+
+inline void SLL_Push(void **list, void *element) {
+ SLL_SetNext(element, *list);
+ *list = element;
+}
+
+inline void *SLL_Pop(void **list) {
+ void *result = *list;
+ *list = SLL_Next(*list);
+ return result;
+}
+
+// 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/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc b/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
new file mode 100644
index 00000000000..a060b54eeb9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "linux_shadow_stacks.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const int kMaxShadowIndex = 2048;
+static const char kOverflowMessage[] = "Shadow stack overflow\n";
+
+// Thread-local vars.
+__thread
+int shadow_index = -1;
+__thread
+void *shadow_ip_stack[kMaxShadowIndex];
+__thread
+void *shadow_sp_stack[kMaxShadowIndex];
+
+enum Status {UNINITIALIZED = -1, DISABLED, ENABLED};
+Status status = UNINITIALIZED;
+
+void init() {
+ if (!getenv("KEEP_SHADOW_STACKS")) {
+ status = DISABLED;
+ return;
+ }
+ status = ENABLED;
+}
+
+void __cyg_profile_func_enter(void *this_fn, void *call_site) {
+ if (status == DISABLED) return;
+ if (status == UNINITIALIZED) {
+ init();
+ if (status == DISABLED) return;
+ }
+ shadow_index++;
+ if (shadow_index > kMaxShadowIndex) {
+ // Avoid memory allocation when reporting an error.
+ write(2, kOverflowMessage, sizeof(kOverflowMessage));
+ int a = 0;
+ a = a / a;
+ }
+ // Update the shadow IP stack
+ shadow_ip_stack[shadow_index] = this_fn;
+ // Update the shadow SP stack. The code for obtaining the frame address was
+ // borrowed from Google Perftools, http://code.google.com/p/google-perftools/
+ //
+ // 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.
+ 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 this_fn, so it's not in sp[2]),
+ // so we also prefer __builtin_frame_address when running under llvm.
+ sp = reinterpret_cast<void**>(__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 **)&this_fn - 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 Cannot obtain SP (possibly compiling on a non x86 architecture)
+#endif
+ shadow_sp_stack[shadow_index] = (void*)sp;
+ return;
+}
+
+void __cyg_profile_func_exit(void *this_fn, void *call_site) {
+ if (status == DISABLED) return;
+ shadow_index--;
+}
+
+void *get_shadow_ip_stack(int *index /*OUT*/) {
+ *index = shadow_index;
+ return shadow_ip_stack;
+}
+
+void *get_shadow_sp_stack(int *index /*OUT*/) {
+ *index = shadow_index;
+ return shadow_sp_stack;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.h b/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.h
new file mode 100644
index 00000000000..e519d298958
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/linux_shadow_stacks.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_TCMALLOC_CHROMIUM_SRC_LINUX_SHADOW_STACKS_H__
+#define THIRD_PARTY_TCMALLOC_CHROMIUM_SRC_LINUX_SHADOW_STACKS_H__
+
+#define NO_INSTRUMENT __attribute__((no_instrument_function))
+
+extern "C" {
+void init() NO_INSTRUMENT;
+void __cyg_profile_func_enter(void *this_fn, void *call_site) NO_INSTRUMENT;
+void __cyg_profile_func_exit(void *this_fn, void *call_site) NO_INSTRUMENT;
+void *get_shadow_ip_stack(int *index /*OUT*/) NO_INSTRUMENT;
+void *get_shadow_sp_stack(int *index /*OUT*/) NO_INSTRUMENT;
+}
+
+#undef NO_INSTRUMENT
+
+#endif // THIRD_PARTY_TCMALLOC_CHROMIUM_SRC_LINUX_SHADOW_STACKS_H__
diff --git a/chromium/third_party/tcmalloc/chromium/src/malloc_extension.cc b/chromium/third_party/tcmalloc/chromium/src/malloc_extension.cc
new file mode 100644
index 00000000000..ad8fb8e6875
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/malloc_extension.cc
@@ -0,0 +1,377 @@
+// 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: Sanjay Ghemawat <opensource@google.com>
+
+#include <config.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#include <string>
+#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 "thread_cache.h"
+
+using STL_NAMESPACE::string;
+using STL_NAMESPACE::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<size_t>(-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<MallocExtension::FreeListInfo>* v) {
+ v->clear();
+}
+
+// The current malloc extension object.
+
+static pthread_once_t module_init = PTHREAD_ONCE_INIT;
+static MallocExtension* current_instance = NULL;
+
+static void InitModule() {
+ current_instance = new MallocExtension;
+#ifndef NO_HEAP_CHECK
+ HeapLeakChecker::IgnoreObject(current_instance);
+#endif
+}
+
+MallocExtension* MallocExtension::instance() {
+ perftools_pthread_once(&module_init, InitModule);
+ return current_instance;
+}
+
+void MallocExtension::Register(MallocExtension* implementation) {
+ perftools_pthread_once(&module_init, 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;
+ }
+}
+
+unsigned int MallocExtension::GetBytesAllocatedOnCurrentThread() {
+ return tcmalloc::ThreadCache::GetBytesAllocatedOnCurrentThread();
+}
+
+// -----------------------------------------------------------------------
+// Heap sampling support
+// -----------------------------------------------------------------------
+
+namespace {
+
+// Accessors
+uintptr_t Count(void** entry) {
+ return reinterpret_cast<uintptr_t>(entry[0]);
+}
+uintptr_t Size(void** entry) {
+ return reinterpret_cast<uintptr_t>(entry[1]);
+}
+uintptr_t Depth(void** entry) {
+ return reinterpret_cast<uintptr_t>(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<uint64>(count),
+ static_cast<uint64>(size),
+ static_cast<uint64>(count),
+ static_cast<uint64>(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));
+
+// 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_Ownership>(
+ MallocExtension::instance()->GetOwnership(p));
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/malloc_hook-inl.h b/chromium/third_party/tcmalloc/chromium/src/malloc_hook-inl.h
new file mode 100644
index 00000000000..27e5bdcaafe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/malloc_hook-inl.h
@@ -0,0 +1,322 @@
+// 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 <stddef.h>
+#include <sys/types.h>
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+#include <gperftools/malloc_hook.h>
+
+namespace base { namespace internal {
+
+// The following (implementation) code is DEPRECATED.
+// A simple atomic pointer class that can be initialized by the linker
+// when you define a namespace-scope variable as:
+//
+// AtomicPtr<Foo*> my_global = { &initial_value };
+//
+// This isn't suitable for a general atomic<> class because of the
+// public access to data_.
+template<typename PtrT>
+class AtomicPtr {
+ public:
+ COMPILE_ASSERT(sizeof(PtrT) <= sizeof(AtomicWord),
+ PtrT_should_fit_in_AtomicWord);
+
+ PtrT Get() const {
+ // Depending on the system, Acquire_Load(AtomicWord*) may have
+ // been defined to return an AtomicWord, Atomic32, or Atomic64.
+ // We hide that implementation detail here with an explicit cast.
+ // This prevents MSVC 2005, at least, from complaining (it has to
+ // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't).
+ return reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::Acquire_Load(&data_)));
+ }
+
+ // Sets the contained value to new_val and returns the old value,
+ // atomically, with acquire and release semantics.
+ // This is a full-barrier instruction.
+ PtrT Exchange(PtrT new_val);
+
+ // Atomically executes:
+ // result = data_
+ // if (data_ == old_val)
+ // data_ = new_val;
+ // return result;
+ // This is a full-barrier instruction.
+ PtrT CompareAndSwap(PtrT old_val, PtrT new_val);
+
+ // Not private so that the class is an aggregate and can be
+ // initialized by the linker. Don't access this directly.
+ AtomicWord data_;
+};
+
+// These are initialized in malloc_hook.cc
+extern AtomicPtr<MallocHook::NewHook> new_hook_;
+extern AtomicPtr<MallocHook::DeleteHook> delete_hook_;
+extern AtomicPtr<MallocHook::PreMmapHook> premmap_hook_;
+extern AtomicPtr<MallocHook::MmapHook> mmap_hook_;
+extern AtomicPtr<MallocHook::MunmapHook> munmap_hook_;
+extern AtomicPtr<MallocHook::MremapHook> mremap_hook_;
+extern AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_;
+extern AtomicPtr<MallocHook::SbrkHook> sbrk_hook_;
+// End DEPRECATED code.
+
+// Maximum of 7 hooks means that HookList is 8 words.
+static const int kHookListMaxValues = 7;
+
+// HookList: a class that provides synchronized insertions and removals and
+// lockless traversal. Most of the implementation is in malloc_hook.cc.
+template <typename T>
+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);
+
+ // 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::Acquire_Load(&priv_end) == 0;
+ }
+
+ // 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.
+ AtomicWord priv_end;
+ AtomicWord priv_data[kHookListMaxValues];
+};
+
+extern HookList<MallocHook::NewHook> new_hooks_;
+extern HookList<MallocHook::DeleteHook> delete_hooks_;
+extern HookList<MallocHook::PreMmapHook> premmap_hooks_;
+extern HookList<MallocHook::MmapHook> mmap_hooks_;
+extern HookList<MallocHook::MmapReplacement> mmap_replacement_;
+extern HookList<MallocHook::MunmapHook> munmap_hooks_;
+extern HookList<MallocHook::MunmapReplacement> munmap_replacement_;
+extern HookList<MallocHook::MremapHook> mremap_hooks_;
+extern HookList<MallocHook::PreSbrkHook> presbrk_hooks_;
+extern HookList<MallocHook::SbrkHook> sbrk_hooks_;
+
+} } // namespace base::internal
+
+// The following method is DEPRECATED
+inline MallocHook::NewHook MallocHook::GetNewHook() {
+ return base::internal::new_hook_.Get();
+}
+
+inline void MallocHook::InvokeNewHook(const void* p, size_t s) {
+ if (!base::internal::new_hooks_.empty()) {
+ InvokeNewHookSlow(p, s);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::NewHook hook = MallocHook::GetNewHook();
+ if (hook != NULL) (*hook)(p, s);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::DeleteHook MallocHook::GetDeleteHook() {
+ return base::internal::delete_hook_.Get();
+}
+
+inline void MallocHook::InvokeDeleteHook(const void* p) {
+ if (!base::internal::delete_hooks_.empty()) {
+ InvokeDeleteHookSlow(p);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::DeleteHook hook = MallocHook::GetDeleteHook();
+ if (hook != NULL) (*hook)(p);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() {
+ return base::internal::premmap_hook_.Get();
+}
+
+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 code is DEPRECATED.
+ MallocHook::PreMmapHook hook = MallocHook::GetPreMmapHook();
+ if (hook != NULL) (*hook)(start, size,
+ protection, flags,
+ fd, offset);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::MmapHook MallocHook::GetMmapHook() {
+ return base::internal::mmap_hook_.Get();
+}
+
+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);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::MmapHook hook = MallocHook::GetMmapHook();
+ if (hook != NULL) (*hook)(result,
+ start, size,
+ protection, flags,
+ fd, offset);
+ // End DEPRECATED code.
+}
+
+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_hook_.Get();
+}
+
+inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) {
+ if (!base::internal::munmap_hooks_.empty()) {
+ InvokeMunmapHookSlow(p, size);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::MunmapHook hook = MallocHook::GetMunmapHook();
+ if (hook != NULL) (*hook)(p, size);
+ // End DEPRECATED code.
+}
+
+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_hook_.Get();
+}
+
+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 code is DEPRECATED.
+ MallocHook::MremapHook hook = MallocHook::GetMremapHook();
+ if (hook != NULL) (*hook)(result,
+ old_addr, old_size,
+ new_size, flags, new_addr);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() {
+ return base::internal::presbrk_hook_.Get();
+}
+
+inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) {
+ if (!base::internal::presbrk_hooks_.empty() && increment != 0) {
+ InvokePreSbrkHookSlow(increment);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::PreSbrkHook hook = MallocHook::GetPreSbrkHook();
+ if (hook != NULL && increment != 0) (*hook)(increment);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::SbrkHook MallocHook::GetSbrkHook() {
+ return base::internal::sbrk_hook_.Get();
+}
+
+inline void MallocHook::InvokeSbrkHook(const void* result,
+ ptrdiff_t increment) {
+ if (!base::internal::sbrk_hooks_.empty() && increment != 0) {
+ InvokeSbrkHookSlow(result, increment);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::SbrkHook hook = MallocHook::GetSbrkHook();
+ if (hook != NULL && increment != 0) (*hook)(result, increment);
+ // End DEPRECATED code.
+}
+
+#endif /* _MALLOC_HOOK_INL_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/malloc_hook.cc b/chromium/third_party/tcmalloc/chromium/src/malloc_hook.cc
new file mode 100644
index 00000000000..2f8608e41b0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/malloc_hook.cc
@@ -0,0 +1,723 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+
+// 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 <sys/mman.h>
+# undef mremap
+#endif
+
+#include <stddef.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <algorithm>
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "maybe_threads.h"
+#include "malloc_hook-inl.h"
+#include <gperftools/malloc_hook.h>
+
+// 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 <gperftools/stacktrace.h>
+#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 {
+
+// The code below is DEPRECATED.
+template<typename PtrT>
+PtrT AtomicPtr<PtrT>::Exchange(PtrT new_val) {
+ base::subtle::MemoryBarrier(); // Release semantics.
+ // Depending on the system, NoBarrier_AtomicExchange(AtomicWord*)
+ // may have been defined to return an AtomicWord, Atomic32, or
+ // Atomic64. We hide that implementation detail here with an
+ // explicit cast. This prevents MSVC 2005, at least, from complaining.
+ PtrT old_val = reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::NoBarrier_AtomicExchange(
+ &data_,
+ reinterpret_cast<AtomicWord>(new_val))));
+ base::subtle::MemoryBarrier(); // And acquire semantics.
+ return old_val;
+}
+
+template<typename PtrT>
+PtrT AtomicPtr<PtrT>::CompareAndSwap(PtrT old_val, PtrT new_val) {
+ base::subtle::MemoryBarrier(); // Release semantics.
+ PtrT retval = reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::NoBarrier_CompareAndSwap(
+ &data_,
+ reinterpret_cast<AtomicWord>(old_val),
+ reinterpret_cast<AtomicWord>(new_val))));
+ base::subtle::MemoryBarrier(); // And acquire semantics.
+ return retval;
+}
+
+AtomicPtr<MallocHook::NewHook> new_hook_ = { 0 };
+AtomicPtr<MallocHook::DeleteHook> delete_hook_ = { 0 };
+AtomicPtr<MallocHook::PreMmapHook> premmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MmapHook> mmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MunmapHook> munmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MremapHook> mremap_hook_ = { 0 };
+AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_ = { 0 };
+AtomicPtr<MallocHook::SbrkHook> sbrk_hook_ = { 0 };
+// End of DEPRECATED code section.
+
+// 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 <typename T>
+bool HookList<T>::Add(T value_as_t) {
+ AtomicWord value = bit_cast<AtomicWord>(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::Release_Store(&priv_data[index], value);
+ if (prev_num_hooks <= index) {
+ base::subtle::Release_Store(&priv_end, index + 1);
+ }
+ return true;
+}
+
+template <typename T>
+bool HookList<T>::Remove(T value_as_t) {
+ if (value_as_t == 0) {
+ return false;
+ }
+ SpinLockHolder l(&hooklist_spinlock);
+ AtomicWord hooks_end = base::subtle::Acquire_Load(&priv_end);
+ int index = 0;
+ while (index < hooks_end && value_as_t != bit_cast<T>(
+ base::subtle::Acquire_Load(&priv_data[index]))) {
+ ++index;
+ }
+ if (index == hooks_end) {
+ return false;
+ }
+ base::subtle::Release_Store(&priv_data[index], 0);
+ if (hooks_end == index + 1) {
+ // Adjust hooks_end down to the lowest possible value.
+ hooks_end = index;
+ while ((hooks_end > 0) &&
+ (base::subtle::Acquire_Load(&priv_data[hooks_end - 1]) == 0)) {
+ --hooks_end;
+ }
+ base::subtle::Release_Store(&priv_end, hooks_end);
+ }
+ return true;
+}
+
+template <typename T>
+int HookList<T>::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<T>(data);
+ ++actual_hooks_end;
+ --n;
+ }
+ }
+ return actual_hooks_end;
+}
+
+// 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<AtomicWord>(initial_value) } }
+
+// Explicit instantiation for malloc_hook_test.cc. This ensures all the methods
+// are instantiated.
+template struct HookList<MallocHook::NewHook>;
+
+HookList<MallocHook::NewHook> new_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook);
+HookList<MallocHook::DeleteHook> delete_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::PreMmapHook> premmap_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook);
+HookList<MallocHook::MmapHook> mmap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::MunmapHook> munmap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::MremapHook> mremap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::PreSbrkHook> presbrk_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(InitialPreSbrkHook);
+HookList<MallocHook::SbrkHook> sbrk_hooks_ = INIT_HOOK_LIST;
+
+// These lists contain either 0 or 1 hooks.
+HookList<MallocHook::MmapReplacement> mmap_replacement_ = { 0 };
+HookList<MallocHook::MunmapReplacement> munmap_replacement_ = { 0 };
+
+#undef INIT_HOOK_LIST_WITH_VALUE
+#undef INIT_HOOK_LIST
+
+} } // namespace base::internal
+
+// The code below is DEPRECATED.
+using base::internal::new_hook_;
+using base::internal::delete_hook_;
+using base::internal::premmap_hook_;
+using base::internal::mmap_hook_;
+using base::internal::munmap_hook_;
+using base::internal::mremap_hook_;
+using base::internal::presbrk_hook_;
+using base::internal::sbrk_hook_;
+// End of DEPRECATED code section.
+
+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_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook) {
+ RAW_VLOG(10, "SetDeleteHook(%p)", hook);
+ return delete_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook) {
+ RAW_VLOG(10, "SetPreMmapHook(%p)", hook);
+ return premmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook) {
+ RAW_VLOG(10, "SetMmapHook(%p)", hook);
+ return mmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook) {
+ RAW_VLOG(10, "SetMunmapHook(%p)", hook);
+ return munmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook) {
+ RAW_VLOG(10, "SetMremapHook(%p)", hook);
+ return mremap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook) {
+ RAW_VLOG(10, "SetPreSbrkHook(%p)", hook);
+ return presbrk_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook) {
+ RAW_VLOG(10, "SetSbrkHook(%p)", hook);
+ return sbrk_hook_.Exchange(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) {
+ INVOKE_HOOKS(NewHook, new_hooks_, (p, s));
+}
+
+void MallocHook::InvokeDeleteHookSlow(const void* p) {
+ 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
+
+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<uintptr_t>(ATTRIBUTE_SECTION_START(name)) <= \
+ reinterpret_cast<uintptr_t>(addr) && \
+ reinterpret_cast<uintptr_t>(addr) < \
+ reinterpret_cast<uintptr_t>(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;
+ }
+}
+
+// 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])) {
+ 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/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h b/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h
new file mode 100644
index 00000000000..dae868c3e09
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h
@@ -0,0 +1,165 @@
+// 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 <unistd.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+// Make sure mmap doesn't get #define'd away by <sys/mman.h>
+#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) {
+ void* curbrk = 0;
+
+#if defined(__x86_64__) || defined(__amd64__)
+# ifdef PIC
+ __asm__ __volatile__(
+ "movq .curbrk@GOTPCREL(%%rip), %%rdx;"
+ "movq (%%rdx), %%rax;"
+ "movq %%rax, %0;"
+ : "=r" (curbrk)
+ :: "%rdx", "%rax");
+# else
+ __asm__ __volatile__(
+ "movq .curbrk(%%rip), %%rax;"
+ "movq %%rax, %0;"
+ : "=r" (curbrk)
+ :: "%rax");
+# endif
+#else
+ __asm__ __volatile__(
+ "movl .curbrk, %%eax;"
+ "movl %%eax, %0;"
+ : "=r" (curbrk)
+ :: "%eax");
+#endif
+
+ if (increment == 0) {
+ return curbrk;
+ }
+
+ char* prevbrk = static_cast<char*>(curbrk);
+ void* newbrk = prevbrk + increment;
+
+ if (brk(newbrk) == -1) {
+ return reinterpret_cast<void*>(static_cast<intptr_t>(-1));
+ }
+
+ return prevbrk;
+}
+
+
+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<size_t>(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/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h b/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
new file mode 100644
index 00000000000..ee36efb4613
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
@@ -0,0 +1,267 @@
+// 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 <opensource@google.com>
+
+// 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 <unistd.h>
+#if defined(__ANDROID__)
+#include <sys/syscall.h>
+#ifndef ANDROID_NON_SDK_BUILD
+#include <sys/linux-syscalls.h>
+#endif
+#else
+#include <syscall.h>
+#endif
+#include <sys/mman.h>
+#include <errno.h>
+#include "base/linux_syscall_support.h"
+
+// SYS_mmap2, SYS_munmap, SYS_mremap and __off64_t are not defined in Android.
+#if defined(__ANDROID__)
+#ifndef SYS_mmap2
+#define SYS_mmap2 __NR_mmap2
+#endif
+#ifndef SYS_munmap
+#define SYS_munmap __NR_munmap
+#endif
+#ifndef SYS_mremap
+#define SYS_mremap __NR_mremap
+#endif
+typedef off64_t __off64_t;
+#endif // defined(__ANDROID__)
+
+// 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(_MIPS_SIM) && _MIPS_SIM == _ABI64)
+
+static inline void* do_mmap64(void *start, size_t length,
+ int prot, int flags,
+ int fd, __off64_t offset) __THROW {
+ // The original gperftools uses sys_mmap() here. But, it is not allowed by
+ // Chromium's sandbox.
+ return (void *)syscall(SYS_mmap, start, length, prot, flags, fd, offset);
+}
+
+#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,
+ (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 mmap doesn't get #define'd away by <sys/mman.h>
+# 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);
+#if !defined(__ANDROID__)
+ void* sbrk(ptrdiff_t increment) __THROW
+ ATTRIBUTE_SECTION(malloc_hook);
+#endif
+}
+
+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<size_t>(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)) {
+ // The original gperftools uses sys_munmap() here. But, it is not allowed
+ // by Chromium's sandbox.
+ 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);
+ // The original gperftools uses sys_mremap() here. But, it is not allowed by
+ // Chromium's sandbox.
+ 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;
+}
+
+// Don't hook sbrk() in Android, since it doesn't expose __sbrk.
+#if !defined(__ANDROID__)
+// libc's version:
+extern "C" void* __sbrk(ptrdiff_t increment);
+
+extern "C" void* sbrk(ptrdiff_t increment) __THROW {
+ MallocHook::InvokePreSbrkHook(increment);
+ void *result = __sbrk(increment);
+ MallocHook::InvokeSbrkHook(result, increment);
+ return result;
+}
+#endif // !defined(__ANDROID__)
+
+/*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/chromium/third_party/tcmalloc/chromium/src/maybe_threads.cc b/chromium/third_party/tcmalloc/chromium/src/maybe_threads.cc
new file mode 100644
index 00000000000..80a07402e90
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/maybe_threads.cc
@@ -0,0 +1,137 @@
+// 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 <opensource@google.com>
+//
+// 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 <assert.h>
+#include <string.h> // for memcmp
+#include <stdio.h> // 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 <string>
+#include "maybe_threads.h"
+#include "base/basictypes.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;
+ 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;
+}
+
+#define MAX_PERTHREAD_VALS 16
+static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
+static int next_key;
+
+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 = (pthread_key_t)(next_key++);
+ return 0;
+ }
+}
+
+void *perftools_pthread_getspecific(pthread_key_t key) {
+ if (pthread_getspecific) {
+ return pthread_getspecific(key);
+ } else {
+ return perftools_pthread_specific_vals[(int)key];
+ }
+}
+
+int perftools_pthread_setspecific(pthread_key_t key, void *val) {
+ if (pthread_setspecific) {
+ return pthread_setspecific(key, val);
+ } else {
+ perftools_pthread_specific_vals[(int)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 <stdio.h>, 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;
+ }
+#elif defined(__ANDROID__)
+ // Android >= 2.3 (GB) always implement pthread_once.
+ return pthread_once(ctl, init_routine);
+#else
+ 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;
+ }
+#endif
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/maybe_threads.h b/chromium/third_party/tcmalloc/chromium/src/maybe_threads.h
new file mode 100644
index 00000000000..5f35e00cdf5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/maybe_threads.h
@@ -0,0 +1,52 @@
+// 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 <opensource@google.com>
+
+//-------------------------------------------------------------------
+// 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 <pthread.h>
+#endif
+
+int perftools_pthread_key_create(pthread_key_t *key,
+ void (*destr_function) (void *));
+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));
+
+#endif /* GOOGLE_MAYBE_THREADS_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/memfs_malloc.cc b/chromium/third_party/tcmalloc/chromium/src/memfs_malloc.cc
new file mode 100644
index 00000000000..13c7424478c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/memfs_malloc.cc
@@ -0,0 +1,267 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Arun Sharma
+//
+// A tcmalloc system allocator that uses a memory based filesystem such as
+// tmpfs or hugetlbfs
+//
+// Since these only exist on linux, we only register this allocator there.
+
+#ifdef __linux
+
+#include <config.h>
+#include <errno.h> // for errno, EINVAL
+#include <inttypes.h> // for PRId64
+#include <limits.h> // for PATH_MAX
+#include <stddef.h> // for size_t, NULL
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for int64_t, uintptr_t
+#endif
+#include <stdio.h> // for snprintf
+#include <stdlib.h> // for mkstemp
+#include <string.h> // for strerror
+#include <sys/mman.h> // for mmap, MAP_FAILED, etc
+#include <sys/statfs.h> // for fstatfs, statfs
+#include <unistd.h> // for ftruncate, off_t, unlink
+#include <new> // for operator new
+#include <string>
+
+#include <gperftools/malloc_extension.h>
+#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");
+
+// 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 char hugetlb_space[sizeof(HugetlbSysAllocator)];
+
+// 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 (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 (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 (aligned_size < size) {
+ return fallback_->Alloc(size, actual_size, alignment);
+ }
+
+ void* result = AllocInternal(aligned_size, actual_size, new_alignment);
+ if (result != NULL) {
+ return result;
+ }
+ 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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void *result;
+ result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ FLAGS_memfs_malloc_map_private ? MAP_PRIVATE : MAP_SHARED,
+ hugetlb_fd_, hugetlb_base_);
+ if (result == reinterpret_cast<void*>(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<uintptr_t>(result);
+
+ // Adjust the return memory so it is aligned
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+ ptr += adjust;
+ hugetlb_base_ += (size + extra);
+
+ if (actual_size) {
+ *actual_size = size + extra - adjust;
+ }
+
+ return reinterpret_cast<void*>(ptr);
+}
+
+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) HugetlbSysAllocator(alloc);
+ if (hp->Initialize()) {
+ MallocExtension::instance()->SetSystemAllocator(hp);
+ }
+ }
+});
+
+#endif /* ifdef __linux */
diff --git a/chromium/third_party/tcmalloc/chromium/src/memory_region_map.cc b/chromium/third_party/tcmalloc/chromium/src/memory_region_map.cc
new file mode 100644
index 00000000000..d7338f2a64c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/memory_region_map.cc
@@ -0,0 +1,816 @@
+/* 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 <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#elif !defined(MAP_FAILED)
+#define MAP_FAILED -1 // the only thing we need from mman.h
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h> // for pthread_t, pthread_self()
+#endif
+#include <stddef.h>
+
+#include <algorithm>
+#include <set>
+
+#include "memory_region_map.h"
+
+#include "base/logging.h"
+#include "base/low_level_alloc.h"
+#include "malloc_hook-inl.h"
+
+#include <gperftools/stacktrace.h>
+#include <gperftools/malloc_hook.h>
+
+// 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;
+static bool initializer = (libpthread_initialized = true, 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<RegionSet*>(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<HeapProfileBucket**>(
+ 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<void*>(stack_top),
+ reinterpret_cast<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_addr));
+ const_cast<Region*>(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<uintptr_t>(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<unsigned int>(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<const void**>(
+ MyAllocator::Allocate(key_size));
+ recursive_insert = false;
+ std::copy(key, key + depth, key_copy);
+ recursive_insert = true;
+ bucket = static_cast<HeapProfileBucket*>(
+ 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<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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<void*>(region.start_addr),
+ reinterpret_cast<void*>(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<unsigned int>(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<const void**>(
+ MyAllocator::Allocate(key_size));
+ std::copy(bucket.stack, bucket.stack + bucket.depth, key_copy);
+ HeapProfileBucket* new_bucket = static_cast<HeapProfileBucket*>(
+ 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<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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':
+ const int depth =
+ max_stack_depth_ > 0
+ ? MallocHook::GetCallerStackTrace(const_cast<void**>(region.call_stack),
+ max_stack_depth_, kStripFrames + 1)
+ : 0;
+ region.set_call_stack_depth(depth); // record stack info fully
+ RAW_VLOG(10, "New global region %p..%p from %p",
+ reinterpret_cast<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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<uintptr_t>(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<void*>(start_addr),
+ reinterpret_cast<void*>(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<uintptr_t>(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 %" PRIuS " regions",
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(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<void*>(region->start_addr),
+ reinterpret_cast<void*>(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<void*>(region->start_addr),
+ reinterpret_cast<void*>(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<void*>(region->start_addr),
+ reinterpret_cast<void*>(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&>(*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<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_addr));
+ RecordRegionRemovalInBucket(region->call_stack_depth, region->call_stack,
+ end_addr - region->start_addr);
+ const_cast<Region&>(*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<void*>(region->start_addr),
+ reinterpret_cast<void*>(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 %" PRIuS " regions",
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(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%"PRIxS" 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 %" PRIuS " at %" PRIu64 " "
+ "prot %d flags %d fd %d offs %" PRId64,
+ reinterpret_cast<uintptr_t>(result), size,
+ reinterpret_cast<uint64>(start), prot, flags, fd,
+ static_cast<int64>(offset));
+ if (result != reinterpret_cast<void*>(MAP_FAILED) && size != 0) {
+ RecordRegionAddition(result, size);
+ }
+}
+
+void MemoryRegionMap::MunmapHook(const void* ptr, size_t size) {
+ RAW_VLOG(10, "MUnmap of %p %" PRIuS, 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 " %" PRIuS " "
+ "to %" PRIuS " 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<void*>(-1)) {
+ RecordRegionRemoval(old_addr, old_size);
+ RecordRegionAddition(result, new_size);
+ }
+}
+
+extern "C" void* __sbrk(ptrdiff_t increment); // defined in libc
+
+void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) {
+ RAW_VLOG(10, "Sbrk = 0x%" PRIxPTR " of %" PRIdS,
+ (uintptr_t)result, increment);
+ if (result != reinterpret_cast<void*>(-1)) {
+ if (increment > 0) {
+ void* new_end = sbrk(0);
+ RecordRegionAddition(result, reinterpret_cast<uintptr_t>(new_end) -
+ reinterpret_cast<uintptr_t>(result));
+ } else if (increment < 0) {
+ void* new_end = sbrk(0);
+ RecordRegionRemoval(new_end, reinterpret_cast<uintptr_t>(result) -
+ reinterpret_cast<uintptr_t>(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/chromium/third_party/tcmalloc/chromium/src/memory_region_map.h b/chromium/third_party/tcmalloc/chromium/src/memory_region_map.h
new file mode 100644
index 00000000000..71876800c55
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/memory_region_map.h
@@ -0,0 +1,415 @@
+/* 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 <config.h>
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <stddef.h>
+#include <set>
+#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<uintptr_t>(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<uintptr_t>(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<class Type>
+ 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<void*>(p));
+ }
+ };
+
+ // Set of the memory regions
+ typedef std::set<Region, RegionCmp,
+ STL_Allocator<Region, MyAllocator> > 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 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 <class Type>
+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/chromium/third_party/tcmalloc/chromium/src/packed-cache-inl.h b/chromium/third_party/tcmalloc/chromium/src/packed-cache-inl.h
new file mode 100644
index 00000000000..36a24a338ae
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/packed-cache-inl.h
@@ -0,0 +1,240 @@
+// 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 <key, value> 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 <key, value> 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<K, V>(key, value); }
+// V GetOrDefault(K key, V default) { const pair<K, V> &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 <key, value> pair with that key
+// has ever been Put. However, a newly initialized cache will have
+// some <key, value> 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 <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#include "base/basictypes.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<IntType>(1) << ((N)-1))-1 + \
+ (static_cast<IntType>(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 T. See also the big comment at the top of the file.
+template <int kKeybits, typename T>
+class PackedCache {
+ public:
+ typedef uintptr_t K;
+ typedef size_t V;
+#ifdef TCMALLOC_SMALL_BUT_SLOW
+ // Decrease the size map cache if running in the small memory mode.
+ static const int kHashbits = 12;
+#else
+ // We don't want the hash map to occupy 512K memory at Chromium, so
+ // kHashbits is decreased from 16 to 12.
+ static const int kHashbits = 12;
+#endif
+ static const int kValuebits = 7;
+ static const bool kUseWholeKeys = kKeybits + kValuebits <= 8 * sizeof(T);
+
+ explicit PackedCache(V initial_value) {
+ COMPILE_ASSERT(kKeybits <= sizeof(K) * 8, key_size);
+ COMPILE_ASSERT(kValuebits <= sizeof(V) * 8, value_size);
+ COMPILE_ASSERT(kHashbits <= kKeybits, hash_function);
+ COMPILE_ASSERT(kKeybits - kHashbits + kValuebits <= kTbits,
+ entry_size_must_be_big_enough);
+ Clear(initial_value);
+ }
+
+ void Put(K key, V value) {
+ ASSERT(key == (key & kKeyMask));
+ ASSERT(value == (value & kValueMask));
+ array_[Hash(key)] = KeyToUpper(key) | value;
+ }
+
+ bool Has(K key) const {
+ ASSERT(key == (key & kKeyMask));
+ return KeyMatch(array_[Hash(key)], key);
+ }
+
+ V GetOrDefault(K key, V default_value) const {
+ // As with other code in this class, we touch array_ as few times
+ // as we can. Assuming entries are read atomically (e.g., their
+ // type is uintptr_t on most hardware) then certain races are
+ // harmless.
+ ASSERT(key == (key & kKeyMask));
+ T entry = array_[Hash(key)];
+ return KeyMatch(entry, key) ? EntryToValue(entry) : default_value;
+ }
+
+ void Clear(V value) {
+ ASSERT(value == (value & kValueMask));
+ for (int i = 0; i < 1 << kHashbits; i++) {
+ ASSERT(kUseWholeKeys || KeyToUpper(i) == 0);
+ array_[i] = kUseWholeKeys ? (value | KeyToUpper(i)) : value;
+ }
+ }
+
+ private:
+ // We are going to pack a value and the upper part of a key (or a
+ // whole key) into an entry of type T. The UPPER type is for the
+ // upper part of a key, after the key has been masked and shifted
+ // for inclusion in an entry.
+ typedef T UPPER;
+
+ static V EntryToValue(T t) { return t & kValueMask; }
+
+ // If we have space for a whole key, we just shift it left.
+ // Otherwise kHashbits determines where in a K to find the upper
+ // part of the key, and kValuebits determines where in the entry to
+ // put it.
+ static UPPER KeyToUpper(K k) {
+ if (kUseWholeKeys) {
+ return static_cast<T>(k) << kValuebits;
+ } else {
+ const int shift = kHashbits - kValuebits;
+ // Assume kHashbits >= kValuebits. It'd be easy to lift this assumption.
+ return static_cast<T>(k >> shift) & kUpperMask;
+ }
+ }
+
+ static size_t Hash(K key) {
+ return static_cast<size_t>(key) & N_ONES_(size_t, kHashbits);
+ }
+
+ // Does the entry match the relevant part of the given key?
+ static bool KeyMatch(T entry, K key) {
+ return kUseWholeKeys ?
+ (entry >> kValuebits == key) :
+ ((KeyToUpper(key) ^ entry) & kUpperMask) == 0;
+ }
+
+ static const int kTbits = 8 * sizeof(T);
+ static const int kUpperbits = kUseWholeKeys ? kKeybits : kKeybits - kHashbits;
+
+ // For masking a K.
+ static const K kKeyMask = N_ONES_(K, kKeybits);
+
+ // For masking a T.
+ static const T kUpperMask = N_ONES_(T, kUpperbits) << kValuebits;
+
+ // 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/chromium/third_party/tcmalloc/chromium/src/page_heap.cc b/chromium/third_party/tcmalloc/chromium/src/page_heap.cc
new file mode 100644
index 00000000000..402dc1f9e8a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/page_heap.cc
@@ -0,0 +1,546 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // for PRIuPTR
+#endif
+#include <gperftools/malloc_extension.h> // 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]");
+
+namespace tcmalloc {
+
+PageHeap::PageHeap()
+ : pagemap_(MetaDataAlloc),
+ pagemap_cache_(0),
+ scavenge_counter_(0),
+ // Start scavenging at kMaxPages list
+ release_index_(kMaxPages) {
+ COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
+ DLL_Init(&large_.normal);
+ DLL_Init(&large_.returned);
+ 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].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].returned;
+ 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
+}
+
+Span* PageHeap::New(Length n) {
+ ASSERT(Check());
+ ASSERT(n > 0);
+
+ Span* 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());
+ return NULL;
+ }
+ return SearchFreeAndLargeLists(n);
+}
+
+Span* PageHeap::AllocLarge(Length n) {
+ // find the best span (closest to n in size).
+ // The following loops implements address-ordered best-fit.
+ Span *best = NULL;
+
+ // Search through normal list
+ for (Span* span = large_.normal.next;
+ span != &large_.normal;
+ span = span->next) {
+ if (span->length >= n) {
+ if ((best == NULL)
+ || (span->length < best->length)
+ || ((span->length == best->length) && (span->start < best->start))) {
+ best = span;
+ ASSERT(best->location == Span::ON_NORMAL_FREELIST);
+ }
+ }
+ }
+
+ // Search through released list in case it has a better fit
+ for (Span* span = large_.returned.next;
+ span != &large_.returned;
+ span = span->next) {
+ if (span->length >= n) {
+ if ((best == NULL)
+ || (span->length < best->length)
+ || ((span->length == best->length) && (span->start < best->start))) {
+ best = span;
+ ASSERT(best->location == Span::ON_RETURNED_FREELIST);
+ }
+ }
+ }
+
+ return best == NULL ? NULL : Carve(best, n);
+}
+
+Span* PageHeap::Split(Span* span, Length n) {
+ ASSERT(0 < n);
+ ASSERT(n < span->length);
+ ASSERT(span->location == Span::IN_USE);
+ ASSERT(span->sizeclass == 0);
+ Event(span, 'T', n);
+
+ const int extra = span->length - n;
+ Span* leftover = NewSpan(span->start + n, extra);
+ ASSERT(leftover->location == Span::IN_USE);
+ Event(leftover, 'U', extra);
+ 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) {
+ TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift),
+ static_cast<size_t>(span->length << kPageShift));
+ stats_.committed_bytes += span->length << kPageShift;
+}
+
+void PageHeap::DecommitSpan(Span* span) {
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(span->start << kPageShift),
+ static_cast<size_t>(span->length << kPageShift));
+ stats_.committed_bytes -= span->length << kPageShift;
+}
+
+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;
+ Event(span, 'A', n);
+
+ const int extra = span->length - n;
+ ASSERT(extra >= 0);
+ if (extra > 0) {
+ Span* leftover = NewSpan(span->start + n, extra);
+ leftover->location = old_location;
+ Event(leftover, 'S', extra);
+ 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|.
+ 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);
+
+ 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;
+ Event(span, 'D', span->length);
+ MergeIntoFreeList(span); // Coalesces if possible
+ IncrementalScavenge(n);
+ ASSERT(stats_.unmapped_bytes+ stats_.committed_bytes==stats_.system_bytes);
+ ASSERT(Check());
+}
+
+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 that the adjacent spans we merge into "span" may come out of a
+ // "normal" (committed) list, and cleanly merge with our IN_USE span, which
+ // is implicitly committed. If the adjacents spans are on the "returned"
+ // (decommitted) list, then we must get both spans into the same state before
+ // or after we coalesce them. The current code always decomits. This is
+ // achieved by blindly decommitting the entire coalesced region, which may
+ // include any combination of committed and decommitted spans, at the end of
+ // the method.
+
+ // 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;
+ Span* prev = GetDescriptor(p-1);
+ if (prev != NULL && prev->location != Span::IN_USE) {
+ // Merge preceding span into this span
+ ASSERT(prev->start + prev->length == p);
+ const Length len = prev->length;
+ if (prev->location == Span::ON_RETURNED_FREELIST) {
+ // We're about to put the merge span into the returned freelist and call
+ // DecommitSpan() on it, which will mark the entire span including this
+ // one as released and decrease stats_.committed_bytes by the size of the
+ // merged span. To make the math work out we temporarily increase the
+ // stats_.committed_bytes amount.
+ stats_.committed_bytes += prev->length << kPageShift;
+ }
+ RemoveFromFreeList(prev);
+ DeleteSpan(prev);
+ span->start -= len;
+ span->length += len;
+ pagemap_.set(span->start, span);
+ Event(span, 'L', len);
+ }
+ Span* next = GetDescriptor(p+n);
+ if (next != NULL && next->location != Span::IN_USE) {
+ // Merge next span into this span
+ ASSERT(next->start == p+n);
+ const Length len = next->length;
+ if (next->location == Span::ON_RETURNED_FREELIST) {
+ // See the comment below 'if (prev->location ...' for explanation.
+ stats_.committed_bytes += next->length << kPageShift;
+ }
+ RemoveFromFreeList(next);
+ DeleteSpan(next);
+ span->length += len;
+ pagemap_.set(span->start + span->length - 1, span);
+ Event(span, 'R', len);
+ }
+
+ Event(span, 'D', span->length);
+ span->location = Span::ON_RETURNED_FREELIST;
+ DecommitSpan(span);
+ PrependToFreeList(span);
+}
+
+void PageHeap::PrependToFreeList(Span* span) {
+ ASSERT(span->location != Span::IN_USE);
+ SpanList* list = (span->length < kMaxPages) ? &free_[span->length] : &large_;
+ if (span->location == Span::ON_NORMAL_FREELIST) {
+ stats_.free_bytes += (span->length << kPageShift);
+ DLL_Prepend(&list->normal, span);
+ } else {
+ stats_.unmapped_bytes += (span->length << kPageShift);
+ 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);
+ }
+ 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;
+ }
+
+ 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<double>(released_pages);
+ if (wait > kMaxReleaseDelay) {
+ // Avoid overflow and bound to reasonable range.
+ wait = kMaxReleaseDelay;
+ }
+ scavenge_counter_ = static_cast<int64_t>(wait);
+ }
+}
+
+Length PageHeap::ReleaseLastNormalSpan(SpanList* slist) {
+ Span* s = slist->normal.prev;
+ ASSERT(s->location == Span::ON_NORMAL_FREELIST);
+ RemoveFromFreeList(s);
+ const Length n = s->length;
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
+ static_cast<size_t>(s->length << kPageShift));
+ s->location = Span::ON_RETURNED_FREELIST;
+ MergeIntoFreeList(s); // Coalesces if possible.
+ return n;
+}
+
+Length PageHeap::ReleaseAtLeastNPages(Length num_pages) {
+ Length released_pages = 0;
+ Length prev_released_pages = -1;
+
+ // Round robin through the lists of free spans, releasing the last
+ // span in each list. Stop after releasing at least num_pages.
+ while (released_pages < num_pages) {
+ if (released_pages == prev_released_pages) {
+ // Last iteration of while loop made no progress.
+ break;
+ }
+ prev_released_pages = released_pages;
+
+ for (int i = 0; i < kMaxPages+1 && released_pages < num_pages;
+ i++, release_index_++) {
+ if (release_index_ > kMaxPages) release_index_ = 0;
+ SpanList* slist = (release_index_ == kMaxPages) ?
+ &large_ : &free_[release_index_];
+ if (!DLL_IsEmpty(&slist->normal)) {
+ Length released_len = ReleaseLastNormalSpan(slist);
+ released_pages += released_len;
+ }
+ }
+ }
+ return released_pages;
+}
+
+void PageHeap::RegisterSizeClass(Span* span, size_t 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);
+ Event(span, 'C', sc);
+ 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 s = 0; s < kMaxPages; s++) {
+ result->normal_length[s] = DLL_Length(&free_[s].normal);
+ result->returned_length[s] = DLL_Length(&free_[s].returned);
+ }
+}
+
+void PageHeap::GetLargeSpanStats(LargeSpanStats* result) {
+ result->spans = 0;
+ result->normal_pages = 0;
+ result->returned_pages = 0;
+ for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
+ result->normal_pages += s->length;;
+ result->spans++;
+ }
+ for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
+ result->returned_pages += s->length;
+ result->spans++;
+ }
+}
+
+bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) {
+ Span* span = reinterpret_cast<Span*>(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<void*>(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<Length>(kMinSystemAlloc);
+ size_t actual_size;
+ void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
+ if (ptr == NULL) {
+ if (n < ask) {
+ // Try growing just "n" pages
+ ask = n;
+ ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
+ }
+ if (ptr == NULL) return false;
+ }
+ ask = actual_size >> kPageShift;
+ RecordGrowth(ask << kPageShift);
+
+ uint64_t old_system_bytes = stats_.system_bytes;
+ stats_.system_bytes += (ask << kPageShift);
+ stats_.committed_bytes += (ask << kPageShift);
+ const PageID p = reinterpret_cast<uintptr_t>(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() {
+ ASSERT(free_[0].normal.next == &free_[0].normal);
+ ASSERT(free_[0].returned.next == &free_[0].returned);
+ return true;
+}
+
+bool PageHeap::CheckExpensive() {
+ bool result = Check();
+ CheckList(&large_.normal, kMaxPages, 1000000000, Span::ON_NORMAL_FREELIST);
+ CheckList(&large_.returned, kMaxPages, 1000000000, Span::ON_RETURNED_FREELIST);
+ for (Length s = 1; s < kMaxPages; s++) {
+ CheckList(&free_[s].normal, s, s, Span::ON_NORMAL_FREELIST);
+ CheckList(&free_[s].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;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/page_heap.h b/chromium/third_party/tcmalloc/chromium/src/page_heap.h
new file mode 100644
index 00000000000..9376a66746f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/page_heap.h
@@ -0,0 +1,311 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_PAGE_HEAP_H_
+#define TCMALLOC_PAGE_HEAP_H_
+
+#include <config.h>
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint64_t, int64_t, uint16_t
+#endif
+#include <gperftools/malloc_extension.h>
+#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 <gperftools/stacktrace.h>
+#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.
+// ...except...
+// On Windows, we use TCMalloc_PageMap1_LazyCommit<> for 32-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 <int BITS> class MapSelector {
+ public:
+ typedef TCMalloc_PageMap3<BITS-kPageShift> Type;
+ typedef PackedCache<BITS-kPageShift, uint64_t> CacheType;
+};
+
+// A two-level map for 32-bit machines
+template <> class MapSelector<32> {
+ public:
+#ifdef WIN32
+// A flat map for 32-bit machines (with lazy commit of memory).
+ typedef TCMalloc_PageMap1_LazyCommit<32-kPageShift> Type;
+#else
+ // A two-level map for 32-bit machines
+ typedef TCMalloc_PageMap2<32-kPageShift> Type;
+#endif
+ typedef PackedCache<32-kPageShift, uint16_t> CacheType;
+};
+
+// -------------------------------------------------------------------------
+// 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, size_t 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 Span* GetDescriptor(PageID p) const {
+ return reinterpret_cast<Span*>(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) {}
+ 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_.
+
+ };
+ 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.
+ 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
+
+ // 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);
+
+ // Return 0 if we have no information, or else the correct sizeclass for p.
+ // Reads and writes to pagemap_cache_ do not require locking.
+ // The entries are 64 bits on 64-bit hardware and 16 bits on
+ // 32-bit hardware, and we don't mind raciness as long as each read of
+ // an entry yields a valid entry, not a partially updated entry.
+ size_t GetSizeClassIfCached(PageID p) const {
+ return pagemap_cache_.GetOrDefault(p, 0);
+ }
+ void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); }
+
+ 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.
+ // Chrome: Changed to 64MB
+ static const int kMaxReleaseDelay = 1 << 14;
+
+ // If there is nothing to release, wait for so many pages before
+ // scavenging again. With 4K pages, this comes to 1GB of memory.
+ // Chrome: Changed to 16MB
+ static const int kDefaultReleaseDelay = 1 << 12;
+
+ // Pick the appropriate map and cache types based on pointer size
+ typedef MapSelector<kAddressBits>::Type PageMap;
+ typedef MapSelector<kAddressBits>::CacheType PageMapCache;
+ PageMap pagemap_;
+ mutable PageMapCache pagemap_cache_;
+
+ // 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;
+ };
+
+ // List of free spans of length >= kMaxPages
+ SpanList large_;
+
+ // Array mapping from span length to a doubly linked list of free spans
+ 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.
+ void 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);
+
+ // Release the last span on the normal portion of this list.
+ // Return the length of that span.
+ Length ReleaseLastNormalSpan(SpanList* slist);
+
+
+ // 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_;
+};
+
+} // namespace tcmalloc
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // TCMALLOC_PAGE_HEAP_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/page_heap_allocator.h b/chromium/third_party/tcmalloc/chromium/src/page_heap_allocator.h
new file mode 100644
index 00000000000..3595b951923
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/page_heap_allocator.h
@@ -0,0 +1,127 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
+#define TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
+
+#include <stddef.h> // for NULL, size_t
+
+#include "common.h" // for MetaDataAlloc
+#include "free_list.h" // for FL_Push/FL_Pop
+#include "internal_logging.h" // for ASSERT
+#include "system-alloc.h" // for TCMalloc_SystemAddGuard
+
+namespace tcmalloc {
+
+// Simple allocator for objects of a specified type. External locking
+// is required before accessing one of these objects.
+template <class T>
+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 = FL_Pop(&free_list_);
+ } else {
+ if (free_avail_ < sizeof(T)) {
+ // Need more room. We assume that MetaDataAlloc returns
+ // suitably aligned memory.
+ free_area_ = reinterpret_cast<char*>(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));
+ }
+
+ // This guard page protects the metadata from being corrupted by a
+ // buffer overrun. We currently have no mechanism for freeing it, since
+ // we never release the metadata buffer. If that changes we'll need to
+ // add something like TCMalloc_SystemRemoveGuard.
+ size_t guard_size = TCMalloc_SystemAddGuard(free_area_,
+ kAllocIncrement);
+ free_area_ += guard_size;
+ free_avail_ = kAllocIncrement - guard_size;
+ if (free_avail_ < sizeof(T)) {
+ Log(kCrash, __FILE__, __LINE__,
+ "FATAL ERROR: Insufficient memory to guard internal tcmalloc "
+ "data (%d bytes, object-size %d, guard-size %d)\n",
+ kAllocIncrement, static_cast<int>(sizeof(T)), guard_size);
+ }
+ }
+ result = free_area_;
+ free_area_ += sizeof(T);
+ free_avail_ -= sizeof(T);
+ }
+ inuse_++;
+ return reinterpret_cast<T*>(result);
+ }
+
+ void Delete(T* p) {
+ FL_Push(&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_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/pagemap.h b/chromium/third_party/tcmalloc/chromium/src/pagemap.h
new file mode 100644
index 00000000000..018619740e8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/pagemap.h
@@ -0,0 +1,526 @@
+// 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 <opensource@google.com>
+//
+// 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 <stddef.h> // for NULL, size_t
+#include <string.h> // for memset
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#ifdef WIN32
+// TODO(jar): This is not needed when TCMalloc_PageMap1_LazyCommit has an API
+// supporting commit and reservation of memory.
+#include "common.h"
+#endif
+
+#include "internal_logging.h" // for ASSERT
+
+// Single-level array
+template <int BITS>
+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<void**>((*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.
+ 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;
+ }
+};
+
+#ifdef WIN32
+// Lazy commit, single-level array.
+// Very similar to PageMap1, except the page map is only committed as needed.
+// Since we don't return memory to the OS, the committed portion of the map will
+// only grow, and we'll only be called to Ensure when we really grow the heap.
+// We maintain a bit map to help us deduce if we've already committed a range
+// in our map.
+template <int BITS>
+class TCMalloc_PageMap1_LazyCommit {
+ private:
+ // Dimension of our page map array_.
+ static const int LENGTH = 1 << BITS;
+
+ // The page map array that sits in reserved virtual space. Pages of this
+ // array are committed as they are needed. For each page of virtual memory,
+ // we potentially have a pointer to a span instance.
+ void** array_;
+
+ // A bit vector that allows us to deduce what pages in array_ are committed.
+ // Note that 2^3 = 8 bits per char, and hence the use of the magical "3" in
+ // the array range gives us the effective "divide by 8".
+ char committed_[sizeof(void*) << (BITS - kPageShift - 3)];
+
+ // Given an |index| into |array_|, find the page number in |array_| that holds
+ // that element.
+ size_t ContainingPage(size_t index) const {
+ return (index * sizeof(*array_)) >> kPageShift;
+ }
+
+ // Find out if the given page_num index in array_ is in committed memory.
+ bool IsCommitted(size_t page_num) const {
+ return committed_[page_num >> 3] & (1 << (page_num & 0x7));
+ }
+
+ // Remember that the given page_num index in array_ is in committed memory.
+ void SetCommitted(size_t page_num) {
+ committed_[page_num >> 3] |= (1 << (page_num & 0x7));
+ }
+
+ public:
+ typedef uintptr_t Number;
+
+ explicit TCMalloc_PageMap1_LazyCommit(void* (*allocator)(size_t)) {
+ // TODO(jar): We need a reservation function, but current API to this class
+ // only provides an allocator.
+ // Get decommitted memory. We will commit as necessary.
+ size_t size = sizeof(*array_) << BITS;
+ array_ = reinterpret_cast<void**>(VirtualAlloc(
+ NULL, size, MEM_RESERVE, PAGE_READWRITE));
+ tcmalloc::update_metadata_system_bytes(size);
+ tcmalloc::update_metadata_unmapped_bytes(size);
+
+ // Make sure we divided LENGTH evenly.
+ ASSERT(sizeof(committed_) * 8 == (LENGTH * sizeof(*array_)) >> kPageShift);
+ // Indicate that none of the pages of array_ have been committed yet.
+ memset(committed_, 0, sizeof(committed_));
+ }
+
+ // Ensure that the map contains initialized and committed entries in array_ to
+ // describe pages "x .. x+n-1".
+ // Returns true if successful, false if we could not ensure this.
+ // If we have to commit more memory in array_ (which also clears said memory),
+ // then we'll set some of the bits in committed_ to remember this fact.
+ // Only the bits of committed_ near end-points for calls to Ensure() are ever
+ // set, as the calls to Ensure() will never have overlapping ranges other than
+ // at their end-points.
+ //
+ // Example: Suppose the OS allocates memory in pages including 40...50, and
+ // later the OS allocates memory in pages 51...83. When the first allocation
+ // of 40...50 is observed, then Ensure of (39,51) will be called. The range
+ // shown in the arguments is extended so that tcmalloc can look to see if
+ // adjacent pages are part of a span that can be coaleced. Later, when pages
+ // 51...83 are allocated, Ensure() will be called with arguments (50,84),
+ // broadened again for the same reason.
+ //
+ // After the above, we would NEVER get a call such as Ensure(45,60), as that
+ // overlaps with the interior of prior ensured regions. We ONLY get an Ensure
+ // call when the OS has allocated memory, and since we NEVER give memory back
+ // to the OS, the OS can't possible allocate the same region to us twice, and
+ // can't induce an Ensure() on an interior of previous Ensure call.
+ //
+ // Also note that OS allocations are NOT guaranteed to be consecutive (there
+ // may be "holes" where code etc. uses the virtual addresses), or to appear in
+ // any order, such as lowest to highest, or vice versa (as other independent
+ // allocation systems in the process may be performing VirtualAllocations and
+ // VirtualFrees asynchronously.)
+ bool Ensure(Number x, size_t n) {
+ if (n > LENGTH - x)
+ return false; // We won't Ensure mapping for last pages in memory.
+ ASSERT(n > 0);
+
+ // For a given page number in memory, calculate what page in array_ needs to
+ // be memory resident. Note that we really only need a few bytes in array_
+ // for each page of virtual space we have to map, but we can only commit
+ // whole pages of array_. For instance, a 4K page of array_ has about 1k
+ // entries, and hence can map about 1K pages, or a total of about 4MB
+ // typically. As a result, it is possible that the first entry in array_,
+ // and the n'th entry in array_, will sit in the same page of array_.
+ size_t first_page = ContainingPage(x);
+ size_t last_page = ContainingPage(x + n - 1);
+
+ // Check at each boundary, to see if we need to commit at that end. Some
+ // other neighbor may have already forced us to commit at either or both
+ // boundaries.
+ if (IsCommitted(first_page)) {
+ if (first_page == last_page) return true;
+ ++first_page;
+ if (IsCommitted(first_page)) {
+ if (first_page == last_page) return true;
+ ++first_page;
+ }
+ }
+
+ if (IsCommitted(last_page)) {
+ if (first_page == last_page) return true;
+ --last_page;
+ if (IsCommitted(last_page)) {
+ if (first_page == last_page) return true;
+ --last_page;
+ }
+ }
+
+ ASSERT(!IsCommitted(last_page));
+ ASSERT(!IsCommitted(first_page));
+
+ void* start = reinterpret_cast<char*>(array_) + (first_page << kPageShift);
+ size_t length = (last_page - first_page + 1) << kPageShift;
+
+#ifndef NDEBUG
+ // Validate we are committing new sections, and hence we're not clearing any
+ // existing data.
+ MEMORY_BASIC_INFORMATION info = {0};
+ size_t result = VirtualQuery(start, &info, sizeof(info));
+ ASSERT(result);
+ ASSERT(0 == (info.State & MEM_COMMIT)); // It starts with uncommitted.
+ ASSERT(info.RegionSize >= length); // Entire length is uncommitted.
+#endif
+
+ TCMalloc_SystemCommit(start, length);
+ tcmalloc::update_metadata_unmapped_bytes(-length);
+
+#ifndef NDEBUG
+ result = VirtualQuery(start, &info, sizeof(info));
+ ASSERT(result);
+ ASSERT(0 != (info.State & MEM_COMMIT)); // Now it is committed.
+ ASSERT(info.RegionSize >= length); // Entire length is committed.
+#endif
+
+ // As noted in the large comment/example describing this method, we will
+ // never be called with a range of pages very much inside this |first_page|
+ // to |last_page| range.
+ // As a result, we only need to set bits for each end of that range, and one
+ // page inside each end.
+ SetCommitted(first_page);
+ if (first_page < last_page) {
+ SetCommitted(last_page);
+ SetCommitted(first_page + 1); // These may be duplicates now.
+ SetCommitted(last_page - 1);
+ }
+
+ return true;
+ }
+
+ // This is a premature call to get all the meta-memory allocated, so as to
+ // avoid virtual space fragmentation. Since we pre-reserved all memory, we
+ // don't need to do anything here (we won't fragment virtual space).
+ void PreallocateMoreMemory() {}
+
+ // Return the current value for KEY. Returns NULL if not yet set,
+ // or if k is out of range.
+ 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 for KEY.
+ 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;
+ }
+};
+#endif // WIN32
+
+
+// Two-level radix tree
+template <int BITS>
+class TCMalloc_PageMap2 {
+ private:
+ // Put 32 entries in the root and (2^BITS)/32 entries in each leaf.
+ static const int ROOT_BITS = 5;
+ static const int ROOT_LENGTH = 1 << ROOT_BITS;
+
+ static const int LEAF_BITS = BITS - ROOT_BITS;
+ static const int LEAF_LENGTH = 1 << LEAF_BITS;
+
+ // Leaf node
+ struct Leaf {
+ void* values[LEAF_LENGTH];
+ };
+
+ Leaf* root_[ROOT_LENGTH]; // Pointers to 32 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_));
+ }
+
+ 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) {
+ ASSERT(k >> BITS == 0);
+ const Number i1 = k >> LEAF_BITS;
+ const Number i2 = k & (LEAF_LENGTH-1);
+ 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<Leaf*>((*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
+ Ensure(0, 1 << BITS);
+ }
+
+ void* Next(Number k) const {
+ while (k < (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 <int BITS>
+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<Node*>((*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;
+ root_ = NewNode();
+ }
+
+ 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<Leaf*>(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<Leaf*>(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<Leaf*>((*allocator_)(sizeof(Leaf)));
+ if (leaf == NULL) return false;
+ memset(leaf, 0, sizeof(*leaf));
+ root_->ptrs[i1]->ptrs[i2] = reinterpret_cast<Node*>(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<Leaf*>(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/chromium/third_party/tcmalloc/chromium/src/pprof b/chromium/third_party/tcmalloc/chromium/src/pprof
new file mode 100755
index 00000000000..727eb43704f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/pprof
@@ -0,0 +1,5348 @@
+#! /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:
+# <count> <stack trace>
+# 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=<regexp> 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=<regexp> 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;
+
+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;
+
+##### Argument parsing #####
+
+sub usage_string {
+ return <<EOF;
+Usage:
+pprof [options] <program> <profiles>
+ <profiles> is a space separated list of profile names.
+pprof [options] <symbolized-profiles>
+ <symbolized-profiles> is a list of profile files where each file contains
+ the necessary symbol mappings as well as profile data (likely generated
+ with --raw).
+pprof [options] <profile>
+ <profile> 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[/<service>] - a location of a service to get profile from
+
+ The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
+ $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
+ $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
+ For instance:
+ pprof http://myserver.com:80$HEAP_PAGE
+ If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
+pprof --symbols <program>
+ 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=<base> Subtract <base> from <profile> before display
+ --interactive Run in interactive mode (interactive "help" gives help) [default]
+ --seconds=<n> Length of time for dynamic profiles [default=30 secs]
+ --add_lib=<file> Read additional symbols and line info from the given library
+ --lib_prefix=<dir> Comma separated list of library path prefixes
+
+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
+ --callgrind Generate callgrind format to stdout
+ --gv Generate Postscript and display
+ --evince Generate PDF and display
+ --web Generate SVG and display
+ --list=<regexp> Generate source listing of matching routines
+ --disasm=<regexp> Generate disassembly of matching routines
+ --symbols Print demangled symbol names found at given addresses
+ --dot Generate DOT file to stdout
+ --ps Generate Postcript 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)
+
+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=<n> Show at most so many nodes [default=80]
+ --nodefraction=<f> Hide nodes below <f>*total [default=.005]
+ --edgefraction=<f> Hide edges below <f>*total [default=.001]
+ --maxdegree=<n> Max incoming/outgoing edges per node [default=8]
+ --focus=<regexp> Focus on nodes matching <regexp>
+ --ignore=<regexp> Ignore nodes matching <regexp>
+ --scale=<n> Set GV scaling [default=0]
+ --heapcheck Make nodes with non-0 object counts
+ (i.e. direct leak generators) more visible
+
+Miscellaneous:
+ --tools=<prefix or binary:fullpath>[,...] \$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:
+
+pprof /bin/ls ls.prof
+ Enters "interactive" mode
+pprof --text /bin/ls ls.prof
+ Outputs one line per procedure
+pprof --web /bin/ls ls.prof
+ Displays annotated call-graph in web browser
+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 http://localhost:1234/
+ Enters "interactive" mode
+pprof --text localhost:1234
+ Outputs one line per procedure for localhost:1234
+pprof --raw localhost:1234 > ./local.raw
+pprof --text ./local.raw
+ Fetches a remote profile for later analysis and then
+ analyzes it in text mode.
+EOF
+}
+
+sub version_string {
+ return <<EOF
+pprof (part of gperftools $PPROF_VERSION)
+
+Copyright 1998-2007 Google Inc.
+
+This is BSD licensed software; see the source for copying conditions
+and license information.
+There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.
+EOF
+}
+
+sub usage {
+ my $msg = shift;
+ print STDERR "$msg\n\n";
+ print STDERR usage_string();
+ print STDERR "\nFATAL ERROR: $msg\n"; # just as a reminder
+ exit(1);
+}
+
+sub Init() {
+ # Setup tmp-file name and handler to clean it up.
+ # We do this in the very beginning so that we can use
+ # error() and cleanup() function anytime here after.
+ $main::tmpfile_sym = "/tmp/pprof$$.sym";
+ $main::tmpfile_ps = "/tmp/pprof$$";
+ $main::next_tmpfile = 0;
+ $SIG{'INT'} = \&sighandler;
+
+ # Cache from filename/linenumber to source code
+ $main::source_cache = ();
+
+ $main::opt_help = 0;
+ $main::opt_version = 0;
+
+ $main::opt_cum = 0;
+ $main::opt_base = '';
+ $main::opt_addresses = 0;
+ $main::opt_lines = 0;
+ $main::opt_functions = 0;
+ $main::opt_files = 0;
+ $main::opt_lib_prefix = "";
+
+ $main::opt_text = 0;
+ $main::opt_callgrind = 0;
+ $main::opt_list = "";
+ $main::opt_disasm = "";
+ $main::opt_symbols = 0;
+ $main::opt_gv = 0;
+ $main::opt_evince = 0;
+ $main::opt_web = 0;
+ $main::opt_dot = 0;
+ $main::opt_ps = 0;
+ $main::opt_pdf = 0;
+ $main::opt_gif = 0;
+ $main::opt_svg = 0;
+ $main::opt_raw = 0;
+
+ $main::opt_nodecount = 80;
+ $main::opt_nodefraction = 0.005;
+ $main::opt_edgefraction = 0.001;
+ $main::opt_maxdegree = 8;
+ $main::opt_focus = '';
+ $main::opt_ignore = '';
+ $main::opt_scale = 0;
+ $main::opt_heapcheck = 0;
+ $main::opt_seconds = 30;
+ $main::opt_lib = "";
+
+ $main::opt_inuse_space = 0;
+ $main::opt_inuse_objects = 0;
+ $main::opt_alloc_space = 0;
+ $main::opt_alloc_objects = 0;
+ $main::opt_show_bytes = 0;
+ $main::opt_drop_negative = 0;
+ $main::opt_interactive = 0;
+
+ $main::opt_total_delay = 0;
+ $main::opt_contentions = 0;
+ $main::opt_mean_delay = 0;
+
+ $main::opt_tools = "";
+ $main::opt_debug = 0;
+ $main::opt_test = 0;
+
+ # These are undocumented flags used only by unittests.
+ $main::opt_test_stride = 0;
+
+ # Are we using $SYMBOL_PAGE?
+ $main::use_symbol_page = 0;
+
+ # Files returned by TempName.
+ %main::tempnames = ();
+
+ # Type of profile we are dealing with
+ # Supported types:
+ # cpu
+ # heap
+ # growth
+ # contention
+ $main::profile_type = ''; # Empty type means "unknown"
+
+ GetOptions("help!" => \$main::opt_help,
+ "version!" => \$main::opt_version,
+ "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,
+ "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,
+ "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,
+ "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_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])) {
+ $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());
+ }
+ PrintText($symbols, $flat, $cumulative, -1);
+ } elsif ($main::opt_raw) {
+ PrintSymbolizedProfile($symbols, $profile, $main::prog);
+ } 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;
+ }
+
+ # 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) ";
+ $_ = <STDIN>;
+ 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 <<ENDOFHELP;
+Interactive pprof mode
+
+Commands:
+ gv
+ gv [focus] [-ignore1] [-ignore2]
+ Show graphical hierarchical display of current profile. Without
+ any arguments, shows all samples in the profile. With the optional
+ "focus" argument, restricts the samples shown to just those where
+ the "focus" regular expression matches a routine name on the stack
+ trace.
+
+ web
+ web [focus] [-ignore1] [-ignore2]
+ Like GV, but displays profile in your web browser instead of using
+ Ghostview. Works best if your web browser is already running.
+ To change the browser that gets used:
+ On Linux, set the /etc/alternatives/gnome-www-browser symlink.
+ On OS X, change the Finder association for SVG files.
+
+ list [routine_regexp] [-ignore1] [-ignore2]
+ Show source listing of routines whose names match "routine_regexp"
+
+ weblist [routine_regexp] [-ignore1] [-ignore2]
+ Displays a source listing of routines whose names match "routine_regexp"
+ in a web browser. You can click on source lines to view the
+ corresponding disassembly.
+
+ top [--cum] [-ignore1] [-ignore2]
+ top20 [--cum] [-ignore1] [-ignore2]
+ top37 [--cum] [-ignore1] [-ignore2]
+ Show top lines ordered by flat profile count, or cumulative count
+ if --cum is specified. If a number is present after 'top', the
+ top K routines will be shown (defaults to showing the top 10)
+
+ disasm [routine_regexp] [-ignore1] [-ignore2]
+ Show disassembly of routines whose names match "routine_regexp",
+ annotated with sample counts.
+
+ callgrind
+ callgrind [filename]
+ Generates callgrind file. If no filename is given, kcachegrind is called.
+
+ help - This listing
+ quit or ^D - End pprof
+
+For commands that accept optional -ignore tags, samples where any routine in
+the stack trace matches the regular expression in any of the -ignore
+parameters will be ignored.
+
+Further pprof details are available at this location (or one similar):
+
+ /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html
+ /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html
+
+ENDOFHELP
+}
+sub ParseInteractiveArgs {
+ my $args = shift;
+ my $focus = "";
+ my $ignore = "";
+ my @x = split(/ +/, $args);
+ foreach $a (@x) {
+ if ($a =~ m/^(--|-)lines$/) {
+ $main::opt_lines = 1;
+ } elsif ($a =~ m/^(--|-)cum$/) {
+ $main::opt_cum = 1;
+ } elsif ($a =~ m/^-(.*)/) {
+ $ignore .= (($ignore ne "") ? "|" : "" ) . $1;
+ } else {
+ $focus .= (($focus ne "") ? "|" : "" ) . $a;
+ }
+ }
+ if ($ignore ne "") {
+ print STDERR "Ignoring samples in call stacks that match '$ignore'\n";
+ }
+ return ($focus, $ignore);
+}
+
+##### Output code #####
+
+sub TempName {
+ my $fnum = shift;
+ my $ext = shift;
+ my $file = "$main::tmpfile_ps.$fnum.$ext";
+ $main::tempnames{$file} = 1;
+ return $file;
+}
+
+# Print profile data in packed binary format (64-bit) to standard out
+sub PrintProfileData {
+ my $profile = shift;
+
+ # print header (64-bit style)
+ # (zero) (header-size) (version) (sample-period) (zero)
+ print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
+
+ foreach my $k (keys(%{$profile})) {
+ my $count = $profile->{$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.
+ 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
+ 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 (<SRC>) {
+ 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;
+
+ 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");
+ printf 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.
+ printf CG CompressedCGName("fl", $caller_file, \%filename_to_index_map);
+ printf CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map);
+ if (defined $6) {
+ printf CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map);
+ printf CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map);
+ printf CG ("calls=$count $callee_line\n");
+ }
+ printf 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 (<OBJDUMP>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ chop;
+ if (m|\s*([^:\s]+):(\d+)\s*$|) {
+ # Location line of the form:
+ # <filename>:<linenumber>
+ $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 ("<div class=\"legend\">%s<br>Total: %s %s</div>\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';
+<DOCTYPE html>
+<html>
+<head>
+<title>Pprof listing</title>
+<style type="text/css">
+body {
+ font-family: sans-serif;
+}
+h1 {
+ font-size: 1.5em;
+ margin-bottom: 4px;
+}
+.legend {
+ font-size: 1.25em;
+}
+.line {
+ color: #aaaaaa;
+}
+.nop {
+ color: #aaaaaa;
+}
+.unimportant {
+ color: #cccccc;
+}
+.disasmloc {
+ color: #000000;
+}
+.deadsrc {
+ cursor: pointer;
+}
+.deadsrc:hover {
+ background-color: #eeeeee;
+}
+.livesrc {
+ color: #0000ff;
+ cursor: pointer;
+}
+.livesrc:hover {
+ background-color: #eeeeee;
+}
+.asm {
+ color: #008800;
+ display: none;
+}
+</style>
+<script type="text/javascript">
+function pprof_toggle_asm(e) {
+ var target;
+ if (!e) e = window.event;
+ if (e.target) target = e.target;
+ else if (e.srcElement) target = e.srcElement;
+
+ if (target) {
+ var asm = target.nextSibling;
+ if (asm && asm.className == "asm") {
+ asm.style.display = (asm.style.display == "block" ? "" : "block");
+ e.preventDefault();
+ return false;
+ }
+ }
+}
+</script>
+</head>
+<body>
+EOF
+}
+
+sub HtmlListingFooter {
+ return <<'EOF';
+</body>
+</html>
+EOF
+}
+
+sub HtmlEscape {
+ my $text = shift;
+ $text =~ s/&/&amp;/g;
+ $text =~ s/</&lt;/g;
+ $text =~ s/>/&gt;/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 (<FILE>) {
+ 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("<span class=disasmloc>%s:%d</span>",
+ HtmlEscape(CleanFileName($f)), $l);
+ } elsif ($l ne $last_dis_linenum) {
+ # De-emphasize the unchanged file name portion
+ $dis .= sprintf("<span class=unimportant>%s</span>" .
+ "<span class=disasmloc>:%d</span>",
+ HtmlEscape(CleanFileName($f)), $l);
+ } else {
+ # De-emphasize the entire location
+ $dis .= sprintf("<span class=unimportant>%s:%d</span>",
+ 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 (
+ "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\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 (<FILE>) {
+ 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 = "<span class=\"asm\">" . $dis . "</span>";
+ }
+ my $source_class = (($n1 + $n2 > 0)
+ ? "livesrc"
+ : (($asm ne "") ? "deadsrc" : "nop"));
+ printf $output (
+ "<span class=\"line\">%5d</span> " .
+ "<span class=\"%s\">%6s %6s %s</span>%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 "</pre>\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 (<FILE>) {
+ 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 = <SVG>;
+ close(SVG);
+ unlink $svgfile;
+ my $svg = join('', @svg);
+
+ # Dot's SVG output is
+ #
+ # <svg width="___" height="___"
+ # viewBox="___" xmlns=...>
+ # <g id="graph0" transform="...">
+ # ...
+ # </g>
+ # </svg>
+ #
+ # Change it to
+ #
+ # <svg width="100%" height="100%"
+ # xmlns=...>
+ # $svg_javascript
+ # <g id="viewport" transform="translate(0,0)">
+ # <g id="graph0" transform="...">
+ # ...
+ # </g>
+ # </g>
+ # </svg>
+
+ # Fix width, height; drop viewBox.
+ $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/;
+
+ # Insert script, viewport <g> above first <g>
+ my $svg_javascript = SvgJavascript();
+ my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n";
+ $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/;
+
+ # Insert final </g> above </svg>.
+ $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/;
+ $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/;
+
+ if ($main::opt_svg) {
+ # --svg: write to standard output.
+ print $svg;
+ } else {
+ # Write back to temporary file.
+ open(SVG, ">$svgfile") || die "open $svgfile: $!";
+ print SVG $svg;
+ close(SVG);
+ }
+}
+
+sub SvgJavascript {
+ return <<'EOF';
+<script type="text/ecmascript"><![CDATA[
+// SVGPan
+// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/
+// Local modification: if(true || ...) below to force panning, never moving.
+
+/**
+ * SVGPan library 1.2
+ * ====================
+ *
+ * Given an unique existing element with id "viewport", including the
+ * the library into any SVG adds the following capabilities:
+ *
+ * - Mouse panning
+ * - Mouse zooming (using the wheel)
+ * - Object dargging
+ *
+ * Known issues:
+ *
+ * - Zooming (while panning) on Safari has still some issues
+ *
+ * Releases:
+ *
+ * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
+ * Fixed a bug with browser mouse handler interaction
+ *
+ * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
+ * Updated the zoom code to support the mouse wheel on Safari/Chrome
+ *
+ * 1.0, Andrea Leofreddi
+ * First release
+ *
+ * This code is licensed under the following BSD license:
+ *
+ * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``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 Andrea Leofreddi 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 views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of Andrea Leofreddi.
+ */
+
+var root = document.documentElement;
+
+var state = 'none', stateTarget, stateOrigin, stateTf;
+
+setupHandlers(root);
+
+/**
+ * Register handlers
+ */
+function setupHandlers(root){
+ setAttributes(root, {
+ "onmouseup" : "add(evt)",
+ "onmousedown" : "handleMouseDown(evt)",
+ "onmousemove" : "handleMouseMove(evt)",
+ "onmouseup" : "handleMouseUp(evt)",
+ //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
+ });
+
+ if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
+ window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
+ else
+ window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
+
+ var g = svgDoc.getElementById("svg");
+ g.width = "100%";
+ g.height = "100%";
+}
+
+/**
+ * Instance an SVGPoint object with given event coordinates.
+ */
+function getEventPoint(evt) {
+ var p = root.createSVGPoint();
+
+ p.x = evt.clientX;
+ p.y = evt.clientY;
+
+ return p;
+}
+
+/**
+ * Sets the current transform matrix of an element.
+ */
+function setCTM(element, matrix) {
+ var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
+
+ element.setAttribute("transform", s);
+}
+
+/**
+ * Dumps a matrix to a string (useful for debug).
+ */
+function dumpMatrix(matrix) {
+ var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
+
+ return s;
+}
+
+/**
+ * Sets attributes of an element.
+ */
+function setAttributes(element, attributes){
+ for (i in attributes)
+ element.setAttributeNS(null, i, attributes[i]);
+}
+
+/**
+ * Handle mouse move event.
+ */
+function handleMouseWheel(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var delta;
+
+ if(evt.wheelDelta)
+ delta = evt.wheelDelta / 3600; // Chrome/Safari
+ else
+ delta = evt.detail / -90; // Mozilla
+
+ var z = 1 + delta; // Zoom factor: 0.9/1.1
+
+ var g = svgDoc.getElementById("viewport");
+
+ var p = getEventPoint(evt);
+
+ p = p.matrixTransform(g.getCTM().inverse());
+
+ // Compute new scale matrix in current mouse position
+ var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
+
+ setCTM(g, g.getCTM().multiply(k));
+
+ stateTf = stateTf.multiply(k.inverse());
+}
+
+/**
+ * Handle mouse move event.
+ */
+function handleMouseMove(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var g = svgDoc.getElementById("viewport");
+
+ if(state == 'pan') {
+ // Pan mode
+ var p = getEventPoint(evt).matrixTransform(stateTf);
+
+ setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
+ } else if(state == 'move') {
+ // Move mode
+ var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
+
+ setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
+
+ stateOrigin = p;
+ }
+}
+
+/**
+ * Handle click event.
+ */
+function handleMouseDown(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var g = svgDoc.getElementById("viewport");
+
+ if(true || evt.target.tagName == "svg") {
+ // Pan mode
+ state = 'pan';
+
+ stateTf = g.getCTM().inverse();
+
+ stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
+ } else {
+ // Move mode
+ state = 'move';
+
+ stateTarget = evt.target;
+
+ stateTf = g.getCTM().inverse();
+
+ stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
+ }
+}
+
+/**
+ * Handle mouse button release event.
+ */
+function handleMouseUp(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ if(state == 'pan' || state == 'move') {
+ // Quit pan mode
+ state = '';
+ }
+}
+
+]]></script>
+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");
+ } else {
+ push(@result, "$func $fileline");
+ }
+ } elsif ($main::opt_functions) {
+ if ($func eq '??') {
+ push(@result, "$a");
+ } else {
+ push(@result, $func);
+ }
+ } 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 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 = "??: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 $destination = ExtractSymbolLocation($symbols, $address[0]);
+ AddEntry($calls, $destination, $count);
+ for (my $i = 1; $i <= $#address; $i++) {
+ my $source = ExtractSymbolLocation($symbols, $address[$i]);
+ my $call = "$source -> $destination";
+ AddEntry($calls, $call, $count);
+ $destination = $source;
+ }
+ }
+
+ return $calls;
+}
+
+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') {
+ # 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];
+ }
+ print STDERR "Removing $second_pc from all stack traces.\n";
+ foreach my $k (keys(%{$profile})) {
+ my $count = $profile->{$k};
+ my @addrs = split(/\n/, $k);
+ 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 = <SYMBOL>;
+ $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>;
+ $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 (<CMDLINE>) {
+ 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 = shift;
+ 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=<value>' 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 = <PROFILE>)) {
+ $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 * 4, 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] @ <heap-url>/266053
+ # There are two pairs <count: size>, 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] @ <heap-url>_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 (<PROFILE>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ if (/^MAPPED_LIBRARIES:/) {
+ # Read the /proc/self/maps data
+ while (<PROFILE>) {
+ 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 (<PROFILE>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ # Parse "build=<dir>" 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:
+ # <count1>: <bytes1> [<count2>: <bytes2>] @ 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);
+ AddEntries($profile, $pcs, FixCallerAddresses($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 = <PROFILE> ) {
+ $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";
+ }
+ 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 (<OBJDUMP>) {
+ 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 (<OTOOL>) {
+ $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 = 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+(\S+\.(so|dll|dylib|bundle)((\.\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;
+ } 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;
+
+ # 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("----\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 (<SYMBOLS>) {
+ # Read fullfunction and filelineinfo from next pair of lines
+ s/\r?\n$//g;
+ my $fullfunction = $_;
+ $_ = <SYMBOLS>;
+ 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
+
+ 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
+ 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
+ # <tool>:<path>. 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 " pprof \\\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 $symbol_table = {};
+ open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n");
+ my $last_start = "0";
+ my $routine = "";
+ while (<NM>) {
+ 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)];
+ }
+ return $symbol_table;
+}
+
+# Gets the procedure boundaries for all routines in "$image" whose names
+# match "$regexp" and returns them in a hashtable mapping from procedure
+# name to a two-element vector of [start address, end address].
+# Will return an empty map if nm is not installed or not working properly.
+sub GetProcedureBoundaries {
+ my $image = shift;
+ my $regexp = shift;
+
+ # If $image doesn't start with /, then put ./ in front of it. This works
+ # around an obnoxious bug in our probing of nm -f behavior.
+ # "nm -f $image" is supposed to fail on GNU nm, but if:
+ #
+ # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND
+ # b. you have a.out in your current directory (a not uncommon occurence)
+ #
+ # then "nm -f $image" succeeds because -f only looks at the first letter of
+ # the argument, which looks valid because it's [BbSsPp], and then since
+ # there's no image provided, it looks for a.out and finds it.
+ #
+ # This regex makes sure that $image starts with . or /, forcing the -f
+ # parsing to fail since . and / are not valid formats.
+ $image =~ s#^[^/]#./$&#;
+
+ # For libc libraries, the copy in /usr/lib/debug contains debugging symbols
+ my $debugging = DebuggingLibrary($image);
+ if ($debugging) {
+ $image = $debugging;
+ }
+
+ my $nm = $obj_tool_map{"nm"};
+ my $cppfilt = $obj_tool_map{"c++filt"};
+
+ # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
+ # binary doesn't support --demangle. In addition, for OS X we need
+ # to use the -f flag to get 'flat' nm output (otherwise we don't sort
+ # properly and get incorrect results). Unfortunately, GNU nm uses -f
+ # in an incompatible way. So first we test whether our nm supports
+ # --demangle and -f.
+ my $demangle_flag = "";
+ my $cppfilt_flag = "";
+ my $to_devnull = ">$dev_null 2>&1";
+ if (system(ShellEscape($nm, "--demangle", "image") . $to_devnull) == 0) {
+ # In this mode, we do "nm --demangle <foo>"
+ $demangle_flag = "--demangle";
+ $cppfilt_flag = "";
+ } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {
+ # In this mode, we do "nm <foo> | 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);
+ 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/chromium/third_party/tcmalloc/chromium/src/profile-handler.cc b/chromium/third_party/tcmalloc/chromium/src/profile-handler.cc
new file mode 100644
index 00000000000..20e5cca90cf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/profile-handler.cc
@@ -0,0 +1,555 @@
+// 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 <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <list>
+#include <string>
+
+#include "base/dynamic_annotations.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "maybe_threads.h"
+
+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;
+};
+
+// 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. On systems which
+ // have a separate interval timer for each thread, this function starts the
+ // timer for the current thread.
+ //
+ // The function also attempts to determine whether or not timers are shared by
+ // all threads in the process. (With LinuxThreads, and with NPTL on some
+ // Linux kernel versions, each thread has separate timers.)
+ //
+ // Prior to determining whether timers are shared, this function will
+ // unconditionally start the timer. However, if this function determines
+ // that timers are shared, then it will stop the timer if no callbacks are
+ // currently registered.
+ 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. Registration of the first callback enables the
+ // SIGPROF handler (or SIGALRM if using ITIMER_REAL).
+ ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback,
+ void* callback_arg);
+
+ // Unregisters a previously registered callback. Expects the token returned
+ // by the corresponding RegisterCallback routine. Unregistering the last
+ // callback disables the SIGPROF handler (or SIGALRM if using ITIMER_REAL).
+ void UnregisterCallback(ProfileHandlerToken* token)
+ NO_THREAD_SAFETY_ANALYSIS;
+
+ // Unregisters all the callbacks, stops the timer if shared, disables the
+ // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state.
+ 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();
+
+ // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received.
+ int64 interrupts_ GUARDED_BY(signal_lock_);
+
+ // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
+ int32 frequency_;
+
+ // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
+ int timer_type_;
+
+ // Counts the number of callbacks registered.
+ int32 callback_count_ GUARDED_BY(control_lock_);
+
+ // Is profiling allowed at all?
+ bool allowed_;
+
+ // Whether or not the threading system provides interval timers that are
+ // shared by all threads in a process.
+ enum {
+ // No timer initialization attempted yet.
+ TIMERS_UNTOUCHED,
+ // First thread has registered and set timer.
+ TIMERS_ONE_SET,
+ // Timers are shared by all threads.
+ TIMERS_SHARED,
+ // Timers are separate in each thread.
+ TIMERS_SEPARATE
+ } timer_sharing_ GUARDED_BY(control_lock_);
+
+ // 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<ProfileHandlerToken*> CallbackList;
+ typedef CallbackList::iterator CallbackIterator;
+ CallbackList callbacks_ GUARDED_BY(signal_lock_);
+
+ // Starts the interval timer. If the thread library shares timers between
+ // threads, this function starts the shared timer. Otherwise, this will start
+ // the timer in the current thread.
+ void StartTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Stops the interval timer. If the thread library shares timers between
+ // threads, this fucntion stops the shared timer. Otherwise, this will stop
+ // the timer in the current thread.
+ void StopTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Returns true if the profile interval timer is enabled in the current
+ // thread. This actually checks the kernel's interval timer setting. (It is
+ // used to detect whether timers are shared or separate.)
+ bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Sets the timer interrupt signal handler.
+ void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Disables (ignores) the timer interrupt signal.
+ void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Returns true if the handler is not being used by something else.
+ // This checks the kernel's signal handler table.
+ bool IsSignalHandlerAvailable();
+
+ // SIGPROF/SIGALRM handler. Iterate over and call 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
+// 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;
+
+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()
+ : interrupts_(0),
+ callback_count_(0),
+ allowed_(true),
+ timer_sharing_(TIMERS_UNTOUCHED) {
+ SpinLockHolder cl(&control_lock_);
+
+ timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
+
+ // 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 something else is using the signal handler,
+ // assume it has priority over us and stop.
+ if (!IsSignalHandlerAvailable()) {
+ RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.",
+ timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF");
+ allowed_ = false;
+ return;
+ }
+
+ // Ignore signals until we decide to turn profiling on. (Paranoia;
+ // should already be ignored.)
+ DisableHandler();
+}
+
+ProfileHandler::~ProfileHandler() {
+ Reset();
+}
+
+void ProfileHandler::RegisterThread() {
+ SpinLockHolder cl(&control_lock_);
+
+ if (!allowed_) {
+ return;
+ }
+
+ // We try to detect whether timers are being shared by setting a
+ // timer in the first call to this function, then checking whether
+ // it's set in the second call.
+ //
+ // Note that this detection method requires that the first two calls
+ // to RegisterThread must be made from different threads. (Subsequent
+ // calls will see timer_sharing_ set to either TIMERS_SEPARATE or
+ // TIMERS_SHARED, and won't try to detect the timer sharing type.)
+ //
+ // Also note that if timer settings were inherited across new thread
+ // creation but *not* shared, this approach wouldn't work. That's
+ // not an issue for any Linux threading implementation, and should
+ // not be a problem for a POSIX-compliant threads implementation.
+ switch (timer_sharing_) {
+ case TIMERS_UNTOUCHED:
+ StartTimer();
+ timer_sharing_ = TIMERS_ONE_SET;
+ break;
+ case TIMERS_ONE_SET:
+ // If the timer is running, that means that the main thread's
+ // timer setup is seen in this (second) thread -- and therefore
+ // that timers are shared.
+ if (IsTimerRunning()) {
+ timer_sharing_ = TIMERS_SHARED;
+ // If callback is already registered, we have to keep the timer
+ // running. If not, we disable the timer here.
+ if (callback_count_ == 0) {
+ StopTimer();
+ }
+ } else {
+ timer_sharing_ = TIMERS_SEPARATE;
+ StartTimer();
+ }
+ break;
+ case TIMERS_SHARED:
+ // Nothing needed.
+ break;
+ case TIMERS_SEPARATE:
+ StartTimer();
+ break;
+ }
+}
+
+ProfileHandlerToken* ProfileHandler::RegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+
+ ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
+
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ callbacks_.push_back(token);
+ }
+ // Start the timer if timer is shared and this is a first callback.
+ if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) {
+ StartTimer();
+ }
+ ++callback_count_;
+ EnableHandler();
+ 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");
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ delete *it;
+ callbacks_.erase(it);
+ }
+ --callback_count_;
+ if (callback_count_ > 0) {
+ EnableHandler();
+ } else if (timer_sharing_ == TIMERS_SHARED) {
+ StopTimer();
+ }
+ return;
+ }
+ }
+ // Unknown token.
+ RAW_LOG(FATAL, "Invalid token");
+}
+
+void ProfileHandler::Reset() {
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ CallbackIterator it = callbacks_.begin();
+ while (it != callbacks_.end()) {
+ CallbackIterator tmp = it;
+ ++it;
+ delete *tmp;
+ callbacks_.erase(tmp);
+ }
+ }
+ callback_count_ = 0;
+ if (timer_sharing_ == TIMERS_SHARED) {
+ StopTimer();
+ }
+ timer_sharing_ = TIMERS_UNTOUCHED;
+}
+
+void ProfileHandler::GetState(ProfileHandlerState* state) {
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_); // Protects interrupts_.
+ state->interrupts = interrupts_;
+ }
+ if (callback_count_ > 0) {
+ EnableHandler();
+ }
+ state->frequency = frequency_;
+ state->callback_count = callback_count_;
+ state->allowed = allowed_;
+}
+
+void ProfileHandler::StartTimer() {
+ if (!allowed_) {
+ return;
+ }
+ struct itimerval timer;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 1000000 / frequency_;
+ timer.it_value = timer.it_interval;
+ setitimer(timer_type_, &timer, 0);
+}
+
+void ProfileHandler::StopTimer() {
+ if (!allowed_) {
+ return;
+ }
+ struct itimerval timer;
+ memset(&timer, 0, sizeof timer);
+ setitimer(timer_type_, &timer, 0);
+}
+
+bool ProfileHandler::IsTimerRunning() {
+ if (!allowed_) {
+ return false;
+ }
+ struct itimerval current_timer;
+ RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
+ return (current_timer.it_value.tv_sec != 0 ||
+ current_timer.it_value.tv_usec != 0);
+}
+
+void ProfileHandler::EnableHandler() {
+ if (!allowed_) {
+ return;
+ }
+ struct sigaction sa;
+ sa.sa_sigaction = SignalHandler;
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)");
+}
+
+void ProfileHandler::DisableHandler() {
+ if (!allowed_) {
+ return;
+ }
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)");
+}
+
+bool ProfileHandler::IsSignalHandlerAvailable() {
+ struct sigaction sa;
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ 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 = ANNOTATE_UNPROTECTED_READ(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());
+
+extern "C" void ProfileHandlerRegisterThread() {
+ ProfileHandler::Instance()->RegisterThread();
+}
+
+extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+ return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
+}
+
+extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
+ ProfileHandler::Instance()->UnregisterCallback(token);
+}
+
+extern "C" void ProfileHandlerReset() {
+ return ProfileHandler::Instance()->Reset();
+}
+
+extern "C" 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.
+extern "C" void ProfileHandlerRegisterThread() {
+}
+
+extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+ return NULL;
+}
+
+extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
+}
+
+extern "C" void ProfileHandlerReset() {
+}
+
+extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
+}
+
+#endif // OS_CYGWIN
diff --git a/chromium/third_party/tcmalloc/chromium/src/profile-handler.h b/chromium/third_party/tcmalloc/chromium/src/profile-handler.h
new file mode 100644
index 00000000000..4b078ecf59e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/profile-handler.h
@@ -0,0 +1,148 @@
+/* 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 registered threads in the program are profiled.
+ * (Note: if using linux 2.4 or earlier, you must use the Thread class, in
+ * google3/thread, to ensure all threads 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 ITIMER_PROF timer and the
+ * SIGPROF signal.
+ */
+
+#ifndef BASE_PROFILE_HANDLER_H_
+#define BASE_PROFILE_HANDLER_H_
+
+#include "config.h"
+#include <signal.h>
+#ifdef COMPILER_MSVC
+#include "conflict-signal.h"
+#endif
+#include "base/basictypes.h"
+
+/* All this code should be usable from within C apps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* BASE_PROFILE_HANDLER_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/profiledata.cc b/chromium/third_party/tcmalloc/chromium/src/profiledata.cc
new file mode 100644
index 00000000000..5f2531bbb00
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/profiledata.cc
@@ -0,0 +1,331 @@
+// 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 <config.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/time.h>
+#include <string.h>
+#include <fcntl.h>
+
+#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/%" PRIuS "\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<Slot>(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<Slot>(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<Slot>(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<char*>(evict_);
+ size_t bytes = sizeof(evict_[0]) * num_evicted_;
+ total_bytes_ += bytes;
+ FDWrite(out_, buf, bytes);
+ }
+ num_evicted_ = 0;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/profiledata.h b/chromium/third_party/tcmalloc/chromium/src/profiledata.h
new file mode 100644
index 00000000000..3521bac35b6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/profiledata.h
@@ -0,0 +1,183 @@
+// 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
+// doc/cpuprofile-fileformat.html
+
+
+#ifndef BASE_PROFILEDATA_H_
+#define BASE_PROFILEDATA_H_
+
+#include <config.h>
+#include <time.h> // for time_t
+#include <stdint.h>
+#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 = 64; // 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/chromium/third_party/tcmalloc/chromium/src/profiler.cc b/chromium/third_party/tcmalloc/chromium/src/profiler.cc
new file mode 100644
index 00000000000..eb6dc4281a5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/profiler.cc
@@ -0,0 +1,344 @@
+// 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 <signal.h>
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpid()
+#endif
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h>
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
+#elif defined(__ANDROID__)
+// Do not define ucontext_t here.
+#else
+typedef int ucontext_t; // just to quiet the compiler, mostly
+#endif
+#include <sys/time.h>
+#include <string>
+#include <gperftools/profiler.h>
+#include <gperftools/stacktrace.h>
+#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"
+#ifdef HAVE_CONFLICT_SIGNAL_H
+#include "conflict-signal.h" /* used on msvc machines */
+#endif
+
+using std::string;
+
+// Collects up all profile data. This is a singleton, which is
+// initialized by a constructor at startup.
+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);
+};
+
+// 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.
+ char fname[PATH_MAX];
+ if (!GetUniquePathFromEnv("CPUPROFILE", fname)) {
+ return;
+ }
+ // We don't enable profiling if setuid -- it's a security risk
+#ifdef HAVE_GETEUID
+ if (getuid() != geteuid())
+ return;
+#endif
+
+ 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<time_t>(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<CpuProfiler*>(cpu_profiler);
+
+ if (instance->filter_ == NULL ||
+ (*instance->filter_)(instance->filter_arg_)) {
+ void* stack[ProfileData::kMaxStackDepth];
+
+ // The top-most active routine doesn't show up as a normal
+ // frame, but as the "pc" value in the signal handler context.
+ stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
+
+ // We skip the top two stack trace entries (this function 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,
+ 2, signal_ucontext);
+ depth++; // To account for pc value in stack[0];
+
+ instance->collector_.Add(depth, 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);
+}
+
+#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));
+}
+
+#endif // OS_CYGWIN
+
+// DEPRECATED routines
+extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
+extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
diff --git a/chromium/third_party/tcmalloc/chromium/src/raw_printer.cc b/chromium/third_party/tcmalloc/chromium/src/raw_printer.cc
new file mode 100644
index 00000000000..730d6e28e43
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/raw_printer.cc
@@ -0,0 +1,71 @@
+// 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 <config.h>
+#include <stdarg.h>
+#include <stdio.h>
+#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/chromium/third_party/tcmalloc/chromium/src/raw_printer.h b/chromium/third_party/tcmalloc/chromium/src/raw_printer.h
new file mode 100644
index 00000000000..62340bb37f7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/raw_printer.h
@@ -0,0 +1,89 @@
+// 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 <config.h>
+#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/chromium/third_party/tcmalloc/chromium/src/sampler.cc b/chromium/third_party/tcmalloc/chromium/src/sampler.cc
new file mode 100644
index 00000000000..0ea6df1503f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/sampler.cc
@@ -0,0 +1,130 @@
+// 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 <algorithm> // For min()
+#include <math.h>
+#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 {
+
+// Statics for Sampler
+double Sampler::log_table_[1<<kFastlogNumBits];
+
+// Populate the lookup table for FastLog2.
+// This approximates the log2 curve with a step function.
+// Steps have height equal to log2 of the mid-point of the step.
+void Sampler::PopulateFastLog2Table() {
+ for (int i = 0; i < (1<<kFastlogNumBits); i++) {
+ log_table_[i] = (log(1.0 + static_cast<double>(i+0.5)/(1<<kFastlogNumBits))
+ / log(2.0));
+ }
+}
+
+int Sampler::GetSamplePeriod() {
+ return FLAGS_tcmalloc_sample_parameter;
+}
+
+// Run this before using your sampler
+void Sampler::Init(uint32_t seed) {
+ // Initialize PRNG
+ if (seed != 0) {
+ rnd_ = seed;
+ } else {
+ rnd_ = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this));
+ if (rnd_ == 0) {
+ rnd_ = 1;
+ }
+ }
+ // Step it forward 20 times for good measure
+ for (int i = 0; i < 20; i++) {
+ rnd_ = NextRandom(rnd_);
+ }
+ // Initialize counter
+ bytes_until_sample_ = PickNextSamplingPoint();
+}
+
+// Initialize the Statics for the Sampler class
+void Sampler::InitStatics() {
+ PopulateFastLog2Table();
+}
+
+// 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
+size_t Sampler::PickNextSamplingPoint() {
+ 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<uint32_t>(rnd_ >> (prng_mod_power - 26)) + 1.0;
+ // Put the computed p-value through the CDF of a geometric.
+ // For faster performance (save ~1/20th exec time), replace
+ // min(0.0, FastLog2(q) - 26) by (Fastlog2(q) - 26.000705)
+ // The value 26.000705 is used rather than 26 to compensate
+ // for inaccuracies in FastLog2 which otherwise result in a
+ // negative answer.
+ return static_cast<size_t>(min(0.0, (FastLog2(q) - 26)) * (-log(2.0)
+ * FLAGS_tcmalloc_sample_parameter) + 1);
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/sampler.h b/chromium/third_party/tcmalloc/chromium/src/sampler.h
new file mode 100644
index 00000000000..8e67fb0249f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/sampler.h
@@ -0,0 +1,179 @@
+// 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 <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint64_t, uint32_t, int32_t
+#endif
+#include <string.h> // for memcpy
+#include "base/basictypes.h" // for ASSERT
+#include "internal_logging.h" // for ASSERT
+
+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 PERFTOOLS_DLL_DECL Sampler {
+ public:
+ // Initialize this sampler.
+ // Passing a seed of 0 gives a non-deterministic
+ // seed value given by casting the object ("this")
+ 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 512K (or FLAG_tcmalloc_sample_parameter)
+ size_t PickNextSamplingPoint();
+
+ // Initialize the statics for the Sampler class
+ static void InitStatics();
+
+ // Returns the current sample period
+ int GetSamplePeriod();
+
+ // The following are public for the purposes of testing
+ static uint64_t NextRandom(uint64_t rnd_); // Returns the next prng value
+ static double FastLog2(const double & d); // Computes Log2(x) quickly
+ static void PopulateFastLog2Table(); // Populate the lookup table
+
+ private:
+ size_t bytes_until_sample_; // Bytes until we sample next
+ uint64_t rnd_; // Cheap random number generator
+
+ // Statics for the fast log
+ // Note that this code may not depend on anything in //util
+ // hence the duplication of functionality here
+ static const int kFastlogNumBits = 10;
+ static const int kFastlogMask = (1 << kFastlogNumBits) - 1;
+ static double log_table_[1<<kFastlogNumBits]; // Constant
+};
+
+inline bool Sampler::SampleAllocation(size_t k) {
+ if (bytes_until_sample_ < k) {
+ bytes_until_sample_ = PickNextSamplingPoint();
+ return true;
+ } else {
+ bytes_until_sample_ -= k;
+ return false;
+ }
+}
+
+// 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 = 0x5DEECE66DLL;
+ const uint64_t prng_add = 0xB;
+ const uint64_t prng_mod_power = 48;
+ const uint64_t prng_mod_mask =
+ ~((~static_cast<uint64_t>(0)) << prng_mod_power);
+ return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+// Adapted from //util/math/fastmath.[h|cc] by Noam Shazeer
+// This mimics the VeryFastLog2 code in those files
+inline double Sampler::FastLog2(const double & d) {
+ ASSERT(d>0);
+ COMPILE_ASSERT(sizeof(d) == sizeof(uint64_t), DoubleMustBe64Bits);
+ uint64_t x;
+ memcpy(&x, &d, sizeof(x)); // we depend on the compiler inlining this
+ const uint32_t x_high = x >> 32;
+ const uint32_t y = x_high >> (20 - kFastlogNumBits) & kFastlogMask;
+ const int32_t exponent = ((x_high >> 20) & 0x7FF) - 1023;
+ return exponent + log_table_[y];
+}
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_SAMPLER_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/solaris/libstdc++.la b/chromium/third_party/tcmalloc/chromium/src/solaris/libstdc++.la
new file mode 100644
index 00000000000..3edf4254192
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/solaris/libstdc++.la
@@ -0,0 +1,51 @@
+# libstdc++.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# ---
+# NOTE: This file lives in /usr/sfw/lib on Solaris 10. Unfortunately,
+# due to an apparent bug in the Solaris 10 6/06 release,
+# /usr/sfw/lib/libstdc++.la is empty. Below is the correct content,
+# according to
+# http://forum.java.sun.com/thread.jspa?threadID=5073150
+# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
+# this copy of the file rather than the empty copy in /usr/sfw/lib.
+#
+# Also see
+# http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
+#
+# Note: this is for 32-bit systems. If you have a 64-bit system,
+# uncomment the appropriate dependency_libs line below.
+# ----
+
+# The name that we can dlopen(3).
+dlname='libstdc++.so.6'
+
+# Names of this library.
+library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
+
+# The name of the static archive.
+old_library='libstdc++.a'
+
+# Libraries that this one depends upon.
+# 32-bit version:
+dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
+# 64-bit version:
+#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
+
+# Version information for libstdc++.
+current=6
+age=0
+revision=3
+
+# Is this an already installed library?
+installed=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/sfw/lib'
diff --git a/chromium/third_party/tcmalloc/chromium/src/span.cc b/chromium/third_party/tcmalloc/chromium/src/span.cc
new file mode 100644
index 00000000000..760094509e2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/span.cc
@@ -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: Sanjay Ghemawat <opensource@google.com>
+
+#include <config.h>
+#include "span.h"
+
+#include <string.h> // for NULL, memset
+
+#include "internal_logging.h" // for ASSERT
+#include "page_heap_allocator.h" // for PageHeapAllocator
+#include "static_vars.h" // for Static
+
+namespace tcmalloc {
+
+#ifdef SPAN_HISTORY
+void Event(Span* span, char op, int v = 0) {
+ span->history[span->nexthistory] = op;
+ span->value[span->nexthistory] = v;
+ span->nexthistory++;
+ if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0;
+}
+#endif
+
+Span* NewSpan(PageID p, Length len) {
+ Span* result = Static::span_allocator()->New();
+ memset(result, 0, sizeof(*result));
+ result->start = p;
+ result->length = len;
+#ifdef SPAN_HISTORY
+ result->nexthistory = 0;
+#endif
+ 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/chromium/third_party/tcmalloc/chromium/src/span.h b/chromium/third_party/tcmalloc/chromium/src/span.h
new file mode 100644
index 00000000000..08db6292f95
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/span.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: Sanjay Ghemawat <opensource@google.com>
+//
+// A Span is a contiguous run of pages.
+
+#ifndef TCMALLOC_SPAN_H_
+#define TCMALLOC_SPAN_H_
+
+#include <config.h>
+#include "common.h"
+
+namespace tcmalloc {
+
+// 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
+ void* objects; // Linked list of free objects
+ 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?
+
+#undef SPAN_HISTORY
+#ifdef SPAN_HISTORY
+ // For debugging, we can keep a log events per span
+ int nexthistory;
+ char history[64];
+ int value[64];
+#endif
+
+ // What freelist the span is on: IN_USE if on none, or normal or returned
+ enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
+};
+
+#ifdef SPAN_HISTORY
+void Event(Span* span, char op, int v = 0);
+#else
+#define Event(s,o,v) ((void) 0)
+#endif
+
+// 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/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.cc b/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.cc
new file mode 100644
index 00000000000..76a032a98b1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.cc
@@ -0,0 +1,159 @@
+// 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 <config.h>
+#include "stack_trace_table.h"
+#include <string.h> // 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 {
+
+bool StackTraceTable::Bucket::KeyEqual(uintptr_t h,
+ const StackTrace& t) const {
+ const bool eq = (this->hash == h && this->trace.depth == t.depth);
+ for (int i = 0; eq && i < t.depth; ++i) {
+ if (this->trace.stack[i] != t.stack[i]) {
+ return false;
+ }
+ }
+ return eq;
+}
+
+StackTraceTable::StackTraceTable()
+ : error_(false),
+ depth_total_(0),
+ bucket_total_(0),
+ table_(new Bucket*[kHashTableSize]()) {
+ memset(table_, 0, kHashTableSize * sizeof(Bucket*));
+}
+
+StackTraceTable::~StackTraceTable() {
+ delete[] table_;
+}
+
+void StackTraceTable::AddTrace(const StackTrace& t) {
+ if (error_) {
+ return;
+ }
+
+ // Hash function borrowed from base/heap-profile-table.cc
+ uintptr_t h = 0;
+ for (int i = 0; i < t.depth; ++i) {
+ h += reinterpret_cast<uintptr_t>(t.stack[i]);
+ h += h << 10;
+ h ^= h >> 6;
+ }
+ h += h << 3;
+ h ^= h >> 11;
+
+ const int idx = h % kHashTableSize;
+
+ Bucket* b = table_[idx];
+ while (b != NULL && !b->KeyEqual(h, t)) {
+ b = b->next;
+ }
+ if (b != NULL) {
+ b->count++;
+ b->trace.size += t.size; // keep cumulative size
+ } else {
+ depth_total_ += t.depth;
+ bucket_total_++;
+ b = Static::bucket_allocator()->New();
+ if (b == NULL) {
+ Log(kLog, __FILE__, __LINE__,
+ "tcmalloc: could not allocate bucket", sizeof(*b));
+ error_ = true;
+ } else {
+ b->hash = h;
+ b->trace = t;
+ b->count = 1;
+ b->next = table_[idx];
+ table_[idx] = b;
+ }
+ }
+}
+
+void** StackTraceTable::ReadStackTracesAndClear() {
+ if (error_) {
+ return NULL;
+ }
+
+ // Allocate output array
+ const int out_len = bucket_total_ * 3 + depth_total_ + 1;
+ void** out = new void*[out_len];
+ if (out == NULL) {
+ Log(kLog, __FILE__, __LINE__,
+ "tcmalloc: allocation failed for stack traces",
+ out_len * sizeof(*out));
+ return NULL;
+ }
+
+ // Fill output array
+ int idx = 0;
+ for (int i = 0; i < kHashTableSize; ++i) {
+ Bucket* b = table_[i];
+ while (b != NULL) {
+ out[idx++] = reinterpret_cast<void*>(static_cast<uintptr_t>(b->count));
+ out[idx++] = reinterpret_cast<void*>(b->trace.size); // cumulative size
+ out[idx++] = reinterpret_cast<void*>(b->trace.depth);
+ for (int d = 0; d < b->trace.depth; ++d) {
+ out[idx++] = b->trace.stack[d];
+ }
+ b = b->next;
+ }
+ }
+ out[idx++] = NULL;
+ ASSERT(idx == out_len);
+
+ // Clear state
+ error_ = false;
+ depth_total_ = 0;
+ bucket_total_ = 0;
+ SpinLockHolder h(Static::pageheap_lock());
+ for (int i = 0; i < kHashTableSize; ++i) {
+ Bucket* b = table_[i];
+ while (b != NULL) {
+ Bucket* next = b->next;
+ Static::bucket_allocator()->Delete(b);
+ b = next;
+ }
+ table_[i] = NULL;
+ }
+
+ return out;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.h b/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.h
new file mode 100644
index 00000000000..26d21c1c7eb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stack_trace_table.h
@@ -0,0 +1,91 @@
+// 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 <config.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#include "common.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
+ struct Bucket {
+ // Key
+ uintptr_t hash;
+ StackTrace trace;
+
+ // Payload
+ int count;
+ Bucket* next;
+
+ bool KeyEqual(uintptr_t h, const StackTrace& t) const;
+ };
+
+ // For testing
+ int depth_total() const { return depth_total_; }
+ int bucket_total() const { return bucket_total_; }
+
+ private:
+ static const int kHashTableSize = 1 << 14; // => table_ is 128k
+
+ bool error_;
+ int depth_total_;
+ int bucket_total_;
+ Bucket** table_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_STACK_TRACE_TABLE_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace.cc b/chromium/third_party/tcmalloc/chromium/src/stacktrace.cc
new file mode 100644
index 00000000000..d96b4d3fa69
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace.cc
@@ -0,0 +1,110 @@
+// 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 <config.h>
+#include <gperftools/stacktrace.h>
+#include "stacktrace_config.h"
+
+#if defined(STACKTRACE_INL_HEADER)
+
+#define IS_STACK_FRAMES 0
+#define IS_WITH_CONTEXT 0
+#define GET_STACK_TRACE_OR_FRAMES \
+ GetStackTrace(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 \
+ GetStackFrames(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 \
+ GetStackTraceWithContext(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 \
+ GetStackFramesWithContext(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
+
+#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"
+#else
+# error Cannot calculate stack trace: will need to write for your environment
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
new file mode 100644
index 00000000000..1f04bc9de27
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
@@ -0,0 +1,121 @@
+// 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: Marcus Bulach
+// This is inspired by Doug Kwan's ARM's stacktrace code and Dai Mikurube's
+// stack trace for chromium on android.
+//
+
+#ifndef BASE_STACKTRACE_ANDROID_INL_H_
+#define BASE_STACKTRACE_ANDROID_INL_H_
+// Note: this file is included into stacktrace.cc more than once.
+// Anything that should only be defined once should be here:
+
+#include <stdint.h> // for uintptr_t
+// See http://crbug.com/236855, would be better to use Bionic's
+// new get_backtrace().
+#include <unwind.h>
+
+/* Depends on the system definition for _Unwind_Context */
+#ifdef HAVE_UNWIND_CONTEXT_STRUCT
+typedef struct _Unwind_Context __unwind_context;
+#else
+typedef _Unwind_Context __unwind_context;
+#endif
+
+struct stack_crawl_state_t {
+ uintptr_t* frames;
+ size_t frame_count;
+ int max_depth;
+ int skip_count;
+ bool have_skipped_self;
+
+ stack_crawl_state_t(uintptr_t* frames, int max_depth, int skip_count)
+ : frames(frames),
+ frame_count(0),
+ max_depth(max_depth),
+ skip_count(skip_count),
+ have_skipped_self(false) {
+ }
+};
+
+static _Unwind_Reason_Code tracer(__unwind_context* context, void* arg) {
+ stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg);
+
+#if defined(__clang__)
+ // Vanilla Clang's unwind.h doesn't have _Unwind_GetIP for ARM.
+ // See http://crbug.com/236855, too.
+ uintptr_t ip = 0;
+ _Unwind_VRS_Get(context, _UVRSC_CORE, 15, _UVRSD_UINT32, &ip);
+ ip &= ~(uintptr_t)0x1; // remove thumb mode bit
+#else
+ uintptr_t ip = _Unwind_GetIP(context);
+#endif
+
+ // The first stack frame is this function itself. Skip it.
+ if (ip != 0 && !state->have_skipped_self) {
+ state->have_skipped_self = true;
+ return _URC_NO_REASON;
+ }
+
+ if (state->skip_count) {
+ --state->skip_count;
+ return _URC_NO_REASON;
+ }
+
+ state->frames[state->frame_count++] = ip;
+ if (state->frame_count >= state->max_depth)
+ return _URC_END_OF_STACK;
+ else
+ return _URC_NO_REASON;
+}
+
+#endif // BASE_STACKTRACE_ANDROID_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 {
+ stack_crawl_state_t state(
+ reinterpret_cast<uintptr_t*>(result), max_depth, skip_count);
+ _Unwind_Backtrace(tracer, &state);
+ return state.frame_count;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h
new file mode 100644
index 00000000000..5ee1bf9d01f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h
@@ -0,0 +1,145 @@
+// 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 <stdint.h> // for uintptr_t
+#include "base/basictypes.h" // for NULL
+#include <gperftools/stacktrace.h>
+
+// 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<bool STRICT_UNWINDING>
+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)
+int GET_STACK_TRACE_OR_FRAMES {
+#ifdef __GNUC__
+ void **sp = reinterpret_cast<void**>(__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();
+
+ 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<IS_STACK_FRAMES == 0>(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/chromium/third_party/tcmalloc/chromium/src/stacktrace_config.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_config.h
new file mode 100644
index 00000000000..a462ceb089d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_config.h
@@ -0,0 +1,89 @@
+// 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: Paul Pluzhnikov
+//
+// Figure out which unwinder to use on a given platform.
+//
+// Defines STACKTRACE_INL_HEADER to the *-inl.h containing
+// actual unwinder implementation.
+//
+// Defines STACKTRACE_SKIP_CONTEXT_ROUTINES if a separate
+// GetStack{Trace,Frames}WithContext should not be provided.
+//
+// This header is "private" to stacktrace.cc and
+// stacktrace_with_context.cc.
+//
+// DO NOT include it into any other files.
+
+#ifndef BASE_STACKTRACE_CONFIG_H_
+#define BASE_STACKTRACE_CONFIG_H_
+
+// First, the i386 and x86_64 case.
+#if (defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h"
+# define STACKTRACE_SKIP_CONTEXT_ROUTINES 1
+# elif defined(HAVE_LIBUNWIND_H) // a proxy for having libunwind installed
+# define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h"
+# define STACKTRACE_USES_LIBUNWIND 1
+# elif defined(__linux)
+# error Cannnot calculate stack trace: need either libunwind or frame-pointers (see INSTALL file)
+# else
+# error Cannnot calculate stack trace: need libunwind (see INSTALL file)
+# endif
+
+// The PowerPC case
+#elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_powerpc-inl.h"
+# else
+# define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h"
+# endif
+
+// The Android case
+#elif defined(__ANDROID__)
+#define STACKTRACE_INL_HEADER "stacktrace_android-inl.h"
+
+// The ARM case
+#elif defined(__arm__) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h"
+# else
+# error stacktrace without frame pointer is not supported on ARM
+# 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.
+#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
+# define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h"
+
+#endif // all the cases
+#endif // BASE_STACKTRACE_CONFIG_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h
new file mode 100644
index 00000000000..5a526e228a1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h
@@ -0,0 +1,83 @@
+// 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 <execinfo.h>
+#include <string.h>
+#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)
+int GET_STACK_TRACE_OR_FRAMES {
+ static const int kStackLength = 64;
+ void * stack[kStackLength];
+ int size;
+
+ size = backtrace(stack, kStackLength);
+ skip_count++; // we want to skip the current 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/chromium/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
new file mode 100644
index 00000000000..82b0cfeb7ae
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
@@ -0,0 +1,128 @@
+// 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 <assert.h>
+#include <string.h> // for memset()
+#include <libunwind.h>
+}
+#include "gperftools/stacktrace.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;
+
+#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)
+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;
+
+ unw_getcontext(&uc);
+ int ret = unw_init_local(&cursor, &uc);
+ assert(ret >= 0);
+ skip_count++; // Do not include current frame
+
+ 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/chromium/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h
new file mode 100644
index 00000000000..acf2884e323
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h
@@ -0,0 +1,170 @@
+// 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 <stdint.h> // for uintptr_t
+#include <stdlib.h> // for NULL
+#include <gperftools/stacktrace.h>
+
+// 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<bool STRICT_UNWINDING>
+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 __APPLE__
+ __asm__ volatile ("mr %0,r1" : "=r" (sp));
+#else
+ __asm__ volatile ("mr %0,1" : "=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<!IS_STACK_FRAMES>(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(_CALL_AIX) || defined(_CALL_DARWIN)
+ result[n] = *(sp+2);
+#elif defined(_CALL_SYSV)
+ result[n] = *(sp+1);
+#elif defined(__APPLE__) || (defined(__linux) && 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);
+#else
+#error Need to specify the PPC ABI for your archiecture.
+#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/chromium/third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h
new file mode 100644
index 00000000000..2af472de5e0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h
@@ -0,0 +1,91 @@
+// 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 <windows.h> // for GetProcAddress and GetModuleHandle
+#include <assert.h>
+
+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");
+
+PERFTOOLS_DLL_DECL int GetStackTrace(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 + 2, max_depth,
+ result, 0);
+}
+
+PERFTOOLS_DLL_DECL int GetStackFrames(void** /* pcs */,
+ int* /* sizes */,
+ int /* max_depth */,
+ int /* skip_count */) {
+ assert(0 == "Not yet implemented");
+ return 0;
+}
+
+#endif // BASE_STACKTRACE_WIN32_INL_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace_with_context.cc b/chromium/third_party/tcmalloc/chromium/src/stacktrace_with_context.cc
new file mode 100644
index 00000000000..036d984f012
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_with_context.cc
@@ -0,0 +1,61 @@
+// 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: Paul Pluzhnikov
+//
+// This code logically belongs in stacktrace.cc, but
+// it is moved into (this) separate file in order to
+// prevent inlining of routines defined here.
+//
+// Inlining causes skip_count to be incorrect, and there
+// is no portable way to prevent it.
+//
+// Eventually LTO (link-time optimization) and/or LLVM
+// may inline this code anyway. Let's hope they respect
+// ATTRIBUTE_NOINLINE.
+
+#include <config.h>
+#include <gperftools/stacktrace.h>
+#include "stacktrace_config.h"
+#include "base/basictypes.h"
+
+#if !defined(STACKTRACE_SKIP_CONTEXT_ROUTINES)
+ATTRIBUTE_NOINLINE PERFTOOLS_DLL_DECL
+int GetStackFramesWithContext(void** pcs, int* sizes, int max_depth,
+ int skip_count, const void * /* uc */) {
+ return GetStackFrames(pcs, sizes, max_depth, skip_count + 1);
+}
+
+ATTRIBUTE_NOINLINE PERFTOOLS_DLL_DECL
+int GetStackTraceWithContext(void** result, int max_depth,
+ int skip_count, const void * /* uc */) {
+ return GetStackTrace(result, max_depth, skip_count + 1);
+}
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h b/chromium/third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h
new file mode 100644
index 00000000000..abbe0a923cc
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h
@@ -0,0 +1,396 @@
+// 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 <stdlib.h> // for NULL
+#include <assert.h>
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h> // for ucontext_t
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+// cygwin/signal.h has a buglet where it uses pthread_attr_t without
+// #including <pthread.h> itself. So we have to do it.
+# ifdef HAVE_PTHREAD
+# include <pthread.h>
+# endif
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h> // for msync
+#include "base/vdso_support.h"
+#endif
+
+#include "gperftools/stacktrace.h"
+#if defined(KEEP_SHADOW_STACKS)
+#include "linux_shadow_stacks.h"
+#endif // KEEP_SHADOW_STACKS
+
+#if defined(__linux__) && defined(__i386__) && defined(__ELF__) && defined(HAVE_MMAP)
+// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
+// preceeding "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<bool STRICT_UNWINDING, bool WITH_CONTEXT>
+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<const unsigned char *>(
+ rt_sigreturn_symbol_info.address);
+ kernel_vsyscall_address =
+ reinterpret_cast<const unsigned char *>(
+ 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<const ucontext_t *>(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<void **>(ucv->uc_mcontext.gregs[REG_EBP]);
+ const unsigned char *const reg_eip =
+ reinterpret_cast<unsigned char *>(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<void **>(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<void *>(
+ (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<void **>(
+ 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<false>() 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)
+
+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<void**>(__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
+
+ int n = 0;
+#if defined(KEEP_SHADOW_STACKS)
+ void **shadow_ip_stack;
+ void **shadow_sp_stack;
+ int stack_size;
+ shadow_ip_stack = (void**) get_shadow_ip_stack(&stack_size);
+ shadow_sp_stack = (void**) get_shadow_sp_stack(&stack_size);
+ int shadow_index = stack_size - 1;
+ for (int i = stack_size - 1; i >= 0; i--) {
+ if (sp == shadow_sp_stack[i]) {
+ shadow_index = i;
+ break;
+ }
+ }
+ void **prev_sp = NULL;
+#endif // KEEP_SHADOW_STACKS
+ while (sp && n < max_depth) {
+ if (*(sp+1) == reinterpret_cast<void *>(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<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(sp, ucp);
+ if (skip_count > 0) {
+ skip_count--;
+#if defined(KEEP_SHADOW_STACKS)
+ shadow_index--;
+#endif // KEEP_SHADOW_STACKS
+ } else {
+ result[n] = *(sp+1);
+#if defined(KEEP_SHADOW_STACKS)
+ if ((shadow_index > 0) && (sp == shadow_sp_stack[shadow_index])) {
+ shadow_index--;
+ }
+#endif // KEEP_SHADOW_STACKS
+
+#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++;
+ }
+#if defined(KEEP_SHADOW_STACKS)
+ prev_sp = sp;
+#endif // KEEP_SHADOW_STACKS
+ sp = next_sp;
+ }
+
+#if defined(KEEP_SHADOW_STACKS)
+ if (shadow_index >= 0) {
+ for (int i = shadow_index; i >= 0; i--) {
+ if (shadow_sp_stack[i] > prev_sp) {
+ result[n] = shadow_ip_stack[i];
+ if (n + 1 < max_depth) {
+ n++;
+ continue;
+ }
+ }
+ break;
+ }
+ }
+#endif // KEEP_SHADOW_STACKS
+ return n;
+}
diff --git a/chromium/third_party/tcmalloc/chromium/src/static_vars.cc b/chromium/third_party/tcmalloc/chromium/src/static_vars.cc
new file mode 100644
index 00000000000..6fc852a82d1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/static_vars.cc
@@ -0,0 +1,73 @@
+// 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 <opensource@google.com>
+
+#include "static_vars.h"
+#include <stddef.h> // for NULL
+#include <new> // for operator new
+#include "internal_logging.h" // for CHECK_CONDITION
+#include "common.h"
+#include "sampler.h" // for Sampler
+
+namespace tcmalloc {
+
+SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
+SizeMap Static::sizemap_;
+CentralFreeListPadded Static::central_cache_[kNumClasses];
+PageHeapAllocator<Span> Static::span_allocator_;
+PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
+Span Static::sampled_objects_;
+PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
+StackTrace* Static::growth_stacks_ = NULL;
+PageHeap* Static::pageheap_ = NULL;
+
+void Static::InitStaticVars() {
+ sizemap_.Init();
+ span_allocator_.Init();
+ span_allocator_.New(); // Reduce cache conflicts
+ span_allocator_.New(); // Reduce cache conflicts
+ stacktrace_allocator_.Init();
+ bucket_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 < kNumClasses; ++i) {
+ central_cache_[i].Init(i);
+ }
+ // It's important to have PageHeap allocated, not in static storage,
+ // so that HeapLeakChecker does not consider all the byte patterns stored
+ // in is caches as pointers that are sources of heap object liveness,
+ // which leads to it missing some memory leaks.
+ pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
+ DLL_Init(&sampled_objects_);
+ Sampler::InitStatics();
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/chromium/src/static_vars.h b/chromium/third_party/tcmalloc/chromium/src/static_vars.h
new file mode 100644
index 00000000000..185a1d45ea8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/static_vars.h
@@ -0,0 +1,111 @@
+// 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 <opensource@google.com>
+//
+// Static variables shared by multiple classes.
+
+#ifndef TCMALLOC_STATIC_VARS_H_
+#define TCMALLOC_STATIC_VARS_H_
+
+#include <config.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();
+
+ // 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_; }
+
+ //////////////////////////////////////////////////////////////////////
+ // In addition to the explicit initialization comment, the variables below
+ // must be protected by pageheap_lock.
+
+ // Page-level allocator.
+ static PageHeap* pageheap() { return pageheap_; }
+
+ static PageHeapAllocator<Span>* span_allocator() { return &span_allocator_; }
+
+ static PageHeapAllocator<StackTrace>* 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_; }
+ static PageHeapAllocator<StackTraceTable::Bucket>* bucket_allocator() {
+ return &bucket_allocator_;
+ }
+
+ private:
+ 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.
+
+ static SizeMap sizemap_;
+ static CentralFreeListPadded central_cache_[kNumClasses];
+ static PageHeapAllocator<Span> span_allocator_;
+ static PageHeapAllocator<StackTrace> stacktrace_allocator_;
+ static Span sampled_objects_;
+ static PageHeapAllocator<StackTraceTable::Bucket> bucket_allocator_;
+
+ // 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].
+ static StackTrace* growth_stacks_;
+
+ static PageHeap* pageheap_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_STATIC_VARS_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/symbolize.cc b/chromium/third_party/tcmalloc/chromium/src/symbolize.cc
new file mode 100644
index 00000000000..65150f31caf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/symbolize.cc
@@ -0,0 +1,280 @@
+// 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 <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h> // for socketpair() -- needed by Symbolize
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h> // for wait() -- needed by Symbolize
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef __MACH__
+#include <mach-o/dyld.h> // for GetProgramInvocationName()
+#include <limits.h> // for PATH_MAX
+#endif
+#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+#include <io.h> // for get_osfhandle()
+#endif
+#include <string>
+#include "base/commandlineflags.h"
+#include "base/logging.h"
+#include "base/sysinfo.h"
+
+using std::string;
+using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
+
+
+DEFINE_string(symbolize_pprof,
+ EnvToString("PPROF_PATH", "pprof"),
+ "Path to pprof to call for reporting function names.");
+
+// heap_profile_table_pprof may be referenced 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 string* g_pprof_path = new string(FLAGS_symbolize_pprof);
+
+// 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 char* GetProgramInvocationName() {
+#if defined(HAVE_PROGRAM_INVOCATION_NAME)
+ extern char* program_invocation_name; // gcc provides this
+ 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;
+#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(g_pprof_path->c_str(), 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(g_pprof_path->c_str(), g_pprof_path->c_str(),
+ "--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<uintptr_t>(iter->first));
+ }
+ write(child_in[1], pprof_buffer, strlen(pprof_buffer));
+ close(child_in[1]); // that's all we need to write
+
+ 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/chromium/third_party/tcmalloc/chromium/src/symbolize.h b/chromium/third_party/tcmalloc/chromium/src/symbolize.h
new file mode 100644
index 00000000000..12c976ba60c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/symbolize.h
@@ -0,0 +1,83 @@
+// 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 <stdint.h> // for uintptr_t
+#endif
+#include <stddef.h> // for NULL
+#include <map>
+
+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<const void*, const char*> 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/chromium/third_party/tcmalloc/chromium/src/system-alloc.cc b/chromium/third_party/tcmalloc/chromium/src/system-alloc.cc
new file mode 100644
index 00000000000..2141d413ed5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/system-alloc.cc
@@ -0,0 +1,695 @@
+// 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 <config.h>
+#include <errno.h> // for EAGAIN, errno
+#include <fcntl.h> // for open, O_RDWR
+#include <stddef.h> // for size_t, NULL, ptrdiff_t
+#if defined HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t, intptr_t
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h> // for munmap, mmap, MADV_DONTNEED, etc
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for sbrk, getpagesize, off_t
+#endif
+#include <new> // for operator new
+#include <gperftools/malloc_extension.h>
+#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
+
+// 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 <sys/types.h> // 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;
+
+// Anonymous namespace to avoid name conflicts on "CheckAddressBits".
+namespace {
+
+// Check that no bit is set at position ADDRESS_BITS or higher.
+template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) {
+ return (ptr >> ADDRESS_BITS) == 0;
+}
+
+// Specialize for the bit width of a pointer to avoid undefined shift.
+template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) {
+ return true;
+}
+
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__)
+#define ASLR_IS_SUPPORTED
+#endif
+
+#if defined(ASLR_IS_SUPPORTED)
+// From libdieharder, public domain library by Bob Jenkins (rngav.c).
+// Described at http://burtleburtle.net/bob/rand/smallprng.html.
+// Not cryptographically secure, but good enough for what we need.
+typedef uint32_t u4;
+struct ranctx {
+ u4 a;
+ u4 b;
+ u4 c;
+ u4 d;
+};
+
+#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
+
+u4 ranval(ranctx* x) {
+ /* xxx: the generator being tested */
+ u4 e = x->a - rot(x->b, 27);
+ x->a = x->b ^ rot(x->c, 17);
+ x->b = x->c + x->d;
+ x->c = x->d + e;
+ x->d = e + x->a;
+ return x->d;
+}
+
+void raninit(ranctx* x, u4 seed) {
+ u4 i;
+ x->a = 0xf1ea5eed;
+ x->b = x->c = x->d = seed;
+ for (i = 0; i < 20; ++i) {
+ (void) ranval(x);
+ }
+}
+
+// If the kernel cannot honor the hint in arch_get_unmapped_area_topdown, it
+// will simply ignore it. So we give a hint that has a good chance of
+// working.
+// The mmap top-down allocator will normally allocate below TASK_SIZE - gap,
+// with a gap that depends on the max stack size. See x86/mm/mmap.c. We
+// should make allocations that are below this area, which would be
+// 0x7ffbf8000000.
+// We use 0x3ffffffff000 as the mask so that we only "pollute" half of the
+// address space. In the unlikely case where fragmentation would become an
+// issue, the kernel will still have another half to use.
+const uint64_t kRandomAddressMask = 0x3ffffffff000ULL;
+
+#endif // defined(ASLR_IS_SUPPORTED)
+
+// Give a random "hint" that is suitable for use with mmap(). This cannot make
+// mmap fail, as the kernel will simply not follow the hint if it can't.
+// However, this will create address space fragmentation. Currently, we only
+// implement it on x86_64, where we have a 47 bits userland address space and
+// fragmentation is not an issue.
+void* GetRandomAddrHint() {
+#if !defined(ASLR_IS_SUPPORTED)
+ return NULL;
+#else
+ // Note: we are protected by the general TCMalloc_SystemAlloc spinlock. Given
+ // the nature of what we're doing, it wouldn't be critical if we weren't for
+ // ctx, but it is for the "initialized" variable.
+ // It's nice to share the state between threads, because scheduling will add
+ // some randomness to the succession of ranval() calls.
+ static ranctx ctx;
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ // We really want this to be a stack variable and don't want any compiler
+ // optimization. We're using its address as a poor-man source of
+ // randomness.
+ volatile char c;
+ // Pre-initialize our seed with a "random" address in case /dev/urandom is
+ // not available.
+ uint32_t seed = (reinterpret_cast<uint64_t>(&c) >> 32) ^
+ reinterpret_cast<uint64_t>(&c);
+ int urandom_fd = open("/dev/urandom", O_RDONLY);
+ if (urandom_fd >= 0) {
+ ssize_t len;
+ len = read(urandom_fd, &seed, sizeof(seed));
+ ASSERT(len == sizeof(seed));
+ int ret = close(urandom_fd);
+ ASSERT(ret == 0);
+ }
+ raninit(&ctx, seed);
+ }
+ uint64_t random_address = (static_cast<uint64_t>(ranval(&ctx)) << 32) |
+ ranval(&ctx);
+ // A a bit-wise "and" won't bias our random distribution.
+ random_address &= kRandomAddressMask;
+ return reinterpret_cast<void*>(random_address);
+#endif // ASLR_IS_SUPPORTED
+}
+
+// Allocate |length| bytes of memory using mmap(). The memory will be
+// readable and writeable, but not executable.
+// Like mmap(), we will return MAP_FAILED on failure.
+// |is_aslr_enabled| controls address space layout randomization. When true, we
+// will put the first mapping at a random address and will then try to grow it.
+// If it's not possible to grow an existing mapping, a new one will be created.
+void* AllocWithMmap(size_t length, bool is_aslr_enabled) {
+ // Note: we are protected by the general TCMalloc_SystemAlloc spinlock.
+ static void* address_hint = NULL;
+#if defined(ASLR_IS_SUPPORTED)
+ if (is_aslr_enabled &&
+ (!address_hint ||
+ reinterpret_cast<uint64_t>(address_hint) & ~kRandomAddressMask)) {
+ address_hint = GetRandomAddrHint();
+ }
+#endif // ASLR_IS_SUPPORTED
+
+ // address_hint is likely to make us grow an existing mapping.
+ void* result = mmap(address_hint, length, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+#if defined(ASLR_IS_SUPPORTED)
+ if (result == address_hint) {
+ // If mmap() succeeded at a address_hint, our next mmap() will try to grow
+ // the current mapping as long as it's compatible with our ASLR mask.
+ // This has been done for performance reasons, see crbug.com/173371.
+ // It should be possible to strike a better balance between performance
+ // and security but will be done at a later date.
+ // If this overflows, it could only set address_hint to NULL, which is
+ // what we want (and can't happen on the currently supported architecture).
+ address_hint = static_cast<char*>(result) + length;
+ } else {
+ // mmap failed or a collision prevented the kernel from honoring the hint,
+ // reset the hint.
+ address_hint = NULL;
+ }
+#endif // ASLR_IS_SUPPORTED
+ return result;
+}
+
+} // Anonymous namespace to avoid name conflicts on "CheckAddressBits".
+
+COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*),
+ address_bits_larger_than_pointer_size);
+
+// Structure for discovering alignment
+union MemoryAligner {
+ void* p;
+ double d;
+ size_t s;
+} CACHELINE_ALIGNED;
+
+static SpinLock spinlock(SpinLock::LINKER_INITIALIZED);
+
+#if defined(HAVE_MMAP) || defined(MADV_FREE)
+#ifdef HAVE_GETPAGESIZE
+static size_t pagesize = 0;
+#endif
+#endif
+
+// The current system allocator
+SysAllocator* sys_alloc = NULL;
+
+// 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_random_allocator,
+#if defined(ASLR_IS_SUPPORTED)
+ EnvToBool("TCMALLOC_ASLR", true),
+#else
+ EnvToBool("TCMALLOC_ASLR", false),
+#endif
+ "Whether to randomize the address space via mmap().");
+
+// static allocators
+class SbrkSysAllocator : public SysAllocator {
+public:
+ SbrkSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t *actual_size, size_t alignment);
+};
+static char sbrk_space[sizeof(SbrkSysAllocator)];
+
+class MmapSysAllocator : public SysAllocator {
+public:
+ MmapSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t *actual_size, size_t alignment);
+};
+static char mmap_space[sizeof(MmapSysAllocator)];
+
+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 char default_space[sizeof(DefaultSysAllocator)];
+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) {
+#ifndef HAVE_SBRK
+ 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<ptrdiff_t>(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<intptr_t>(sbrk(0)) + size < size) {
+ return NULL;
+ }
+
+ void* result = sbrk(size);
+ if (result == reinterpret_cast<void*>(-1)) {
+ return NULL;
+ }
+
+ // Is it aligned?
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(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<uintptr_t>(r2) == (ptr + size)) {
+ // Contiguous with previous result
+ return reinterpret_cast<void*>(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<void*>(-1)) {
+ return NULL;
+ }
+ ptr = reinterpret_cast<uintptr_t>(result);
+ if ((ptr & (alignment-1)) != 0) {
+ ptr += alignment - (ptr & (alignment-1));
+ }
+ return reinterpret_cast<void*>(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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void* result = AllocWithMmap(size + extra, FLAGS_malloc_random_allocator);
+ if (result == reinterpret_cast<void*>(MAP_FAILED)) {
+ return NULL;
+ }
+
+ // Adjust the return memory so it is aligned
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+
+ // Return the unused memory to the system
+ if (adjust > 0) {
+ munmap(reinterpret_cast<void*>(ptr), adjust);
+ }
+ if (adjust < extra) {
+ munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
+ }
+
+ ptr += adjust;
+ return reinterpret_cast<void*>(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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ MAP_SHARED, physmem_fd, physmem_base);
+ if (result == reinterpret_cast<void*>(MAP_FAILED)) {
+ return NULL;
+ }
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+
+ // Adjust the return memory so it is aligned
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+
+ // Return the unused virtual memory to the system
+ if (adjust > 0) {
+ munmap(reinterpret_cast<void*>(ptr), adjust);
+ }
+ if (adjust < extra) {
+ munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
+ }
+
+ ptr += adjust;
+ physmem_base += adjust + size;
+
+ return reinterpret_cast<void*>(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;
+}
+
+static bool system_alloc_inited = false;
+void InitSystemAllocators(void) {
+ MmapSysAllocator *mmap = new (mmap_space) MmapSysAllocator();
+ SbrkSysAllocator *sbrk = new (sbrk_space) 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) DefaultSysAllocator();
+ // Unfortunately, this code runs before flags are initialized. So
+ // we can't use FLAGS_malloc_random_allocator.
+#if defined(ASLR_IS_SUPPORTED)
+ // Our only random allocator is mmap.
+ sdef->SetChildAllocator(mmap, 0, mmap_name);
+#else
+ 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);
+ }
+#endif // ASLR_IS_SUPPORTED
+ sys_alloc = 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);
+
+ void* result = sys_alloc->Alloc(size, actual_size, alignment);
+ if (result != NULL) {
+ if (actual_size) {
+ CheckAddressBits<kAddressBits>(
+ reinterpret_cast<uintptr_t>(result) + *actual_size - 1);
+ } else {
+ CheckAddressBits<kAddressBits>(
+ reinterpret_cast<uintptr_t>(result) + size - 1);
+ }
+ }
+ return result;
+}
+
+size_t TCMalloc_SystemAddGuard(void* start, size_t size) {
+#ifdef HAVE_GETPAGESIZE
+ if (pagesize == 0)
+ pagesize = getpagesize();
+
+ if (size < pagesize || (reinterpret_cast<size_t>(start) % pagesize) != 0)
+ return 0;
+
+ if (!mprotect(start, pagesize, PROT_NONE))
+ return pagesize;
+#endif
+
+ return 0;
+}
+
+void 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;
+ }
+ if (pagesize == 0) pagesize = getpagesize();
+ const size_t pagemask = pagesize - 1;
+
+ size_t new_start = reinterpret_cast<size_t>(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<size_t>(start));
+ ASSERT(new_end <= end);
+
+ if (new_end > new_start) {
+ // Note -- ignoring most return codes, because if this fails it
+ // doesn't matter...
+ while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start,
+ MADV_FREE) == -1 &&
+ errno == EAGAIN) {
+ // NOP
+ }
+ }
+#endif
+}
+
+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/chromium/third_party/tcmalloc/chromium/src/system-alloc.h b/chromium/third_party/tcmalloc/chromium/src/system-alloc.h
new file mode 100644
index 00000000000..0432b32ebd9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/system-alloc.h
@@ -0,0 +1,88 @@
+// 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 <config.h>
+#include <stddef.h> // 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 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.)
+extern void 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 void TCMalloc_SystemCommit(void* start, size_t length);
+
+// Guards the first page in the supplied range of memory and returns the size
+// of the guard page. Will return 0 if a guard cannot be added to the page
+// (e.g. start is not aligned or size is not large enough).
+extern size_t TCMalloc_SystemAddGuard(void* start, size_t size);
+
+// The current system allocator.
+extern PERFTOOLS_DLL_DECL SysAllocator* sys_alloc;
+
+#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/tcmalloc.cc b/chromium/third_party/tcmalloc/chromium/src/tcmalloc.cc
new file mode 100644
index 00000000000..118e40a09fd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/tcmalloc.cc
@@ -0,0 +1,1880 @@
+// 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 <opensource@google.com>
+//
+// 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 doc/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"
+#include <gperftools/tcmalloc.h>
+
+#include <errno.h> // for ENOMEM, EINVAL, errno
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#include <stddef.h> // for size_t, NULL
+#include <stdlib.h> // for getenv
+#include <string.h> // for strcmp, memset, strlen, etc
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpagesize, write, etc
+#endif
+#include <algorithm> // for max, min
+#include <limits> // for numeric_limits
+#include <new> // for nothrow_t (ptr only), etc
+#include <vector> // for vector
+
+#include <gperftools/malloc_extension.h>
+#include <gperftools/malloc_hook.h> // for MallocHook
+#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 "free_list.h" // for FL_Init
+#include "internal_logging.h" // for ASSERT, TCMalloc_Printer, etc
+#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
+
+#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 (!)
+// For instance, <windows.h> appears to have "#define small char".
+#undef small
+
+using STL_NAMESPACE::max;
+using STL_NAMESPACE::min;
+using STL_NAMESPACE::numeric_limits;
+using STL_NAMESPACE::vector;
+
+#include "libc_override.h"
+
+// __THROW is defined in glibc (via <sys/cdefs.h>). 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 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;
+
+// ---- Functions doing validation with an extra mark.
+static size_t ExcludeSpaceForMark(size_t size);
+static void AddRoomForMark(size_t* size);
+static void ExcludeMarkFromSize(size_t* new_size);
+static void MarkAllocatedRegion(void* ptr);
+static void ValidateAllocatedRegion(void* ptr, size_t cl);
+// ---- End validation functions.
+
+DECLARE_int64(tcmalloc_sample_parameter);
+DECLARE_double(tcmalloc_release_rate);
+
+// 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<int64>(1) << 62;
+#else
+const int64 kDefaultLargeAllocReportThreshold = static_cast<int64>(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.
+extern "C" {
+ void* tc_malloc(size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_free(void* ptr) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_realloc(void* ptr, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_calloc(size_t nmemb, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_cfree(void* ptr) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ void* tc_memalign(size_t __alignment, size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ int tc_posix_memalign(void** ptr, size_t align, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_valloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_pvalloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ void tc_malloc_stats(void) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ int tc_mallopt(int cmd, int value) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+#ifdef HAVE_STRUCT_MALLINFO
+ struct mallinfo tc_mallinfo(void) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+#endif
+
+ void* tc_new(size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_delete(void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_newarray(size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_deletearray(void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ // And the nothrow variants of these:
+ void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW
+ 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&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_deletearray_nothrow(void* ptr, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ // 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) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+} // extern "C"
+
+
+// ----------------------- 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 {
+void InvalidFree(void* ptr) {
+ 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;
+}
+
+// For security reasons, we want to limit the size of allocations.
+// See crbug.com/169327.
+inline bool IsAllocSizePermitted(size_t alloc_size) {
+ // Never allow an allocation larger than what can be indexed via an int.
+ // Remove kPageSize to account for various rounding, padding and to have a
+ // small margin.
+ return alloc_size <= ((std::numeric_limits<int>::max)() - kPageSize);
+}
+
+} // 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
+ uint64_t metadata_unmapped_bytes; // Address space reserved for metadata
+ // but is not committed.
+ PageHeap::Stats pageheap; // Stats from page heap
+};
+
+// Get stats into "r". Also get per-size-class counts if class_count != NULL
+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 < kNumClasses; ++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<uint64_t>(
+ Static::sizemap()->ByteSizeForClass(cl));
+ r->central_bytes += (size * length) + cache_overhead;
+ r->transfer_bytes += (size * tc_length);
+ if (class_count) 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->metadata_unmapped_bytes = tcmalloc::metadata_unmapped_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[kNumClasses];
+ 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 physical_memory_used_by_metadata =
+ stats.metadata_bytes - stats.metadata_unmapped_bytes;
+ const uint64_t unmapped_bytes =
+ stats.pageheap.unmapped_bytes + stats.metadata_unmapped_bytes;
+
+ const uint64_t virtual_memory_used = (stats.pageheap.system_bytes
+ + stats.metadata_bytes);
+ const uint64_t physical_memory_used = virtual_memory_used - unmapped_bytes;
+ const uint64_t bytes_in_use_by_app = (physical_memory_used
+ - physical_memory_used_by_metadata
+ - stats.pageheap.free_bytes
+ - stats.central_bytes
+ - stats.transfer_bytes
+ - stats.thread_bytes);
+
+ out->printf(
+ "WASTE: %7.1f MiB bytes in use\n"
+ "WASTE: + %7.1f MiB committed but not used\n"
+ "WASTE: ------------\n"
+ "WASTE: = %7.1f MiB bytes committed\n"
+ "WASTE: committed/used ratio of %f\n",
+ bytes_in_use_by_app / MiB,
+ (stats.pageheap.committed_bytes - bytes_in_use_by_app) / MiB,
+ stats.pageheap.committed_bytes / MiB,
+ stats.pageheap.committed_bytes / static_cast<double>(bytes_in_use_by_app)
+ );
+#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: ------------\n"
+ "MALLOC: = %12" PRIu64 " (%7.1f MiB) Bytes committed\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.pageheap.committed_bytes, stats.pageheap.committed_bytes / MiB,
+ physical_memory_used_by_metadata , physical_memory_used_by_metadata / MiB,
+ physical_memory_used, physical_memory_used / MiB,
+ unmapped_bytes, 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("Size class breakdown\n");
+ out->printf("------------------------------------------------\n");
+ uint64_t cumulative = 0;
+ for (int cl = 0; cl < kNumClasses; ++cl) {
+ if (class_count[cl] > 0) {
+ uint64_t class_bytes =
+ class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
+ cumulative += class_bytes;
+ out->printf("class %3d [ %8" PRIuS " bytes ] : "
+ "%8" PRIu64 " objs; %5.1f MiB; %5.1f cum MiB\n",
+ cl, Static::sizemap()->ByteSizeForClass(cl),
+ class_count[cl],
+ class_bytes / MiB,
+ cumulative / 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 = 0; s < kMaxPages; s++) {
+ const int n_length = small.normal_length[s];
+ const int r_length = small.returned_length[s];
+ 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(">255 large * %6u spans ~ %6.1f MiB; %6.1f MiB cum"
+ "; unmapped: %6.1f MiB; %6.1f MiB cum\n",
+ static_cast<unsigned int>(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<StackTrace*>(
+ 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<StackTrace*>(
+ 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<void*>(static_cast<uintptr_t>(1));
+ result[used_slots+1] = reinterpret_cast<void*>(t->size);
+ result[used_slots+2] = reinterpret_cast<void*>(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<void*>(static_cast<uintptr_t>(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<StackTrace*>(s->objects));
+ }
+ }
+ *sample_period = ThreadCache::GetCache()->GetSamplePeriod();
+ return table.ReadStackTracesAndClear(); // grabs and releases pageheap_lock
+ }
+
+ virtual void** ReadHeapGrowthStackTraces() {
+ return DumpHeapGrowthStackTraces();
+ }
+
+ 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, "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.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.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;
+ }
+
+ 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;
+ }
+
+ return false;
+ }
+
+ virtual void MarkThreadIdle() {
+ ThreadCache::BecomeIdle();
+ }
+
+ virtual void MarkThreadBusy(); // Implemented below
+
+ virtual SysAllocator* GetSystemAllocator() {
+ SpinLockHolder h(Static::pageheap_lock());
+ return sys_alloc;
+ }
+
+ virtual void SetSystemAllocator(SysAllocator* alloc) {
+ SpinLockHolder h(Static::pageheap_lock());
+ 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<Length>(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) {
+ if (size <= kMaxSize) {
+ const size_t cl = Static::sizemap()->SizeClass(size);
+ const size_t alloc_size = Static::sizemap()->ByteSizeForClass(cl);
+ return alloc_size;
+ } else {
+ return tcmalloc::pages(size) << kPageShift;
+ }
+ }
+
+ // 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<uintptr_t>(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;
+ }
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+ if (cl != 0) {
+ return kOwned;
+ }
+ const Span *span = Static::pageheap()->GetDescriptor(p);
+ return span ? kOwned : kNotOwned;
+ }
+
+ virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* 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 < kNumClasses; ++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[kNumClasses];
+ 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 < kNumClasses; ++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);
+ }
+
+ // 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<size_t>::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];
+ v->push_back(i);
+
+ i.type = kPageHeapUnmappedType;
+ i.total_bytes_free = (s << kPageShift) * small.returned_length[s];
+ v->push_back(i);
+ }
+ }
+};
+
+// 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) {
+#ifdef HAVE_TLS // this is true if the cc/ld/libc combo support TLS
+ // Check whether the kernel also supports TLS (needs to happen at runtime)
+ tcmalloc::CheckIfKernelSupportsTLS();
+#endif
+ 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 = 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<uintptr_t>(ptr) >> kPageShift;
+ size_t cached_value = Static::pageheap()->GetSizeClassIfCached(p);
+ return cached_value == 0 ||
+ cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass;
+}
+
+static inline void* CheckMallocResult(void *result) {
+ ASSERT(result == NULL || CheckCachedSizeClass(result));
+ MarkAllocatedRegion(result);
+ return result;
+}
+
+static inline void* SpanToMallocResult(Span *span) {
+ Static::pageheap()->CacheSizeClass(span->start, 0);
+ return
+ CheckMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
+}
+
+static void* DoSampledAllocation(size_t size) {
+ // 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 (span == NULL) {
+ return NULL;
+ }
+
+ // Allocate stack trace
+ StackTrace *stack = Static::stacktrace_allocator()->New();
+ if (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);
+}
+
+namespace {
+
+// Copy of FLAGS_tcmalloc_large_alloc_report_threshold with
+// automatic increases factored in.
+static int64_t large_alloc_threshold =
+ (kPageSize > FLAGS_tcmalloc_large_alloc_report_threshold
+ ? kPageSize : FLAGS_tcmalloc_large_alloc_report_threshold);
+
+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<uint64>(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));
+}
+
+inline void* cpp_alloc(size_t size, bool nothrow);
+inline void* do_malloc(size_t size);
+
+// TODO(willchan): Investigate whether or not inlining this much is harmful to
+// performance.
+// This is equivalent to do_malloc() except when tc_new_mode is set to true.
+// Otherwise, it will run the std::new_handler if set.
+inline void* do_malloc_or_cpp_alloc(size_t size) {
+ return tc_new_mode ? cpp_alloc(size, true) : do_malloc(size);
+}
+
+void* cpp_memalign(size_t align, size_t size);
+void* do_memalign(size_t align, size_t size);
+
+inline void* do_memalign_or_cpp_memalign(size_t align, size_t size) {
+ return tc_new_mode ? cpp_memalign(align, size) : do_memalign(align, size);
+}
+
+// Must be called with the page lock held.
+inline bool should_report_large(Length num_pages) {
+ 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;
+ }
+ return false;
+}
+
+// Helper for do_malloc().
+inline void* do_malloc_pages(ThreadCache* heap, size_t size) {
+ void* result;
+ bool report_large;
+
+ Length num_pages = tcmalloc::pages(size);
+ size = num_pages << kPageShift;
+
+ // Chromium profiling. Measurements in March 2013 suggest this
+ // imposes a small enough runtime cost that there's no reason to
+ // try to optimize it.
+ heap->AddToByteAllocatedTotal(size);
+
+ if ((FLAGS_tcmalloc_sample_parameter > 0) && 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 = (span == NULL ? NULL : SpanToMallocResult(span));
+ report_large = should_report_large(num_pages);
+ }
+
+ if (report_large) {
+ ReportLargeAlloc(num_pages, result);
+ }
+ return result;
+}
+
+inline void* do_malloc(size_t size) {
+ AddRoomForMark(&size);
+
+ void* ret = NULL;
+
+ // The following call forces module initialization
+ ThreadCache* heap = ThreadCache::GetCache();
+ if (size <= kMaxSize && IsAllocSizePermitted(size)) {
+ size_t cl = Static::sizemap()->SizeClass(size);
+ size = Static::sizemap()->class_to_size(cl);
+
+ // Chromium profiling. Measurements in March 2013 suggest this
+ // imposes a small enough runtime cost that there's no reason to
+ // try to optimize it.
+ heap->AddToByteAllocatedTotal(size);
+
+ if ((FLAGS_tcmalloc_sample_parameter > 0) &&
+ heap->SampleAllocation(size)) {
+ ret = DoSampledAllocation(size);
+ MarkAllocatedRegion(ret);
+ } else {
+ // The common case, and also the simplest. This just pops the
+ // size-appropriate freelist, after replenishing it if it's empty.
+ ret = CheckMallocResult(heap->Allocate(size, cl));
+ }
+ } else if (IsAllocSizePermitted(size)) {
+ ret = do_malloc_pages(heap, size);
+ MarkAllocatedRegion(ret);
+ }
+ if (ret == NULL) errno = ENOMEM;
+ ASSERT(IsAllocSizePermitted(size) || ret == NULL);
+ return ret;
+}
+
+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, size);
+ }
+ return result;
+}
+
+static inline ThreadCache* GetCacheIfPresent() {
+ void* const p = ThreadCache::GetCacheIfPresent();
+ return reinterpret_cast<ThreadCache*>(p);
+}
+
+// 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.
+inline void do_free_with_callback(void* ptr, void (*invalid_free_fn)(void*)) {
+ if (ptr == NULL) return;
+ if (Static::pageheap() == NULL) {
+ // We called free() before malloc(). This can occur if the
+ // (system) malloc() is called before tcmalloc is loaded, and then
+ // free() is called after tcmalloc is loaded (and tc_free has
+ // replaced free), but before the global constructor has run that
+ // sets up the tcmalloc data structures.
+ (*invalid_free_fn)(ptr); // Decide how to handle the bad free request
+ return;
+ }
+ const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
+ Span* span = NULL;
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+
+ if (cl == 0) {
+ span = Static::pageheap()->GetDescriptor(p);
+ if (!span) {
+ // span can be NULL because the pointer passed in is 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.
+ (*invalid_free_fn)(ptr); // Decide how to handle the bad free request
+ return;
+ }
+ cl = span->sizeclass;
+ Static::pageheap()->CacheSizeClass(p, cl);
+ }
+ if (cl == 0) {
+ // Check to see if the object is in use.
+ CHECK_CONDITION_PRINT(span->location == Span::IN_USE,
+ "Object was not in-use");
+
+ CHECK_CONDITION_PRINT(
+ span->start << kPageShift == reinterpret_cast<uintptr_t>(ptr),
+ "Pointer is not pointing to the start of a span");
+ }
+ ValidateAllocatedRegion(ptr, cl);
+
+ if (cl != 0) {
+ ASSERT(!Static::pageheap()->GetDescriptor(p)->sample);
+ ThreadCache* heap = GetCacheIfPresent();
+ if (heap != NULL) {
+ heap->Deallocate(ptr, cl);
+ } else {
+ // Delete directly into central cache
+ tcmalloc::FL_Init(ptr);
+ Static::central_cache()[cl].InsertRange(ptr, ptr, 1);
+ }
+ } else {
+ SpinLockHolder h(Static::pageheap_lock());
+ ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
+ ASSERT(span != NULL && span->start == p);
+ if (span->sample) {
+ StackTrace* st = reinterpret_cast<StackTrace*>(span->objects);
+ tcmalloc::DLL_Remove(span);
+ Static::stacktrace_allocator()->Delete(st);
+ span->objects = NULL;
+ }
+ Static::pageheap()->Delete(span);
+ }
+}
+
+// The default "do_free" that uses the default callback.
+inline void do_free(void* ptr) {
+ return do_free_with_callback(ptr, &InvalidFree);
+}
+
+// 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<uintptr_t>(ptr) >> kPageShift;
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+ if (cl != 0) {
+ return Static::sizemap()->ByteSizeForClass(cl);
+ } else {
+ const Span *span = Static::pageheap()->GetDescriptor(p);
+ if (span == NULL) { // means we do not own this memory
+ return (*invalid_getsize_fn)(ptr);
+ } else if (span->sizeclass != 0) {
+ Static::pageheap()->CacheSizeClass(p, span->sizeclass);
+ return Static::sizemap()->ByteSizeForClass(span->sizeclass);
+ } else {
+ 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.
+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*)) {
+ AddRoomForMark(&new_size);
+ // 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<size_t>::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 / 2;
+ 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);
+ }
+ ExcludeMarkFromSize(&new_size); // do_malloc will add space if needed.
+ 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 (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);
+ return new_ptr;
+ } else {
+ // We still need to call hooks to report the updated size:
+ MallocHook::InvokeDeleteHook(old_ptr);
+ ExcludeMarkFromSize(&new_size);
+ MallocHook::InvokeNewHook(old_ptr, new_size);
+ return old_ptr;
+ }
+}
+
+inline void* do_realloc(void* old_ptr, size_t new_size) {
+ return do_realloc_with_callback(old_ptr, new_size,
+ &InvalidFree, &InvalidGetSizeForRealloc);
+}
+
+// For use by exported routines below that want specific alignments
+//
+// Note: this code can be slow for alignments > 16, and can
+// significantly fragment memory. The expectation is that
+// memalign/posix_memalign/valloc/pvalloc will not be invoked very
+// often. This requirement simplifies our implementation and allows
+// us to tune for expected allocation patterns.
+void* do_memalign(size_t align, size_t size) {
+ ASSERT((align & (align - 1)) == 0);
+ ASSERT(align > 0);
+ // Marked in CheckMallocResult(), which is also inside SpanToMallocResult().
+ AddRoomForMark(&size);
+ if (size + align < size) return NULL; // Overflow
+
+ // Fall back to malloc if we would already align this memory access properly.
+ if (align <= AlignmentForSize(size)) {
+ void* p = do_malloc(size);
+ ASSERT((reinterpret_cast<uintptr_t>(p) % align) == 0);
+ return p;
+ }
+
+ if (Static::pageheap() == NULL) ThreadCache::InitModule();
+
+ // Allocate at least one byte to avoid boundary conditions below
+ if (size == 0) size = 1;
+
+ if (size <= kMaxSize && align < kPageSize) {
+ // Search through acceptable size classes looking for one with
+ // enough alignment. This depends on the fact that
+ // InitSizeClasses() currently produces several size classes that
+ // are aligned at powers of two. We will waste time and space if
+ // we miss in the size class array, but that is deemed acceptable
+ // since memalign() should be used rarely.
+ int cl = Static::sizemap()->SizeClass(size);
+ while (cl < kNumClasses &&
+ ((Static::sizemap()->class_to_size(cl) & (align - 1)) != 0)) {
+ cl++;
+ }
+ if (cl < kNumClasses) {
+ ThreadCache* heap = ThreadCache::GetCache();
+ size = Static::sizemap()->class_to_size(cl);
+ return CheckMallocResult(heap->Allocate(size, cl));
+ }
+ }
+
+ // We will allocate directly from the page heap
+ SpinLockHolder h(Static::pageheap_lock());
+
+ if (align <= kPageSize) {
+ // Any page-level allocation will be fine
+ // TODO: We could put the rest of this page in the appropriate
+ // TODO: cache but it does not seem worth it.
+ Span* span = Static::pageheap()->New(tcmalloc::pages(size));
+ return span == NULL ? NULL : SpanToMallocResult(span);
+ }
+
+ // Allocate extra pages and carve off an aligned portion
+ const Length alloc = tcmalloc::pages(size + align);
+ Span* span = Static::pageheap()->New(alloc);
+ if (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<int>(stats.pageheap.system_bytes);
+ info.fsmblks = static_cast<int>(stats.thread_bytes
+ + stats.central_bytes
+ + stats.transfer_bytes);
+ info.fordblks = static_cast<int>(stats.pageheap.free_bytes +
+ stats.pageheap.unmapped_bytes);
+ info.uordblks = static_cast<int>(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
+
+static SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED);
+
+inline void* cpp_alloc(size_t size, bool nothrow) {
+ for (;;) {
+ void* p = do_malloc(size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ 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 p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+void* cpp_memalign(size_t align, size_t size) {
+ for (;;) {
+ void* p = do_memalign(align, size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh)
+ return 0;
+
+ // 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&) {
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+} // end unnamed namespace
+
+// As promised, the definition of this function, declared above.
+size_t TCMallocImplementation::GetAllocatedSize(const void* ptr) {
+ // Chromium workaround for third-party code calling tc_malloc_size(NULL), see
+ // http://code.google.com/p/chromium/issues/detail?id=118087
+ // Note: this is consistent with GLIBC's implementation of
+ // malloc_usable_size(NULL).
+ if (ptr == NULL)
+ return 0;
+ ASSERT(TCMallocImplementation::GetOwnership(ptr)
+ != TCMallocImplementation::kNotOwned);
+ return ExcludeSpaceForMark(
+ 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) __THROW {
+ 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) __THROW {
+ int old_mode = tc_new_mode;
+ tc_new_mode = flag;
+ return old_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.
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
+ void* result = do_malloc_or_cpp_alloc(size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ do_free(ptr);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n,
+ size_t elem_size) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ do_free(ptr);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_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(old_ptr);
+ return NULL;
+ }
+ return do_realloc(old_ptr, new_size);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
+ void* p = cpp_alloc(size, false);
+ // We keep this next instruction out of cpp_alloc for a reason: when
+ // it's in, and new just calls cpp_alloc, the optimizer may fold the
+ // new call into cpp_alloc, which messes up our whole section-based
+ // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
+ // isn't the last thing this fn calls, and prevents the folding.
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
+ void* p = cpp_alloc(size, false);
+ // We keep this next instruction out of cpp_alloc for a reason: when
+ // it's in, and new just calls cpp_alloc, the optimizer may fold the
+ // new call into cpp_alloc, which messes up our whole section-based
+ // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
+ // isn't the last thing this fn calls, and prevents the folding.
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
+ __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align,
+ size_t size) __THROW {
+ void* result = do_memalign_or_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(
+ void** result_ptr, size_t align, size_t size) __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
+
+ void* result = do_memalign_or_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ if (result == NULL) {
+ return ENOMEM;
+ } else {
+ *result_ptr = result;
+ return 0;
+ }
+}
+
+static size_t pagesize = 0;
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
+ // Allocate page-aligned object of length >= size bytes
+ if (pagesize == 0) pagesize = getpagesize();
+ void* result = do_memalign_or_cpp_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
+ // 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);
+ void* result = do_memalign_or_cpp_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
+ do_malloc_stats();
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
+ return do_mallopt(cmd, value);
+}
+
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
+ return do_mallinfo();
+}
+#endif
+
+extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
+ return MallocExtension::instance()->GetAllocatedSize(ptr);
+}
+
+#endif // TCMALLOC_USING_DEBUGALLOCATION
+
+// --- Validation implementation with an extra mark ----------------------------
+// We will put a mark at the extreme end of each allocation block. We make
+// sure that we always allocate enough "extra memory" that we can fit in the
+// mark, and still provide the requested usable region. If ever that mark is
+// not as expected, then we know that the user is corrupting memory beyond their
+// request size, or that they have called free a second time without having
+// the memory allocated (again). This allows us to spot most double free()s,
+// but some can "slip by" or confuse our logic if the caller reallocates memory
+// (for a second use) before performing an evil double-free of a first
+// allocation
+
+// This code can be optimized, but for now, it is written to be most easily
+// understood, and flexible (since it is evolving a bit). Potential
+// optimizations include using other calculated data, such as class size, or
+// allocation size, which is known in the code above, but then is recalculated
+// below. Another potential optimization would be careful manual inlining of
+// code, but I *think* that the compile will probably do this for me, and I've
+// been careful to avoid aliasing issues that might make a compiler back-off.
+
+// Evolution includes experimenting with different marks, to minimize the chance
+// that a mark would be misunderstood (missed corruption). The marks are meant
+// to be hashed encoding of the location, so that they can't be copied over a
+// different region (by accident) without being detected (most of the time).
+
+// Enable the following define to turn on all the TCMalloc checking.
+// It will cost about 2% in performance, but it will catch double frees (most of
+// the time), and will often catch allocated-buffer overrun errors. This
+// validation is only active when TCMalloc is used as the allocator.
+#ifndef NDEBUG
+#define TCMALLOC_VALIDATION
+#endif
+
+#if !defined(TCMALLOC_VALIDATION)
+
+static size_t ExcludeSpaceForMark(size_t size) { return size; }
+static void AddRoomForMark(size_t* size) {}
+static void ExcludeMarkFromSize(size_t* new_size) {}
+static void MarkAllocatedRegion(void* ptr) {}
+static void ValidateAllocatedRegion(void* ptr, size_t cl) {}
+
+#else // TCMALLOC_VALIDATION
+
+static void DieFromDoubleFree() {
+ Log(kCrash, __FILE__, __LINE__, "Attempt to double free");
+}
+
+static void DieFromMemoryCorruption() {
+ Log(kCrash, __FILE__, __LINE__, "Memory corrupted");
+}
+
+// We can either do byte marking, or whole word marking based on the following
+// define. char is as small as we can get, and word marking probably provides
+// more than enough bits that we won't miss a corruption. Any sized integral
+// type can be used, but we just define two examples.
+
+// #define TCMALLOC_SMALL_VALIDATION
+#if defined (TCMALLOC_SMALL_VALIDATION)
+
+typedef char MarkType; // char saves memory... int is more complete.
+static const MarkType kAllocationMarkMask = static_cast<MarkType>(0x36);
+
+#else
+
+typedef int MarkType; // char saves memory... int is more complete.
+static const MarkType kAllocationMarkMask = static_cast<MarkType>(0xE1AB9536);
+
+#endif
+
+// TODO(jar): See if use of reference rather than pointer gets better inlining,
+// or if macro is needed. My fear is that taking address map preclude register
+// allocation :-(.
+inline static void AddRoomForMark(size_t* size) {
+ *size += sizeof(kAllocationMarkMask);
+}
+
+inline static void ExcludeMarkFromSize(size_t* new_size) {
+ *new_size -= sizeof(kAllocationMarkMask);
+}
+
+inline static size_t ExcludeSpaceForMark(size_t size) {
+ return size - sizeof(kAllocationMarkMask); // Lie about size when asked.
+}
+
+inline static MarkType* GetMarkLocation(void* ptr) {
+ size_t size = GetSizeWithCallback(ptr, &InvalidGetAllocatedSize);
+ ASSERT(size % sizeof(kAllocationMarkMask) == 0);
+ size_t last_index = (size / sizeof(kAllocationMarkMask)) - 1;
+ return static_cast<MarkType*>(ptr) + last_index;
+}
+
+// We hash in the mark location plus the pointer so that we effectively mix in
+// the size of the block. This means that if a span is used for different sizes
+// that the mark will be different. It would be good to hash in the size (which
+// we effectively get by using both mark location and pointer), but even better
+// would be to also include the class, as it concisely contains the entropy
+// found in the size (when we don't have large allocation), and there is less
+// risk of losing those bits to truncation. It would probably be good to combine
+// the high bits of size (capturing info about large blocks) with the class
+// (which is a 6 bit number).
+inline static MarkType GetMarkValue(void* ptr, MarkType* mark) {
+ void* ptr2 = static_cast<void*>(mark);
+ size_t offset1 = static_cast<char*>(ptr) - static_cast<char*>(NULL);
+ size_t offset2 = static_cast<char*>(ptr2) - static_cast<char*>(NULL);
+ static const int kInvariantBits = 2;
+ ASSERT((offset1 >> kInvariantBits) << kInvariantBits == offset1);
+ // Note: low bits of both offsets are invariants due to alignment. High bits
+ // of both offsets are the same (unless we have a large allocation). Avoid
+ // XORing high bits together, as they will cancel for most small allocations.
+
+ MarkType ret = kAllocationMarkMask;
+ // Using a little shift, we can safely XOR together both offsets.
+ ret ^= static_cast<MarkType>(offset1 >> kInvariantBits) ^
+ static_cast<MarkType>(offset2);
+ if (sizeof(ret) == 1) {
+ // Try to bring some high level bits into the mix.
+ ret += static_cast<MarkType>(offset1 >> 8) ^
+ static_cast<MarkType>(offset1 >> 16) ^
+ static_cast<MarkType>(offset1 >> 24) ;
+ }
+ // Hash in high bits on a 64 bit architecture.
+ if (sizeof(size_t) == 8 && sizeof(ret) == 4)
+ ret += offset1 >> 16;
+ if (ret == 0)
+ ret = kAllocationMarkMask; // Avoid common pattern of all zeros.
+ return ret;
+}
+
+// TODO(jar): Use the passed in TCmalloc Class Index to calculate mark location
+// faster. The current implementation calls general functions, which have to
+// recalculate this in order to get the Class Size. This is a slow and wasteful
+// recomputation... but it is much more readable this way (for now).
+static void ValidateAllocatedRegion(void* ptr, size_t cl) {
+ if (ptr == NULL) return;
+ MarkType* mark = GetMarkLocation(ptr);
+ MarkType allocated_mark = GetMarkValue(ptr, mark);
+ MarkType current_mark = *mark;
+
+ if (current_mark == ~allocated_mark)
+ DieFromDoubleFree();
+ if (current_mark != allocated_mark)
+ DieFromMemoryCorruption();
+#ifndef NDEBUG
+ // In debug mode, copy the mark into all the free'd region.
+ size_t class_size = static_cast<size_t>(reinterpret_cast<char*>(mark) -
+ reinterpret_cast<char*>(ptr));
+ memset(ptr, static_cast<char>(0x36), class_size);
+#endif
+ *mark = ~allocated_mark; // Distinctively not allocated.
+}
+
+static void MarkAllocatedRegion(void* ptr) {
+ if (ptr == NULL) return;
+ MarkType* mark = GetMarkLocation(ptr);
+ *mark = GetMarkValue(ptr, mark);
+}
+
+#endif // TCMALLOC_VALIDATION
diff --git a/chromium/third_party/tcmalloc/chromium/src/tcmalloc.h b/chromium/third_party/tcmalloc/chromium/src/tcmalloc.h
new file mode 100644
index 00000000000..3b0fe7cadf8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/tcmalloc.h
@@ -0,0 +1,69 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 600 // for posix_memalign
+#endif
+#include <stdlib.h> // for posix_memalign
+// FreeBSD has malloc.h, but complains if you use it
+#if defined(HAVE_MALLOC_H) && !defined(__FreeBSD__)
+#include <malloc.h> // 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_CFREE_SYMBOL
+extern "C" void cfree(void* ptr) __THROW;
+#endif
+#if !HAVE_POSIX_MEMALIGN_SYMBOL
+extern "C" int posix_memalign(void** ptr, size_t align, size_t size) __THROW;
+#endif
+#if !HAVE_MEMALIGN_SYMBOL
+extern "C" void* memalign(size_t __alignment, size_t __size) __THROW;
+#endif
+#if !HAVE_VALLOC_SYMBOL
+extern "C" void* valloc(size_t __size) __THROW;
+#endif
+#if !HAVE_PVALLOC_SYMBOL
+extern "C" void* pvalloc(size_t __size) __THROW;
+#endif
diff --git a/chromium/third_party/tcmalloc/chromium/src/tcmalloc_guard.h b/chromium/third_party/tcmalloc/chromium/src/tcmalloc_guard.h
new file mode 100644
index 00000000000..7874dadaea9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/tcmalloc_guard.h
@@ -0,0 +1,48 @@
+// 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/chromium/third_party/tcmalloc/chromium/src/thread_cache.cc b/chromium/third_party/tcmalloc/chromium/src/thread_cache.cc
new file mode 100644
index 00000000000..1ad0f6d66d6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/thread_cache.cc
@@ -0,0 +1,514 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#include "thread_cache.h"
+#include <errno.h>
+#include <string.h> // for memcpy
+#include <algorithm> // for max, min
+#include "base/commandlineflags.h" // for SpinLockHolder
+#include "base/spinlock.h" // for SpinLockHolder
+#include "central_freelist.h" // for CentralFreeListPadded
+#include "maybe_threads.h"
+
+using std::min;
+using std::max;
+
+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> threadcache_allocator;
+ThreadCache* ThreadCache::thread_heaps_ = NULL;
+int ThreadCache::thread_heap_count_ = 0;
+ThreadCache* ThreadCache::next_memory_steal_ = NULL;
+#ifdef HAVE_TLS
+__thread ThreadCache* ThreadCache::threadlocal_heap_
+// See comments in thread_cache.h about this. Bug here:
+// http://code.google.com/p/chromium/issues/detail?id=124489
+#if defined(HAVE___ATTRIBUTE__) && !defined(PGO_GENERATE)
+ __attribute__ ((tls_model ("initial-exec")))
+# endif
+ ;
+#endif
+bool ThreadCache::tsd_inited_ = false;
+pthread_key_t ThreadCache::heap_key_;
+
+#if defined(HAVE_TLS)
+bool kernel_supports_tls = false; // be conservative
+# if defined(_WIN32) // windows has supported TLS since winnt, I think.
+ void CheckIfKernelSupportsTLS() {
+ kernel_supports_tls = true;
+ }
+# elif !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS
+ void CheckIfKernelSupportsTLS() {
+ kernel_supports_tls = false;
+ }
+# else
+# include <sys/utsname.h> // DECL_UNAME checked for <sys/utsname.h> too
+ void CheckIfKernelSupportsTLS() {
+ struct utsname buf;
+ if (uname(&buf) < 0) { // should be impossible
+ Log(kLog, __FILE__, __LINE__,
+ "uname failed assuming no TLS support (errno)", errno);
+ kernel_supports_tls = false;
+ } else if (strcasecmp(buf.sysname, "linux") == 0) {
+ // The linux case: the first kernel to support TLS was 2.6.0
+ if (buf.release[0] < '2' && buf.release[1] == '.') // 0.x or 1.x
+ kernel_supports_tls = false;
+ else if (buf.release[0] == '2' && buf.release[1] == '.' &&
+ buf.release[2] >= '0' && buf.release[2] < '6' &&
+ buf.release[3] == '.') // 2.0 - 2.5
+ kernel_supports_tls = false;
+ else
+ kernel_supports_tls = true;
+ } else if (strcasecmp(buf.sysname, "CYGWIN_NT-6.1-WOW64") == 0) {
+ // In my testing, this version of cygwin, at least, would hang
+ // when using TLS.
+ kernel_supports_tls = false;
+ } else { // some other kernel, we'll be optimisitic
+ kernel_supports_tls = true;
+ }
+ // TODO(csilvers): VLOG(1) the tls status once we support RAW_VLOG
+ }
+# endif // HAVE_DECL_UNAME
+#endif // HAVE_TLS
+
+void ThreadCache::Init(pthread_t tid) {
+ size_ = 0;
+ total_bytes_allocated_ = 0;
+
+ max_size_ = 0;
+ IncreaseCacheLimitLocked();
+ if (max_size_ == 0) {
+ // There isn't enough memory to go around. Just give the minimum to
+ // this thread.
+ max_size_ = 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 (size_t cl = 0; cl < kNumClasses; ++cl) {
+ list_[cl].Init();
+ }
+
+ 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 (int cl = 0; cl < kNumClasses; ++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(size_t cl, size_t byte_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<int>(list->max_length(), batch_size);
+ void *start, *end;
+ int fetch_count = Static::central_cache()[cl].RemoveRange(
+ &start, &end, num_to_move);
+
+ ASSERT((start == NULL) == (fetch_count == 0));
+ if (--fetch_count >= 0) {
+ size_ += byte_size * fetch_count;
+ // Pop the top of the list and add the rest to the freelist.
+ void *second = start;
+ start = FL_Pop(&second);
+ list->PushRange(fetch_count, second, 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<int>(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, size_t cl) {
+ 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);
+ }
+ }
+}
+
+// Remove some objects of class "cl" from thread heap and add to central cache
+void ThreadCache::ReleaseToCentralCache(FreeList* src, size_t 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.
+ //int64 start = CycleClock::Now();
+ for (int cl = 0; cl < kNumClasses; 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<int>(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;
+ 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_->max_size_ -= kStealAmount;
+ max_size_ += kStealAmount;
+
+ next_memory_steal_ = next_memory_steal_->next_;
+ return;
+ }
+}
+
+int ThreadCache::GetSamplePeriod() {
+ return sampler_.GetSamplePeriod();
+}
+
+// static
+unsigned int ThreadCache::GetBytesAllocatedOnCurrentThread() {
+ return ThreadCache::GetThreadHeap()->GetTotalBytesAllocated();
+}
+
+void ThreadCache::InitModule() {
+ SpinLockHolder h(Static::pageheap_lock());
+ if (!phinited) {
+ Static::InitStaticVars();
+ threadcache_allocator.Init();
+ phinited = 1;
+ }
+}
+
+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() {
+ // Initialize per-thread data if necessary
+ ThreadCache* heap = NULL;
+ {
+ 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.
+ 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_heap_ = heap;
+#endif
+ heap->in_setspecific_ = false;
+ }
+ 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_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::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_heap_ = NULL;
+#endif
+ DeleteCache(reinterpret_cast<ThreadCache*>(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<double>(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->max_size_ = static_cast<size_t>(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 < kNumClasses; ++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/chromium/third_party/tcmalloc/chromium/src/thread_cache.h b/chromium/third_party/tcmalloc/chromium/src/thread_cache.h
new file mode 100644
index 00000000000..221cacb8eb3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/thread_cache.h
@@ -0,0 +1,430 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_THREAD_CACHE_H_
+#define TCMALLOC_THREAD_CACHE_H_
+
+#include <config.h>
+#ifdef HAVE_PTHREAD
+#include <pthread.h> // for pthread_t, pthread_key_t
+#endif
+#include <stddef.h> // for size_t, NULL
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint32_t, uint64_t
+#endif
+#include <sys/types.h> // for ssize_t
+#include "common.h" // for SizeMap, kMaxSize, etc
+#include "free_list.h" // for FL_Pop, FL_PopRange, etc
+#include "internal_logging.h" // for ASSERT, etc
+#include "maybe_threads.h"
+#include "page_heap_allocator.h" // for PageHeapAllocator
+#include "sampler.h" // for Sampler
+#include "static_vars.h" // for Static
+
+namespace tcmalloc {
+
+// Even if we have support for thread-local storage in the compiler
+// and linker, the OS may not support it. We need to check that at
+// runtime. Right now, we have to keep a manual set of "bad" OSes.
+#if defined(HAVE_TLS)
+extern bool kernel_supports_tls; // defined in thread_cache.cc
+void CheckIfKernelSupportsTLS();
+inline bool KernelSupportsTLS() {
+ return kernel_supports_tls;
+}
+#endif // HAVE_TLS
+
+//-------------------------------------------------------------------
+// Data kept per thread
+//-------------------------------------------------------------------
+
+class ThreadCache {
+ public:
+ // All ThreadCache objects are kept in a linked list (for stats collection)
+ ThreadCache* next_;
+ ThreadCache* prev_;
+
+ void Init(pthread_t tid);
+ void Cleanup();
+
+ // Accessors (mostly just for printing stats)
+ int freelist_length(size_t 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, size_t cl);
+ void Deallocate(void* ptr, size_t size_class);
+
+ void Scavenge();
+
+ int GetSamplePeriod();
+
+ // Record allocation of "k" bytes. Return true iff allocation
+ // should be sampled
+ bool SampleAllocation(size_t k);
+
+ // Record additional bytes allocated.
+ void AddToByteAllocatedTotal(size_t k) { total_bytes_allocated_ += k; }
+
+ // Return the total number of bytes allocated from this heap. The value will
+ // wrap when there is an overflow, and so only the differences between two
+ // values should be relied on (and even then, modulo 2^32).
+ uint32 GetTotalBytesAllocated() const;
+
+ // On the current thread, return GetTotalBytesAllocated().
+ static uint32 GetBytesAllocatedOnCurrentThread();
+
+ static void InitModule();
+ static void InitTSD();
+ static ThreadCache* GetThreadHeap();
+ static ThreadCache* GetCache();
+ static ThreadCache* GetCacheIfPresent();
+ static ThreadCache* CreateCacheIfNecessary();
+ static void BecomeIdle();
+
+ // Return the number of thread heaps in use.
+ static inline int HeapsInUse();
+
+ // Writes to total_bytes the total number of bytes used by all thread heaps.
+ // class_count must be an array of size kNumClasses. Writes the number of
+ // items on the corresponding freelist. class_count may be NULL.
+ // The storage of both parameters must be zero intialized.
+ // 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
+
+ public:
+ void Init() {
+ list_ = NULL;
+ length_ = 0;
+ lowater_ = 0;
+ max_length_ = 1;
+ length_overages_ = 0;
+ }
+
+ // Return current length of list
+ size_t length() const {
+ return length_;
+ }
+
+ // 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_; }
+
+ void Push(void* ptr) {
+ FL_Push(&list_, ptr);
+ length_++;
+ }
+
+ void* Pop() {
+ ASSERT(list_ != NULL);
+ length_--;
+ if (length_ < lowater_) lowater_ = length_;
+ return FL_Pop(&list_);
+ }
+
+ void* Next() {
+ if (list_ == NULL) return NULL;
+ return FL_Next(list_);
+ }
+
+ void PushRange(int N, void *start, void *end) {
+ FL_PushRange(&list_, start, end);
+ length_ += N;
+ }
+
+ void PopRange(int N, void **start, void **end) {
+ FL_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(size_t cl, size_t byte_size);
+
+ // 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, size_t cl);
+
+ // Releases N items from this thread cache.
+ void ReleaseToCentralCache(FreeList* src, size_t cl, int N);
+
+ // 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
+ static __thread ThreadCache* threadlocal_heap_
+ // This code links against pyautolib.so, which causes dlopen() on that shared
+ // object to fail when -fprofile-generate is used with it. Ideally
+ // pyautolib.so should not link against this code. There is a bug filed for
+ // that:
+ // http://code.google.com/p/chromium/issues/detail?id=124489
+ // For now the workaround is to pass in -DPGO_GENERATE when building Chrome
+ // for instrumentation (-fprofile-generate).
+ // For all non-instrumentation builds, this define will not be set and the
+ // performance benefit of "intial-exec" will be achieved.
+#if defined(HAVE___ATTRIBUTE__) && !defined(PGO_GENERATE)
+ __attribute__ ((tls_model ("initial-exec")))
+# endif
+ ;
+#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 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.
+
+ size_t size_; // Combined size of data
+ size_t max_size_; // size_ > max_size_ --> Scavenge()
+
+ // The following is the tally of bytes allocated on a thread as a response to
+ // any flavor of malloc() call. The aggegated amount includes all padding to
+ // the smallest class that can hold the request, or to the nearest whole page
+ // when a large allocation is made without using a class. This sum is
+ // currently used for Chromium profiling, where tallies are kept of the amount
+ // of memory allocated during the running of each task on each thread.
+ uint32 total_bytes_allocated_; // Total, modulo 2^32.
+
+ // We sample allocations, biased by the size of the allocation
+ Sampler sampler_; // A sampler
+
+ FreeList list_[kNumClasses]; // Array indexed by size-class
+
+ 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();
+
+ // 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> threadcache_allocator;
+
+inline int ThreadCache::HeapsInUse() {
+ return threadcache_allocator.inuse();
+}
+
+inline bool ThreadCache::SampleAllocation(size_t k) {
+ return sampler_.SampleAllocation(k);
+}
+
+inline uint32 ThreadCache::GetTotalBytesAllocated() const {
+ return total_bytes_allocated_;
+}
+
+inline void* ThreadCache::Allocate(size_t size, size_t cl) {
+ ASSERT(size <= kMaxSize);
+ ASSERT(size == Static::sizemap()->ByteSizeForClass(cl));
+
+ FreeList* list = &list_[cl];
+ if (list->empty()) {
+ return FetchFromCentralCache(cl, size);
+ }
+ size_ -= size;
+ return list->Pop();
+}
+
+inline void ThreadCache::Deallocate(void* ptr, size_t cl) {
+ FreeList* list = &list_[cl];
+ size_ += Static::sizemap()->ByteSizeForClass(cl);
+ ssize_t size_headroom = max_size_ - size_ - 1;
+
+ // 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());
+
+ list->Push(ptr);
+ ssize_t list_headroom =
+ static_cast<ssize_t>(list->max_length()) - list->length();
+
+ // There are two relatively uncommon things that require further work.
+ // In the common case we're done, and in that case we need a single branch
+ // because of the bitwise-or trick that follows.
+ if ((list_headroom | size_headroom) < 0) {
+ if (list_headroom < 0) {
+ ListTooLong(list, cl);
+ }
+ if (size_ >= max_size_) Scavenge();
+ }
+}
+
+inline ThreadCache* ThreadCache::GetThreadHeap() {
+#ifdef HAVE_TLS
+ // __thread is faster, but only when the kernel supports it
+ if (KernelSupportsTLS())
+ return threadlocal_heap_;
+#endif
+ return reinterpret_cast<ThreadCache *>(
+ perftools_pthread_getspecific(heap_key_));
+}
+
+inline ThreadCache* ThreadCache::GetCache() {
+ ThreadCache* ptr = NULL;
+ if (!tsd_inited_) {
+ InitModule();
+ } else {
+ ptr = GetThreadHeap();
+ }
+ 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() {
+ if (!tsd_inited_) return NULL;
+ return GetThreadHeap();
+}
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_THREAD_CACHE_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/type_profiler_map.cc b/chromium/third_party/tcmalloc/chromium/src/type_profiler_map.cc
new file mode 100644
index 00000000000..a2f21f82bab
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/type_profiler_map.cc
@@ -0,0 +1,112 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(TYPE_PROFILING)
+
+#include <config.h>
+
+#include <new>
+#include <stddef.h>
+#include <typeinfo>
+
+#include <gperftools/type_profiler_map.h>
+
+#include "addressmap-inl.h"
+#include "base/logging.h"
+#include "base/low_level_alloc.h"
+#include "base/spinlock.h"
+#include "tcmalloc_guard.h"
+
+namespace {
+
+const TCMallocGuard tcmalloc_initializer;
+
+//----------------------------------------------------------------------
+// A struct to store size and type_info of an object
+//----------------------------------------------------------------------
+
+struct ObjectInfo {
+ public:
+ ObjectInfo(): size(0), type(NULL) {}
+ ObjectInfo(size_t size_arg, const std::type_info* type_arg)
+ : size(size_arg),
+ type(type_arg) {
+ }
+
+ size_t size;
+ const std::type_info* type;
+};
+
+//----------------------------------------------------------------------
+// Locking
+//----------------------------------------------------------------------
+
+SpinLock g_type_profiler_lock(SpinLock::LINKER_INITIALIZED);
+
+//----------------------------------------------------------------------
+// Simple allocator for type_info map's internal memory
+//----------------------------------------------------------------------
+
+LowLevelAlloc::Arena* g_type_profiler_map_memory = NULL;
+
+void* TypeProfilerMalloc(size_t bytes) {
+ return LowLevelAlloc::AllocWithArena(bytes, g_type_profiler_map_memory);
+}
+
+void TypeProfilerFree(void* p) {
+ LowLevelAlloc::Free(p);
+}
+
+//----------------------------------------------------------------------
+// Profiling control/state data
+//----------------------------------------------------------------------
+
+AddressMap<ObjectInfo>* g_type_profiler_map = NULL;
+
+//----------------------------------------------------------------------
+// Manage type_info map
+//----------------------------------------------------------------------
+
+void InitializeTypeProfilerMemory() {
+ if (g_type_profiler_map_memory != NULL) {
+ RAW_DCHECK(g_type_profiler_map != NULL, "TypeProfilerMap is NULL");
+ return;
+ }
+
+ g_type_profiler_map_memory =
+ LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena());
+
+ g_type_profiler_map =
+ new(TypeProfilerMalloc(sizeof(*g_type_profiler_map)))
+ AddressMap<ObjectInfo>(TypeProfilerMalloc, TypeProfilerFree);
+}
+
+} // namespace
+
+void InsertType(void* address, size_t size, const std::type_info& type) {
+ SpinLockHolder lock(&g_type_profiler_lock);
+ InitializeTypeProfilerMemory();
+
+ g_type_profiler_map->Insert(address, ObjectInfo(size, &type));
+}
+
+void EraseType(void* address) {
+ SpinLockHolder lock(&g_type_profiler_lock);
+ InitializeTypeProfilerMemory();
+
+ ObjectInfo obj;
+ g_type_profiler_map->FindAndRemove(address, &obj);
+}
+
+const std::type_info* LookupType(const void* address) {
+ SpinLockHolder lock(&g_type_profiler_lock);
+ InitializeTypeProfilerMemory();
+
+ const ObjectInfo* found = g_type_profiler_map->Find(address);
+ if (found == NULL)
+ return NULL;
+ return found->type;
+}
+
+#endif // defined(TYPE_PROFILING)
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/TODO b/chromium/third_party/tcmalloc/chromium/src/windows/TODO
new file mode 100644
index 00000000000..708ec237ac4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/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/chromium/third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c b/chromium/third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c
new file mode 100644
index 00000000000..97b614b41ea
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c
@@ -0,0 +1,156 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <dbghelp.h>
+
+#define SEARCH_CAP (1024*1024)
+#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols"
+
+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], "-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 {
+ fprintf(stderr, "usage: "
+ "addr2line-pdb [-f|--functions] [-C|--demangle] [-e filename]\n");
+ fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n");
+ exit(1);
+ }
+ }
+
+ 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;
+ }
+
+ 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 addr = _strtoui64(buf, NULL, 16);
+ ULONG64 buffer[(sizeof(SYMBOL_INFO) +
+ MAX_SYM_NAME*sizeof(TCHAR) +
+ sizeof(ULONG64) - 1)
+ / sizeof(ULONG64)];
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+ IMAGEHLP_LINE64 line;
+ DWORD dummy;
+ pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ pSymbol->MaxNameLen = MAX_SYM_NAME;
+ if (print_function_name) {
+ if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
+ printf("%s\n", pSymbol->Name);
+ } else {
+ printf("??\n");
+ }
+ }
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ if (SymGetLineFromAddr64(process, (DWORD64)addr, &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/chromium/third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h b/chromium/third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h
new file mode 100644
index 00000000000..5a047977395
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h
@@ -0,0 +1,155 @@
+// 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 <typename T>
+class AutoTestingHookImpl : public AutoTestingHookBase {
+ public:
+ static AutoTestingHookImpl<T> MakeTestingHook(T target_function,
+ T replacement_function,
+ bool do_it) {
+ return AutoTestingHookImpl<T>(target_function, replacement_function, do_it);
+ }
+
+ static AutoTestingHookImpl<T>* MakeTestingHookHolder(T target_function,
+ T replacement_function,
+ bool do_it) {
+ return new AutoTestingHookImpl<T>(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 <typename T>
+inline AutoTestingHookImpl<T> MakeTestingHook(T target,
+ T replacement,
+ bool do_it) {
+ return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, do_it);
+}
+
+template <typename T>
+inline AutoTestingHookImpl<T> MakeTestingHook(T target, T replacement) {
+ return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, true);
+}
+
+template <typename T>
+inline AutoTestingHookImpl<T>* MakeTestingHookHolder(T target, T replacement) {
+ return AutoTestingHookImpl<T>::MakeTestingHookHolder(target, replacement,
+ true);
+}
+
+}; // namespace sidestep
+
+#endif // CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/config.h b/chromium/third_party/tcmalloc/chromium/src/windows/config.h
new file mode 100644
index 00000000000..9d61884e298
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/config.h
@@ -0,0 +1,306 @@
+/* A manual version of config.h fit for windows machines. */
+
+/* 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_
+
+/* define this if you are linking tcmalloc statically and overriding the
+ * default allocators.
+ * For instructions on how to use this mode, see
+ * http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
+ */
+#undef WIN32_OVERRIDE_ALLOCATORS
+
+/* Define to 1 if your libc has a snprintf implementation */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+#undef HAVE_BUILTIN_STACK_POINTER
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+#undef HAVE_CONFLICT_SIGNAL_H
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_UNAME
+
+/* 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 <dlfcn.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1 /* we define it in windows/port.cc */
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+#undef HAVE_LIBUNWIND_H
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#undef HAVE_LINUX_PTRACE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> 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
+
+/* Define to 1 if you have the <pwd.h> 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 <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> 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 <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#undef HAVE_UNWIND_H
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+#define HAVE___INT64 1
+
+/* 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 in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 'volatile' if __malloc_hook is declared volatile */
+#undef MALLOC_HOOK_MAYBE_VOLATILE
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "gperftools"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.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.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "gperftools"
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.0"
+
+/* 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
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "Id"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "Iu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "Ix"
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#undef VERSION
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#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/chromium/third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc b/chromium/third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc
new file mode 100644
index 00000000000..e8a96dfff7d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc
@@ -0,0 +1,64 @@
+// 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 <sys/types.h> // for size_t
+#include <new> // 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/chromium/third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h b/chromium/third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h
new file mode 100644
index 00000000000..c7db6319426
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/tcmalloc.h>
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h b/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h
new file mode 100644
index 00000000000..db32c5366ab
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h.in file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR 2
+#define TC_VERSION_MINOR 0
+#define TC_VERSION_PATCH ""
+#define TC_VERSION_STRING "gperftools 2.0"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if 0
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in b/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in
new file mode 100644
index 00000000000..d09ec953622
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h.in file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// 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@"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if 0
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc b/chromium/third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc
new file mode 100644
index 00000000000..142c7cbea60
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc
@@ -0,0 +1,121 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Table of relevant information about how to decode the ModR/M byte.
+ * Based on information in the IA-32 Intel® Architecture
+ * Software Developer's Manual Volume 2: Instruction Set Reference.
+ */
+
+#include "mini_disassembler.h"
+#include "mini_disassembler_types.h"
+
+namespace sidestep {
+
+const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, false, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_WORD },
+ /* r/m == 001 */ { true, false, OS_WORD },
+ /* r/m == 010 */ { true, false, OS_WORD },
+ /* r/m == 011 */ { true, false, OS_WORD },
+ /* r/m == 100 */ { true, false, OS_WORD },
+ /* r/m == 101 */ { true, false, OS_WORD },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { true, false, OS_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO }
+};
+
+const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, true, OS_ZERO },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, true, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+};
+
+}; // namespace sidestep
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc b/chromium/third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc
new file mode 100644
index 00000000000..e14279cd345
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc
@@ -0,0 +1,1219 @@
+/* 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/chromium/third_party/tcmalloc/chromium/src/windows/mingw.h b/chromium/third_party/tcmalloc/chromium/src/windows/mingw.h
new file mode 100644
index 00000000000..2aa5eb3ed27
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/mingw.h
@@ -0,0 +1,67 @@
+/* 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
+
+#define HAVE_SNPRINTF 1
+
+// 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.
+#undef HAVE_PTHREAD
+
+#include "windows/port.h"
+
+#endif /* __MINGW32__ */
+
+#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc
new file mode 100644
index 00000000000..9e336ba4f9a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc
@@ -0,0 +1,431 @@
+/* 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/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.h b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.h
new file mode 100644
index 00000000000..85be6748e95
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler.h
@@ -0,0 +1,197 @@
+/* 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 <windows.h>
+#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 <b>incremented</b> by
+ // the length in bytes of the instruction.
+ // @return enItJump, enItReturn or enItGeneric on success. enItUnknown
+ // if unable to disassemble, enItUnused if this seems to be an unused
+ // opcode. In the last two (error) cases, cbInstruction will be set
+ // to 0xffffffff.
+ //
+ // @post This instance of the disassembler is ready to be used again,
+ // with unchanged defaults from creation time.
+ InstructionType Disassemble(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/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h
new file mode 100644
index 00000000000..83dee8ba920
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h
@@ -0,0 +1,236 @@
+/* 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.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+
+ // Alternative opcode info if certain prefixes are specified.
+ // In most cases, all of these are zeroed-out. Only used if
+ // bPrefixDependent is true.
+ bool is_prefix_dependent_;
+ SpecificOpcode opcode_if_f2_prefix_;
+ SpecificOpcode opcode_if_f3_prefix_;
+ SpecificOpcode opcode_if_66_prefix_;
+};
+
+// Information about each table entry.
+struct OpcodeTable {
+ // Table of instruction entries
+ const Opcode* table_;
+ // How many bytes left to shift ModR/M byte <b>before</b> applying mask
+ unsigned char shift_;
+ // Mask to apply to byte being looked at before comparing to table
+ unsigned char mask_;
+ // Minimum/maximum indexes in table.
+ unsigned char min_lim_;
+ unsigned char max_lim_;
+};
+
+// Information about each entry in table used to decode ModR/M byte.
+struct ModrmEntry {
+ // Is the operand encoded as bytes in the instruction (rather than
+ // if it's e.g. a register in which case it's just encoded in the
+ // ModR/M byte)
+ bool is_encoded_in_instruction_;
+
+ // Is there a SIB byte? In this case we always need to decode it.
+ bool use_sib_byte_;
+
+ // What is the size of the operand (only important if it's encoded
+ // in the instruction)?
+ OperandSize operand_size_;
+};
+
+}; // namespace sidestep
+
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/nm-pdb.c b/chromium/third_party/tcmalloc/chromium/src/windows/nm-pdb.c
new file mode 100644
index 00000000000..726d345953a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/nm-pdb.c
@@ -0,0 +1,266 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h> // for _strdup
+
+#include <windows.h>
+#include <dbghelp.h>
+
+// 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
+}
+
+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 {
+ break;
+ }
+ }
+ if (i != argc - 1) {
+ fprintf(stderr, "usage: nm-pdb [-C|--demangle] <module or filename>\n");
+ 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/chromium/third_party/tcmalloc/chromium/src/windows/override_functions.cc b/chromium/third_party/tcmalloc/chromium/src/windows/override_functions.cc
new file mode 100644
index 00000000000..e634fe27280
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/override_functions.cc
@@ -0,0 +1,122 @@
+// 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 <config.h>
+
+#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* _recalloc(void* p, size_t n, size_t size) {
+ void* result = realloc(p, n * size);
+ memset(result, 0, n * size);
+ return result;
+}
+
+extern "C" void* _calloc_impl(size_t n, size_t size) {
+ return calloc(n, size);
+}
+
+extern "C" size_t _msize(void* p) {
+ return MallocExtension::instance()->GetAllocatedSize(p);
+}
+
+extern "C" intptr_t _get_heap_handle() {
+ return 0;
+}
+
+// The CRT heap initialization stub.
+extern "C" 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.
+extern "C" void _heap_term() {
+}
+
+extern "C" int _set_new_mode(int flag) {
+ return tc_set_new_mode(flag);
+}
+
+#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
+
+// 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.
+extern "C" void* _crtheap = reinterpret_cast<void*>(1);
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/patch_functions.cc b/chromium/third_party/tcmalloc/chromium/src/windows/patch_functions.cc
new file mode 100644
index 00000000000..7a7e6adf039
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/patch_functions.cc
@@ -0,0 +1,1080 @@
+// 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 <config.h>
+
+#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 <windows.h>
+#include <stdio.h>
+#include <malloc.h> // for _msize and _expand
+#include <Psapi.h> // for EnumProcessModules, GetModuleInformation, etc.
+#include <set>
+#include <map>
+#include <vector>
+#include <base/logging.h>
+#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.
+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";
+
+// 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<HMODULE>(const_cast<void*>(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,
+ 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 arugment -- 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<int> 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_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<const HMODULE>(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",
+};
+
+// 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,
+};
+
+template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
+ // This will get filled in at run-time, as patching is done.
+};
+
+template<int T>
+const GenericFnPtr LibcInfoWithPatchFunctions<T>::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,
+};
+
+/*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<int T>
+bool LibcInfoWithPatchFunctions<T>::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.
+ // 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*)(origstub_fn_[i]);
+ 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<int T>
+void LibcInfoWithPatchFunctions<T>::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<HMODULE> *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<ModuleEntryCopy> 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<HMODULE> currently_loaded_modules;
+ {
+ SpinLockHolder h(&patch_all_modules_lock);
+ if (!g_last_loaded) g_last_loaded = new std::set<HMODULE>;
+ // 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<ModuleEntryCopy>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW {
+ void* result = do_malloc_or_cpp_alloc(size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::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]);
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::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]);
+ 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<int T>
+void* LibcInfoWithPatchFunctions<T>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_new(size_t size) {
+ void* p = cpp_alloc(size, false);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_newarray(size_t size) {
+ void* p = cpp_alloc(size, false);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_delete(void *p) {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_deletearray(void *p) {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_new_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_newarray_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_delete_nothrow(
+ void *p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow(
+ void *p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+
+// _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<int T>
+size_t LibcInfoWithPatchFunctions<T>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::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);
+}
+
+// g_load_map holds a copy of windows' refcount for how many times
+// each currently loaded module has been loaded and unloaded. We use
+// it as an optimization when the same module is loaded more than
+// once: as long as the refcount stays above 1, we don't need to worry
+// about patching because it's already patched. Likewise, we don't
+// need to unpatch until the refcount drops to 0. load_map is
+// maintained in LoadLibraryExW and FreeLibrary, and only covers
+// modules explicitly loaded/freed via those interfaces.
+static std::map<HMODULE, int>* g_load_map = NULL;
+
+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/chromium/third_party/tcmalloc/chromium/src/windows/port.cc b/chromium/third_party/tcmalloc/chromium/src/windows/port.cc
new file mode 100644
index 00000000000..00919856339
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/port.cc
@@ -0,0 +1,362 @@
+/* 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 <config.h>
+#include <string.h> // for strlen(), memset(), memcmp()
+#include <assert.h>
+#include <stdarg.h> // for va_list, va_start, va_end
+#include <windows.h>
+#include "port.h"
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "internal_logging.h"
+#include "system-alloc.h"
+
+// -----------------------------------------------------------------------
+// Basic libraries
+
+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
+
+// Declared (not extern "C") in thread_cache.h
+bool CheckIfKernelSupportsTLS() {
+ // TODO(csilvers): return true (all win's since win95, at least, support this)
+ return false;
+}
+
+// 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 http://www.codeproject.com/threads/tls.asp.
+// 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.
+extern "C" {
+// This tells the linker to run these functions.
+// We use CRT$XLY instead of CRT$XLB to ensure we're called LATER in sequence.
+#pragma section(".CRT$XLY", read)
+_declspec(allocate(".CRT$XLY")) \
+ void (NTAPI *p_thread_callback_tcmalloc)(
+ HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback;
+#pragma section(".CRT$XTU", read)
+_declspec(allocate(".CRT$XTU")) \
+ int (*p_process_term_tcmalloc)(void) = on_process_term;
+} // extern "C"
+
+#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 replace system-alloc.cc
+
+// This is mostly like MmapSysAllocator::Alloc, except it does these weird
+// munmap's in the middle of the page, which is forbidden in windows.
+extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
+ size_t alignment) {
+ // 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<uintptr_t>(result) & (alignment - 1)) == 0);
+
+ return result;
+}
+
+size_t TCMalloc_SystemAddGuard(void* start, size_t size) {
+ static size_t pagesize = 0;
+ if (pagesize == 0) {
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ pagesize = system_info.dwPageSize;
+ }
+
+ // We know that TCMalloc_SystemAlloc will give us a correct page alignment
+ // regardless, so we can just assert to detect erroneous callers.
+ assert(reinterpret_cast<size_t>(start) % pagesize == 0);
+
+ // Add a guard page to catch metadata corruption. We're using the
+ // PAGE_GUARD flag rather than NO_ACCESS because we want the unique
+ // exception in crash reports.
+ DWORD permissions = 0;
+ if (size > pagesize &&
+ VirtualProtect(start, pagesize, PAGE_READONLY | PAGE_GUARD,
+ &permissions)) {
+ return pagesize;
+ }
+
+ return 0;
+}
+
+void TCMalloc_SystemRelease(void* start, size_t length) {
+ if (VirtualFree(start, length, MEM_DECOMMIT))
+ return;
+
+ // 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<char*>(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<size_t>(info.RegionSize, end - ptr);
+ BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
+ assert(success == TRUE);
+ ptr += decommitSize;
+ }
+}
+
+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<char*>(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<size_t>(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
+}
+
+// The current system allocator
+SysAllocator* sys_alloc = NULL;
+
+
+// -----------------------------------------------------------------------
+// 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/chromium/third_party/tcmalloc/chromium/src/windows/port.h b/chromium/third_party/tcmalloc/chromium/src/windows/port.h
new file mode 100644
index 00000000000..c2381091859
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/port.h
@@ -0,0 +1,477 @@
+/* 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 NOMINMAX
+#define NOMINMAX /* Do not define min and max macros. */
+#endif
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
+#endif
+#include <windows.h>
+#include <io.h> /* because we so often use open/close/etc */
+#include <direct.h> /* for _getcwd */
+#include <process.h> /* for _getpid */
+#include <limits.h> /* for PATH_MAX */
+#include <stdarg.h> /* for va_list */
+#include <stdio.h> /* need this to override stdio's (v)snprintf */
+#include <sys/types.h> /* for _off_t */
+#include <assert.h>
+#include <stdlib.h> /* for rand, srand, _strtoxxx */
+
+/*
+ * 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
+#ifndef HAVE___INT64 /* we need to have all the __intX names */
+# error Do not know how to set up type aliases. Edit port.h for your system.
+#endif
+
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif /* #ifndef HAVE_STDINT_H */
+
+/* I guess MSVC's <types.h> 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;
+}
+
+/* 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 */
+#endif /* HAVE_PTHREAD */
+
+inline void sched_yield(void) {
+ Sleep(0);
+}
+
+/*
+ * __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_SNPRINTF
+inline int snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ int r;
+ va_start(ap, format);
+ r = perftools_vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
+#endif
+
+#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
+
+/* ----------------------------------- 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 */
+
+typedef int pid_t;
+#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 int getpagesize(); /* in port.cc */
+
+/* ----------------------------------- OTHER */
+
+inline void srandom(unsigned int seed) { srand(seed); }
+inline long random(void) { return rand(); }
+inline unsigned int sleep(unsigned int seconds) {
+ Sleep(seconds * 1000);
+ return 0;
+}
+
+// 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
+
+inline int nanosleep(const struct timespec *req, struct timespec *rem) {
+ Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
+ return 0;
+}
+
+#ifndef __MINGW32__
+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);
+}
+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();
+
+// ----------------------------------- BUILD-SPECIFIC
+
+/*
+ * 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
+
+
+#endif /* _WIN32 */
+
+#undef inline
+#undef EXTERN_C
+
+#endif /* GOOGLE_BASE_WINDOWS_H_ */
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc
new file mode 100644
index 00000000000..b27a95bcb6f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc
@@ -0,0 +1,684 @@
+/* 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, <replacement_function>
+// 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<void*>(&relative_offset),
+ reinterpret_cast<void*>(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<void*>(&relative_offset),
+ reinterpret_cast<void*>(target + 1), 1);
+ new_target = target + 2 + relative_offset;
+ } else if (target[0] == ASM_JMP32ABS_0 &&
+ target[1] == ASM_JMP32ABS_1) {
+ // 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<void*>(&target_offset),
+ reinterpret_cast<void*>(target + 2), 4);
+ new_target_v = reinterpret_cast<void**>(target + target_offset + 6);
+ } else {
+ SIDESTEP_ASSERT(sizeof(new_target) == 4);
+ memcpy(&new_target_v, reinterpret_cast<void*>(target + 2), 4);
+ }
+ new_target = reinterpret_cast<unsigned char*>(*new_target_v);
+ } 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<void*>(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<void*>(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<void*>(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<unsigned char*>(target_function);
+ target = reinterpret_cast<unsigned char*>(
+ ResolveTargetImpl(
+ target, reinterpret_cast<unsigned char*>(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<void*>(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<unsigned char*>(
+ 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 orignal 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<void*>(target + target_bytes),
+ reinterpret_cast<void*>(reinterpret_cast<unsigned char*>(
+ 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<unsigned char*>(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<void*>(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<PreamblePage*>(AllocPageNear(target));
+ SIDESTEP_ASSERT(preamble_page != NULL && "Could not allocate page!");
+ void** pp = &preamble_page->free_;
+ unsigned char* ptr = reinterpret_cast<unsigned char*>(preamble_page) +
+ MAX_PREAMBLE_STUB_SIZE;
+ unsigned char* limit = reinterpret_cast<unsigned char*>(preamble_page) +
+ pagesize_;
+ while (ptr < limit) {
+ *pp = ptr;
+ pp = reinterpret_cast<void**>(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<unsigned char*>(preamble_page->free_);
+ preamble_page->free_ = *(reinterpret_cast<void**>(preamble_page->free_));
+ return ret;
+}
+
+void PreamblePatcher::FreePreambleBlock(unsigned char* block) {
+ SIDESTEP_ASSERT(block != NULL);
+ SIDESTEP_ASSERT(granularity_ != 0);
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(block);
+ ptr -= ptr & (granularity_ - 1);
+ PreamblePage* preamble_page = reinterpret_cast<PreamblePage*>(ptr);
+ SIDESTEP_ASSERT(preamble_page->magic_ == kPreamblePageMagic);
+ *(reinterpret_cast<void**>(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<unsigned char*>(
+ 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 <= NULL) {
+ // Less than 0
+ break;
+ }
+ pv = ::VirtualAlloc(reinterpret_cast<void*>(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<unsigned char*>(
+ (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<void*>(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::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) {
+ unsigned char* original_jump_dest = (source + 2) + 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<void*>(target),
+ reinterpret_cast<void*>(&jmpcode), 2);
+ memcpy(reinterpret_cast<void*>(target + 2),
+ reinterpret_cast<void*>(&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<unsigned char *>(
+ reinterpret_cast<__int64>(source + instruction_size) +
+ *(reinterpret_cast<int*>(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<unsigned char>(
+ fixup_jump_offset) << 8) | (0x70 | (source[1] & 0xf));
+ memcpy(reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(&jmpcode),
+ 2);
+ } else {
+ target[0] = ASM_JMP8REL;
+ target[1] = static_cast<unsigned char>(fixup_jump_offset);
+ }
+ }
+ } else {
+ *target_bytes = instruction_size;
+ if (target_size > *target_bytes) {
+ memcpy(reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(source),
+ jmp_offset_in_instruction);
+ memcpy(reinterpret_cast<void*>(target + jmp_offset_in_instruction),
+ reinterpret_cast<void*>(&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 <offset>
+ unsigned char* original_mov_dest = reinterpret_cast<unsigned char*>(
+ reinterpret_cast<__int64>(source + instruction_size) +
+ *(reinterpret_cast<int*>(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<void*>(target),
+ reinterpret_cast<void*>(source),
+ mov_offset_in_instruction);
+ memcpy(reinterpret_cast<void*>(target + mov_offset_in_instruction),
+ reinterpret_cast<void*>(&fixup_mov_offset),
+ 4);
+ }
+ return SIDESTEP_SUCCESS;
+}
+
+}; // namespace sidestep
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.h b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.h
new file mode 100644
index 00000000000..4fdb7d00165
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher.h
@@ -0,0 +1,611 @@
+/* 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 <windows.h>
+
+// 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 <class T>
+ 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 <class T>
+ 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 <class T>
+ 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);
+
+ // 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);
+
+ // 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/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc
new file mode 100644
index 00000000000..41ab551cc99
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc
@@ -0,0 +1,367 @@
+/* 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 <windows.h>
+#include <tchar.h>
+
+// Turning off all optimizations for this file, since the official build's
+// "Whole program optimization" seems to cause the TestPatchUsingDynamicStub
+// test to crash with an access violation. We debugged this and found
+// that the optimized access a register that is changed by a call to the hook
+// function.
+#pragma optimize("", off)
+
+// A convenience macro to avoid a lot of casting in the tests.
+// I tried to make this a templated function, but windows complained:
+// error C2782: 'sidestep::SideStepError `anonymous-namespace'::Unpatch(T,T,T *)' : template parameter 'T' is ambiguous
+// could be 'int (int)'
+// or 'int (__cdecl *)(int)'
+// My life isn't long enough to try to figure out how to fix this.
+#define UNPATCH(target_function, replacement_function, original_function_stub) \
+ sidestep::PreamblePatcher::Unpatch((void*)(target_function), \
+ (void*)(replacement_function), \
+ (void*)(original_function))
+
+namespace {
+
+// Function for testing - this is what we patch
+//
+// NOTE: Because of the way the compiler optimizes this function in
+// release builds, we need to use a different input value every time we
+// call it within a function, otherwise the compiler will just reuse the
+// last calculated incremented value.
+int __declspec(noinline) IncrementNumber(int i) {
+#ifdef _M_X64
+ __int64 i2 = i + 1;
+ return (int) i2;
+#else
+ return i + 1;
+#endif
+}
+
+extern "C" int TooShortFunction(int);
+
+extern "C" int JumpShortCondFunction(int);
+
+extern "C" int JumpNearCondFunction(int);
+
+extern "C" int JumpAbsoluteFunction(int);
+
+extern "C" int CallNearRelativeFunction(int);
+
+typedef int (*IncrementingFunc)(int);
+IncrementingFunc original_function = NULL;
+
+int HookIncrementNumber(int i) {
+ SIDESTEP_ASSERT(original_function != NULL);
+ int incremented_once = original_function(i);
+ return incremented_once + 1;
+}
+
+// For the AutoTestingHook test, we can't use original_function, because
+// all that is encapsulated.
+// This function "increments" by 10, just to set it apart from the other
+// functions.
+int __declspec(noinline) AutoHookIncrementNumber(int i) {
+ return i + 10;
+}
+
+}; // namespace
+
+namespace sidestep {
+
+bool TestDisassembler() {
+ unsigned int instruction_size = 0;
+ sidestep::MiniDisassembler disassembler;
+ void * target = reinterpret_cast<unsigned char *>(IncrementNumber);
+ void * new_target = PreamblePatcher::ResolveTarget(target);
+ if (target != new_target)
+ target = new_target;
+
+ while (1) {
+ sidestep::InstructionType instructionType = disassembler.Disassemble(
+ reinterpret_cast<unsigned char *>(target) + instruction_size,
+ instruction_size);
+ if (sidestep::IT_RETURN == instructionType) {
+ return true;
+ }
+ }
+}
+
+bool TestPatchWithLongJump() {
+ original_function = NULL;
+ void *p = ::VirtualAlloc(reinterpret_cast<void *>(0x0000020000000000), 4096,
+ MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ SIDESTEP_EXPECT_TRUE(p != NULL);
+ memset(p, 0xcc, 4096);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ (IncrementingFunc) p,
+ &original_function));
+ SIDESTEP_ASSERT((*original_function)(1) == 2);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ (IncrementingFunc)p,
+ original_function));
+ ::VirtualFree(p, 0, MEM_RELEASE);
+ return true;
+}
+
+bool TestPatchWithPreambleShortCondJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpShortCondFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpShortCondFunction,
+ (void*)HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleNearRelativeCondJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpNearCondFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpNearCondFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleAbsoluteJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpAbsoluteFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpAbsoluteFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleNearRelativeCall() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(
+ CallNearRelativeFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(CallNearRelativeFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchUsingDynamicStub() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &original_function));
+ SIDESTEP_EXPECT_TRUE(original_function);
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 4);
+ SIDESTEP_EXPECT_TRUE(original_function(3) == 4);
+
+ // Clearbox test to see that the function has been patched.
+ sidestep::MiniDisassembler disassembler;
+ unsigned int instruction_size = 0;
+ SIDESTEP_EXPECT_TRUE(sidestep::IT_JUMP == disassembler.Disassemble(
+ reinterpret_cast<unsigned char*>(IncrementNumber),
+ instruction_size));
+
+ // Since we patched IncrementNumber, its first statement is a
+ // jmp to the hook function. So verify that we now can not patch
+ // IncrementNumber because it starts with a jump.
+#if 0
+ IncrementingFunc dummy = NULL;
+ // TODO(joi@chromium.org): restore this test once flag is added to
+ // disable JMP following
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_JUMP_INSTRUCTION ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &dummy));
+
+ // This test disabled because code in preamble_patcher_with_stub.cc
+ // asserts before returning the error code -- so there is no way
+ // to get an error code here, in debug build.
+ dummy = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_FUNCTION_TOO_SMALL ==
+ sidestep::PreamblePatcher::Patch(TooShortFunction,
+ HookIncrementNumber,
+ &dummy));
+#endif
+
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool PatchThenUnpatch() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &original_function));
+ SIDESTEP_EXPECT_TRUE(original_function);
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 3);
+ SIDESTEP_EXPECT_TRUE(original_function(2) == 3);
+
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ HookIncrementNumber,
+ original_function));
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool AutoTestingHookTest() {
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+
+ // Inner scope, so we can test what happens when the AutoTestingHook
+ // goes out of scope
+ {
+ AutoTestingHook hook = MakeTestingHook(IncrementNumber,
+ AutoHookIncrementNumber);
+ (void) hook;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
+ }
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool AutoTestingHookInContainerTest() {
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+
+ // Inner scope, so we can test what happens when the AutoTestingHook
+ // goes out of scope
+ {
+ AutoTestingHookHolder hook(MakeTestingHookHolder(IncrementNumber,
+ AutoHookIncrementNumber));
+ (void) hook;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
+ }
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool TestPreambleAllocation() {
+ __int64 diff = 0;
+ void* p1 = reinterpret_cast<void*>(0x110000000);
+ void* p2 = reinterpret_cast<void*>(0x810000000);
+ unsigned char* b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
+ SIDESTEP_EXPECT_TRUE(b1 != NULL);
+ diff = reinterpret_cast<__int64>(p1) - reinterpret_cast<__int64>(b1);
+ // Ensure blocks are within 2GB
+ SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
+ unsigned char* b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
+ SIDESTEP_EXPECT_TRUE(b2 != NULL);
+ diff = reinterpret_cast<__int64>(p2) - reinterpret_cast<__int64>(b2);
+ SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
+
+ // Ensure we're reusing free blocks
+ unsigned char* b3 = b1;
+ unsigned char* b4 = b2;
+ PreamblePatcher::FreePreambleBlock(b1);
+ PreamblePatcher::FreePreambleBlock(b2);
+ b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
+ SIDESTEP_EXPECT_TRUE(b1 == b3);
+ b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
+ SIDESTEP_EXPECT_TRUE(b2 == b4);
+ PreamblePatcher::FreePreambleBlock(b1);
+ PreamblePatcher::FreePreambleBlock(b2);
+
+ return true;
+}
+
+bool UnitTests() {
+ return TestPatchWithPreambleNearRelativeCall() &&
+ TestPatchWithPreambleAbsoluteJump() &&
+ TestPatchWithPreambleNearRelativeCondJump() &&
+ TestPatchWithPreambleShortCondJump() &&
+ TestDisassembler() && TestPatchWithLongJump() &&
+ TestPatchUsingDynamicStub() && PatchThenUnpatch() &&
+ AutoTestingHookTest() && AutoTestingHookInContainerTest() &&
+ TestPreambleAllocation();
+}
+
+}; // namespace sidestep
+
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (size == 0) // not even room for a \0?
+ return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ bool ret = sidestep::UnitTests();
+ printf("%s\n", ret ? "PASS" : "FAIL");
+ return ret ? 0 : -1;
+}
+
+#pragma optimize("", on)
diff --git a/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc
new file mode 100644
index 00000000000..b0dc393d975
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc
@@ -0,0 +1,296 @@
+/* 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<unsigned char*>(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>
+ //
+ // trampoline:
+ // nop
+ // mov rax, <replacement_function>
+ // 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 (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<void*>(preamble_stub + stub_bytes),
+ reinterpret_cast<void*>(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<unsigned char*>(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<void*>(preamble_stub + stub_bytes + 1),
+ reinterpret_cast<void*>(&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<void*>(preamble_stub + trampoline_pos + 3),
+ reinterpret_cast<void*>(&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<unsigned char*>(replacement_function) -
+ reinterpret_cast<unsigned char*>(target) - 5;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ // complete the jmp instruction
+ memcpy(reinterpret_cast<void*>(target + 1),
+ reinterpret_cast<void*>(&offset_to_replacement_function), 4);
+
+ // Set any remaining bytes that were moved to the preamble-stub to INT3 so
+ // as not to cause confusion (otherwise you might see some strange
+ // instructions if you look at the disassembly, or even invalid
+ // instructions). Also, by doing this, we will break into the debugger if
+ // some code calls into this portion of the code. If this happens, it
+ // means that this function cannot be patched using this patcher without
+ // further thought.
+ if (preamble_bytes > kRequiredTargetPatchBytes) {
+ memset(reinterpret_cast<void*>(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/chromium/third_party/tcmalloc/chromium/src/windows/shortproc.asm b/chromium/third_party/tcmalloc/chromium/src/windows/shortproc.asm
new file mode 100644
index 00000000000..7e8e3d78395
--- /dev/null
+++ b/chromium/third_party/tcmalloc/chromium/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/chromium/third_party/tcmalloc/vendor/AUTHORS b/chromium/third_party/tcmalloc/vendor/AUTHORS
new file mode 100644
index 00000000000..3995ed4cf57
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/AUTHORS
@@ -0,0 +1,2 @@
+google-perftools@googlegroups.com
+
diff --git a/chromium/third_party/tcmalloc/vendor/COPYING b/chromium/third_party/tcmalloc/vendor/COPYING
new file mode 100644
index 00000000000..e4956cfd9fd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/ChangeLog b/chromium/third_party/tcmalloc/vendor/ChangeLog
new file mode 100644
index 00000000000..4b334beaade
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/ChangeLog
@@ -0,0 +1,646 @@
+Fri Feb 03 15:40:45 2012 Google Inc. <google-perftools@googlegroups.com>
+
+ * 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. <opensource@google.com>
+
+ * google-perftools: version 1.10 release
+ * PORTING: Support for patching assembly on win x86_64! (scott.fr...)
+ * PORTING: Work around atexit-execution-order bug on freebsd (csilvers)
+ * PORTING: Patch _calloc_crt for windows (roger orr)
+ * PORTING: Add C++11 compatibility method for stl allocator (jdennett)
+ * PORTING: use MADV_FREE, not MADV_DONTNEED, on freebsd (csilvers)
+ * PORTING: Don't use SYS_open when not supported on solaris (csilvers)
+ * PORTING: Do not assume uname() returns 0 on success (csilvers)
+ * LSS: Improved ARM support in linux-syscall-support (dougkwan)
+ * LSS: Get rid of unused syscalls in linux-syscall-support (csilvers)
+ * LSS: Fix broken mmap wrapping for ppc (markus)
+ * LSS: Emit .cfi_adjust_cfa_offset when appropriate (ppluzhnikov)
+ * LSS: Be more accurate in register use in __asm__ (markus)
+ * LSS: Fix __asm__ calls to compile under clang (chandlerc)
+ * LSS: Fix ARM inline assembly bug around r7 and swi (lcwu)
+ * No longer log when an allocator fails (csilvers)
+ * void* -> const void* for MallocExtension methods (llib)
+ * Improve HEAP_PROFILE_MMAP and fix bugs with it (dmikurube)
+ * Replace int-based abs with more correct fabs in a test (pmurin)
+
+Thu Dec 22 16:22:45 2011 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 1.9 release
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * google-perftools: version 1.0 release
+ * Exactly the same as 1.0rc2
+
+Sun Dec 14 17:10:35 2008 Google Inc. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * google-perftools: version 0.93 release
+ * PORTING: everything compiles on Solaris, OS X, FreeBSD (see INSTALL)
+ * PORTING: cpu-profiler works on most platforms (much better GetPC())
+ * PORTING: heap-profiler works on most platforms
+ * PORTING: improved windows support, including release builds
+ * No longer build or run ptmalloc tests by default
+ * Add support for using memfs filesystem to allocate memory in linux
+ * WINDOWS: give debug library and release library different names
+
+Tue Jul 17 22:26:27 2007 Google Inc. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * google-perftools: version 0.91 release
+ * Brown-paper-bag bugfix: compilation error on some x86-64 machines
+
+Fri Apr 13 14:50:51 2007 Google Inc. <opensource@google.com>
+
+ * 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. <opensource@google.com>
+
+ * google-perftools: version 0.8 release
+ * Experimental support for remote profiling added to pprof (many)
+ * Fixed race condition in ProfileData::FlushTable (etune)
+ * Better support for weird /proc maps (maxim, mec)
+ * Fix heap-checker interaction with gdb (markus)
+ * Better 64-bit support in pprof (aruns)
+ * Reduce scavenging cost in tcmalloc by capping NumMoveSize (sanjay)
+ * Cast syscall(SYS_mmap); works on more 64-bit systems now (menage)
+ * Document the text output of pprof! (csilvers)
+ * Better compiler support for no-THREADS and for old compilers (csilvers)
+ * Make libunwind the default stack unwinder for x86-64 (aruns)
+ * Somehow the COPYING file got erased. Regenerate it (csilvers)
+
+Thu Apr 13 20:59:09 2006 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.7 release
+ * Major rewrite of thread introspection for new kernels (markus)
+ * Major rewrite of heap-checker to use new thread tools (maxim)
+ * Add proper support for following data in thread registers (maxim)
+ * Syscall support for older kernels, including _syscall6 (markus)
+ * Support PIC mode (markus, mbland, iant)
+ * Better support for running in non-threaded contexts (csilvers)
+
+Fri Jan 27 14:04:27 2006 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.6 release
+ * More sophisticated stacktrace usage, possibly using libunwind (aruns)
+ * Update pprof to handle 64-bit profiles (dehnert)
+ * Fix GetStackTrace to correctly return top stackframe (sanjay)
+ * Add ANSI compliance for new and new[], including new_handler (jkearney)
+ * More accuracy by reading ELF files directly rather than objdump (mec)
+ * Add readline support for pprof (addi)
+ * Add #includes for PPC (csilvers)
+ * New PC-detection routine for ibook powerpc (asbestoshead)
+ * Vastly improved tcmalloc unittest (csilvers)
+ * Move documentation from /usr/doc to /usr/share/doc
+
+Mon Nov 14 17:28:59 2005 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.5 release
+ * Add va_start/va_end calls around vsnprintf() (csilvers)
+ * Write our own __syscall_return(), since it's not defined
+ consistently on all 64-bit linux distros (markus)
+
+Wed Oct 26 15:19:16 2005 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.4 release
+ * Decrease fragmentation in tcmalloc (lefevere)
+ * Support for ARM in some of the thread-specific code (markus)
+ * Turn off heap-checker for statically-linked binaries, which
+ cause error leak reports now (etune)
+ * Many pprof improvements, including a command-line interface (jeff)
+ * CPU profiling now automatically affects all threads in linux 2.6.
+ (Kernel bugs break CPU profiling and threads in linux 2.4 a bit.)
+ ProfilerEnable() and ProfilerDisable() are deprecated. (sanjay)
+ * tcmalloc now correctly intercepts memalign (m3b, maxim)
+ * Syntax fix: added missing va_end()s. Helps non-gcc compiling (etune)
+ * Fixed a few coredumper bugs: race condition after PTRACE_DETACH,
+ ignore non-aligned stackframe pointers (markus, menage)
+ * 64-bit cleanup, especially for spinlock code (etune) and mmap (sanjay)
+ * Better support for finding threads in linux (markus)
+ * tcmalloc now tracks those stack traces that allocate memory (sanjay)
+ * Work around a weird setspecific problem (sanjay)
+ * Fix tcmalloc overflow problems when an alloc is close to 2G/4G (sanjay)
+
+Fri Jun 24 18:02:26 2005 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.3 release
+ * Add missing errno include for one of the unittests (csilvers)
+ * Reduce tcmalloc startup memory from 5M to 256K (sanjay)
+ * Add support for mallopt() and mallinfo (sanjay)
+ * Improve stacktrace's performance on some 64-bit systems (etune)
+ * Improve the stacktrace unittest (etune)
+
+Tue May 31 08:14:38 2005 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 0.2 release
+ * Use mmap2() instead of mmap(), to map more memory (menage)
+ * Do correct pthread-local checking in heap-checker! (maxim)
+ * Avoid overflow on 64-bit machines in pprof (sanjay)
+ * Add a few more GetPC() functions, including for AMD (csilvers)
+ * Better method for overriding pthread functions (menage)
+ * (Hacky) fix to avoid overwriting profile files after fork() (csilvers)
+ * Crashing bugfix involving dumping heaps on small-stack threads (tudor)
+ * Allow library versions with letters at the end (csilvers)
+ * Config fixes for systems that don't define PATH_MAX (csilvers)
+ * Confix fixes so we no longer need config.h after install (csilvers)
+ * Fix to pprof to correctly read very big cpu profiles (csilvers)
+ * Fix to pprof to deal with new commandline flags in modern gv's
+ * Better error reporting when we can't access /proc/maps (etune)
+ * Get rid of the libc-preallocate code (which could crash on some
+ systems); no longer needed with local-threads fix (csilvers)
+
+Tue Feb 8 09:57:17 2005 Google Inc. <opensource@google.com>
+
+ * google-perftools: initial release:
+ The google-perftools package contains some utilities to improve
+ and analyze the performance of C++ programs. This includes an
+ optimized thread-caching malloc() and cpu and heap profiling
+ utilities.
diff --git a/chromium/third_party/tcmalloc/vendor/INSTALL b/chromium/third_party/tcmalloc/vendor/INSTALL
new file mode 100644
index 00000000000..4a09e1482f6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/INSTALL
@@ -0,0 +1,539 @@
+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
+================================
+
+*** 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, experimental 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.
+
+This feature is still very experimental; it's not even a configure
+flag yet. To build libtcmalloc with large pages, run
+
+ ./configure <normal flags> CXXFLAGS=-DTCMALLOC_LARGE_PAGES
+
+(or add -DTCMALLOC_LARGE_PAGES to your existing CXXFLAGS argument).
+
+
+*** 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 <normal flags> 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: 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/chromium/third_party/tcmalloc/vendor/Makefile.am b/chromium/third_party/tcmalloc/vendor/Makefile.am
new file mode 100644
index 00000000000..93ed11ed31d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/Makefile.am
@@ -0,0 +1,1386 @@
+## 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
+
+# This is so we can #include <gperftools/foo>
+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. We also tell gcc
+# that malloc, free, realloc, mmap, etc. are not builtins (these flags
+# are supported since gcc 3.1.1). gcc doesn't think most of them are
+# builtins now in any case, but it's best to be explicit in case that
+# changes one day. gcc ignores functions it doesn't understand.
+if GCC
+AM_CXXFLAGS += -Wall -Wwrite-strings -Woverloaded-virtual \
+ -Wno-sign-compare \
+ -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc \
+ -fno-builtin-calloc -fno-builtin-cfree \
+ -fno-builtin-memalign -fno-builtin-posix_memalign \
+ -fno-builtin-valloc -fno-builtin-pvalloc
+# On i386, -mmmx is needed for the mmx-based instructions in
+# atomicops-internal-x86.h.
+if I386
+AM_CXXFLAGS += -mmmx
+endif I386
+endif GCC
+if HAVE_W_NO_UNUSED_RESULT
+AM_CXXFLAGS += -Wno-unused-result
+endif HAVE_W_NO_UNUSED_RESULT
+
+# 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)
+
+# We know our low-level code cannot trigger an exception. On some
+# systems, such as cygwin, it would be disastrous if they did, because
+# the exception handler might call malloc! If our low-level routines
+# raised an exception within the malloc, they'd deadlock. Luckily,
+# we control all this code, and do not need exceptions for it.
+if GCC
+NO_EXCEPTIONS = -fno-exceptions
+else !GCC
+NO_EXCEPTIONS =
+endif !GCC
+
+# 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 X86_64_AND_NO_FP_BY_DEFAULT
+if ENABLE_FRAME_POINTERS
+AM_CXXFLAGS += -fno-omit-frame-pointer
+else
+ # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
+ # before setting this.
+AM_CXXFLAGS += -DNO_FRAME_POINTER
+endif !ENABLE_FRAME_POINTERS
+endif X86_64_AND_NO_FP_BY_DEFAULT
+
+# 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 malloc_stats -W mallopt -W mallinfo \
+ -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 \
+ src/windows/google/tcmalloc.h
+
+docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
+# 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
+
+# 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 += doc/index.html doc/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 \
+ src/third_party/valgrind.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/base/logging.h \
+ src/base/commandlineflags.h \
+ src/base/cycleclock.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)
+
+# 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/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/synchronization_profiling.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-windows.h \
+ src/base/atomicops-internals-x86.h
+noinst_LTLIBRARIES += libspinlock.la
+libspinlock_la_SOURCES = src/base/spinlock.cc \
+ src/base/spinlock_internal.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.
+MAYBE_THREADS_CC =
+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
+MAYBE_THREADS_CC = src/maybe_threads.cc
+SYSTEM_ALLOC_CC = src/system-alloc.cc
+endif !MINGW
+
+# Add this whether or not we're under MinGW, to keep the tarball complete.
+WINDOWS_PROJECTS += vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj
+# Because we've commented out the test, above, we have to explicitly add
+# the test files to the tarball or automake will leave them out.
+WINDOWS_PROJECTS += src/windows/preamble_patcher_test.cc \
+ src/windows/shortproc.asm \
+ src/windows/auto_testing_hook.h
+
+### Unittests
+TESTS += low_level_alloc_unittest
+WINDOWS_PROJECTS += vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
+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 \
+ $(MAYBE_THREADS_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)
+
+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_config.h \
+ src/stacktrace_generic-inl.h \
+ src/stacktrace_libunwind-inl.h \
+ src/stacktrace_arm-inl.h \
+ src/stacktrace_powerpc-inl.h \
+ src/stacktrace_x86-inl.h \
+ src/stacktrace_win32-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)
+
+### 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
+
+### 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 = 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
+
+### Documentation
+dist_man_MANS = doc/pprof.1
+dist_doc_DATA += doc/pprof_remote_servers.html
+
+# On MSVC, we need our own versions of addr2line and nm to work with pprof.
+WINDOWS_PROJECTS += vsprojects/nm-pdb/nm-pdb.vcproj
+WINDOWS_PROJECTS += vsprojects/addr2line-pdb/addr2line-pdb.vcproj
+# 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 \
+ src/maybe_threads.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/stacktrace.h
+TCMALLOC_MINIMAL_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) $(SG_TCMALLOC_MINIMAL_INCLUDES)
+perftoolsinclude_HEADERS += $(SG_TCMALLOC_MINIMAL_INCLUDES)
+
+### Making the library
+
+# As we describe at the top of this file, we want to turn off exceptions
+# for all files in this library -- except tcmalloc.cc which needs them
+# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
+# to separate into two libraries.
+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 \
+ $(MAYBE_THREADS_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 \
+ $(PTHREAD_CFLAGS) -DNDEBUG \
+ $(AM_CXXFLAGS) $(NO_EXCEPTIONS)
+libtcmalloc_minimal_internal_la_LDFLAGS = $(PTHREAD_CFLAGS)
+libtcmalloc_minimal_internal_la_LIBADD = $(PTHREAD_LIBS) $(LIBSPINLOCK)
+
+lib_LTLIBRARIES += libtcmalloc_minimal.la
+WINDOWS_PROJECTS += vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
+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 = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
+libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la $(PTHREAD_LIBS)
+
+# 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.vcproj
+WINDOWS_PROJECTS += vsprojects/tmu-static/tmu-static.vcproj
+tcmalloc_minimal_unittest_SOURCES = src/tests/tcmalloc_unittest.cc \
+ src/tests/testutil.h src/tests/testutil.cc \
+ $(TCMALLOC_UNITTEST_INCLUDES)
+tcmalloc_minimal_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(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)
+
+TESTS += tcmalloc_minimal_large_unittest
+WINDOWS_PROJECTS += vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
+tcmalloc_minimal_large_unittest_SOURCES = src/tests/tcmalloc_large_unittest.cc
+tcmalloc_minimal_large_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+tcmalloc_minimal_large_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+tcmalloc_minimal_large_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.vcproj
+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
+
+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.vcproj
+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.vcproj
+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.vcproj
+markidle_unittest_SOURCES = src/tests/markidle_unittest.cc \
+ src/config_for_unittests.h \
+ src/tests/testutil.h src/tests/testutil.cc
+markidle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(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.vcproj
+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.vcproj
+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.vcproj
+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 static linkage, because libtcmalloc.a isn't
+# happy with C linkage (it misses the stdc++ library). Likewise 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
+if !ENABLE_STATIC
+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)
+endif !ENABLE_STATIC
+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.vcproj
+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.vcproj
+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.vcproj
+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.vcproj
+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.vcproj
+thread_dealloc_unittest_SOURCES = src/tests/thread_dealloc_unittest.cc \
+ src/config_for_unittests.h \
+ src/tests/testutil.h src/tests/testutil.cc
+thread_dealloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+thread_dealloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+thread_dealloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
+
+### Documentation
+dist_doc_DATA += doc/tcmalloc.html \
+ doc/overview.gif \
+ doc/pageheap.gif \
+ doc/spanmap.gif \
+ doc/threadheap.gif \
+ doc/t-test1.times.txt \
+ doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \
+ doc/tcmalloc-opspersec.vs.size.1.threads.png \
+ doc/tcmalloc-opspersec.vs.size.12.threads.png \
+ doc/tcmalloc-opspersec.vs.size.16.threads.png \
+ doc/tcmalloc-opspersec.vs.size.2.threads.png \
+ doc/tcmalloc-opspersec.vs.size.20.threads.png \
+ doc/tcmalloc-opspersec.vs.size.3.threads.png \
+ doc/tcmalloc-opspersec.vs.size.4.threads.png \
+ doc/tcmalloc-opspersec.vs.size.5.threads.png \
+ doc/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 += doc/overview.dot \
+ doc/pageheap.dot \
+ doc/spanmap.dot \
+ doc/threadheap.dot
+
+
+### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation)
+
+# Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its
+# API. Luckily, we can reuse everything else from tcmalloc_minimal.
+
+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
+
+
+### ------- 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
+SG_TCMALLOC_INCLUDES = $(SG_TCMALLOC_MINIMAL_INCLUDES) \
+ src/gperftools/heap-profiler.h \
+ src/gperftools/heap-checker.h
+TCMALLOC_INCLUDES = $(S_TCMALLOC_INCLUDES) $(SG_TCMALLOC_INCLUDES)
+perftoolsinclude_HEADERS += $(SG_TCMALLOC_INCLUDES)
+
+### Making the library
+
+# As we describe at the top of this file, we want to turn off exceptions
+# for all files in this library -- except tcmalloc.cc which needs them
+# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
+# to separate into two libraries.
+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 \
+ src/memory_region_map.cc
+libtcmalloc_internal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG \
+ $(AM_CXXFLAGS) $(NO_EXCEPTIONS)
+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)
+libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
+libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
+libtcmalloc_la_LIBADD = libtcmalloc_internal.la $(PTHREAD_LIBS)
+
+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
+libtcmalloc_la_SOURCES += $(HEAP_CHECKER_SOURCES)
+else !WITH_HEAP_CHECKER
+HEAP_CHECKER_SOURCES =
+libtcmalloc_internal_la_CXXFLAGS += -DNO_HEAP_CHECK
+libtcmalloc_la_CXXFLAGS += -DNO_HEAP_CHECK
+endif !WITH_HEAP_CHECKER
+
+LIBTCMALLOC = libtcmalloc.la
+
+LIBS_TO_WEAKEN += libtcmalloc.la
+
+### Unittests
+
+TESTS += 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)
+
+# 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 += 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.vcproj
+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 += doc/heapprofile.html doc/heap-example1.png
+endif WITH_HEAP_PROFILER
+
+if WITH_HEAP_CHECKER
+dist_doc_DATA += doc/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 \
+ src/gperftools/stacktrace.h
+CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_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
+# We have to include ProfileData for profiledata_unittest
+CPU_PROFILER_SYMBOLS = '(ProfilerStart|ProfilerStartWithOptions|ProfilerStop|ProfilerFlush|ProfilerEnable|ProfilerDisable|ProfilingIsEnabledForAllThreads|ProfilerRegisterThread|ProfilerGetCurrentState|ProfilerState|ProfileData|ProfileHandler)'
+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.vcproj
+getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
+
+TESTS += profiledata_unittest
+#WINDOWS_PROJECTS += vsprojects/profiledata_unittest/profiledata_unittest.vcproj
+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 += doc/cpuprofile.html \
+ doc/cpuprofile-fileformat.html \
+ doc/pprof-test-big.gif \
+ doc/pprof-test.gif \
+ doc/pprof-vsnprintf-big.gif \
+ doc/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_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
+
+# Windows wants write permission to .vcproj files and maybe even sln files.
+dist-hook:
+ test -e "$(distdir)/vsprojects" \
+ && chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
+
+EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
+ $(SCRIPTS) libtool \
+ src/windows/get_mangled_names.cc src/windows/override_functions.cc \
+ src/windows/config.h src/windows/gperftools/tcmalloc.h \
+ $(WINDOWS_PROJECTS) \
+ src/solaris/libstdc++.la
diff --git a/chromium/third_party/tcmalloc/vendor/Makefile.in b/chromium/third_party/tcmalloc/vendor/Makefile.in
new file mode 100644
index 00000000000..d90e83e570b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/Makefile.in
@@ -0,0 +1,5373 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 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@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@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. We also tell gcc
+# that malloc, free, realloc, mmap, etc. are not builtins (these flags
+# are supported since gcc 3.1.1). gcc doesn't think most of them are
+# builtins now in any case, but it's best to be explicit in case that
+# changes one day. gcc ignores functions it doesn't understand.
+@GCC_TRUE@am__append_2 = -Wall -Wwrite-strings -Woverloaded-virtual \
+@GCC_TRUE@ -Wno-sign-compare \
+@GCC_TRUE@ -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc \
+@GCC_TRUE@ -fno-builtin-calloc -fno-builtin-cfree \
+@GCC_TRUE@ -fno-builtin-memalign -fno-builtin-posix_memalign \
+@GCC_TRUE@ -fno-builtin-valloc -fno-builtin-pvalloc
+
+# On i386, -mmmx is needed for the mmx-based instructions in
+# atomicops-internal-x86.h.
+@GCC_TRUE@@I386_TRUE@am__append_3 = -mmmx
+@HAVE_W_NO_UNUSED_RESULT_TRUE@am__append_4 = -Wno-unused-result
+
+# 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_TRUE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_5 = -fno-omit-frame-pointer
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@am__append_6 = -DNO_FRAME_POINTER
+@MINGW_TRUE@am__append_7 = -Wl,-u__tcmalloc
+TESTS = low_level_alloc_unittest$(EXEEXT) atomicops_unittest$(EXEEXT) \
+ $(am__EXEEXT_9) tcmalloc_minimal_unittest$(EXEEXT) \
+ tcmalloc_minimal_large_unittest$(EXEEXT) $(am__append_17) \
+ addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \
+ 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_11) $(am__EXEEXT_12) page_heap_test$(EXEEXT) \
+ pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \
+ stack_trace_table_test$(EXEEXT) \
+ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_13) \
+ $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_29) \
+ $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18) \
+ $(am__EXEEXT_19) $(am__append_49) $(am__EXEEXT_20) \
+ $(am__append_58) $(am__append_60) $(am__EXEEXT_21) \
+ $(am__EXEEXT_22)
+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_23)
+bin_PROGRAMS =
+@MINGW_TRUE@am__append_8 = 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_9 = -lshlwapi
+@MINGW_FALSE@am__append_10 = libspinlock.la
+@WITH_STACK_TRACE_TRUE@am__append_11 = $(SG_STACKTRACE_INCLUDES)
+
+### Making the library
+@WITH_STACK_TRACE_TRUE@am__append_12 = libstacktrace.la
+
+### Unittests
+@WITH_STACK_TRACE_TRUE@am__append_13 = stacktrace_unittest
+
+### Documentation
+@WITH_STACK_TRACE_TRUE@am__append_14 = doc/pprof_remote_servers.html
+
+# Let unittests find pprof if they need to run it
+@WITH_STACK_TRACE_TRUE@am__append_15 = PPROF_PATH=$(top_srcdir)/src/pprof
+
+# 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_16 = \
+@WITH_STACK_TRACE_TRUE@ vsprojects/nm-pdb/nm-pdb.vcproj \
+@WITH_STACK_TRACE_TRUE@ vsprojects/addr2line-pdb/addr2line-pdb.vcproj \
+@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_17 = maybe_threads_unittest.sh$(EXEEXT)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_18 = $(maybe_threads_unittest_sh_SOURCES)
+@MINGW_TRUE@am__append_19 = src/windows/port.h src/windows/port.cc
+@MINGW_FALSE@am__append_20 = system_alloc_unittest
+
+# This doesn't work with static linkage, because libtcmalloc.a isn't
+# happy with C linkage (it misses the stdc++ library). Likewise with
+# mingw, which links foo.a even though it doesn't set ENABLE_STATIC.
+# TODO(csilvers): set enable_static=true in configure.ac:36?
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__append_21 = malloc_extension_c_test
+# -ansi here is just to help ensure the code is bog-standard C.
+@ENABLE_STATIC_FALSE@@GCC_TRUE@@MINGW_FALSE@am__append_22 = -ansi
+@MINGW_FALSE@@OSX_FALSE@am__append_23 = memalign_unittest
+
+### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation)
+
+# Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its
+# API. Luckily, we can reuse everything else from tcmalloc_minimal.
+@WITH_DEBUGALLOC_TRUE@am__append_24 = libtcmalloc_minimal_debug.la
+@WITH_DEBUGALLOC_TRUE@am__append_25 = libtcmalloc_minimal_debug.la
+
+### Unittests
+@WITH_DEBUGALLOC_TRUE@am__append_26 = tcmalloc_minimal_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test
+@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__append_27 = memalign_debug_unittest
+@WITH_DEBUGALLOC_TRUE@am__append_28 = 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_29 = debugallocation_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_30 = $(debugallocation_test_sh_SOURCES)
+
+# This is the sub-program used by debugallocation_test.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__append_31 = debugallocation_test
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = $(SG_TCMALLOC_INCLUDES)
+
+### Making the library
+
+# As we describe at the top of this file, we want to turn off exceptions
+# for all files in this library -- except tcmalloc.cc which needs them
+# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
+# to separate into two libraries.
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = libtcmalloc_internal.la
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = libtcmalloc.la
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = $(HEAP_CHECKER_SOURCES)
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_36 = -DNO_HEAP_CHECK
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_37 = -DNO_HEAP_CHECK
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_38 = libtcmalloc.la
+
+### Unittests
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_39 = tcmalloc_unittest
+@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_40 = tcmalloc_both_unittest
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_41 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_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_42 = 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_43 = vsprojects/sampler_test/sampler_test.vcproj
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = $(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_45 = sampling_test
+
+# 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_46 = \
+@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT) \
+@WITH_HEAP_PROFILER_TRUE@ simple_compat_test
+@WITH_HEAP_PROFILER_TRUE@am__append_47 = $(heap_profiler_unittest_sh_SOURCES)
+
+# These are sub-programs used by heap-profiler_unittest.sh
+@WITH_HEAP_PROFILER_TRUE@am__append_48 = heap-profiler_unittest
+@WITH_HEAP_CHECKER_TRUE@am__append_49 = \
+@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_50 = \
+@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_51 = heap-checker_unittest
+
+### Documentation (above and beyond tcmalloc_minimal documentation)
+@WITH_HEAP_PROFILER_TRUE@am__append_52 = doc/heapprofile.html doc/heap-example1.png
+@WITH_HEAP_CHECKER_TRUE@am__append_53 = doc/heap_checker.html
+
+### ------- tcmalloc with debugallocation
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_54 = libtcmalloc_debug.la
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_55 = libtcmalloc_debug.la
+
+### Unittests
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_56 = 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_57 = sampling_debug_test
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_58 = 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_59 = heap-profiler_debug_unittest
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_60 = 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_61 = heap-checker_debug_unittest
+@WITH_CPU_PROFILER_TRUE@am__append_62 = $(SG_CPU_PROFILER_INCLUDES)
+
+### Making the library
+@WITH_CPU_PROFILER_TRUE@am__append_63 = libprofiler.la
+
+### Unittests
+@WITH_CPU_PROFILER_TRUE@am__append_64 = 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_65 = $(profiler_unittest_sh_SOURCES)
+
+# These are sub-programs used by profiler_unittest.sh
+@WITH_CPU_PROFILER_TRUE@am__append_66 = 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_67 = doc/cpuprofile.html \
+@WITH_CPU_PROFILER_TRUE@ doc/cpuprofile-fileformat.html \
+@WITH_CPU_PROFILER_TRUE@ doc/pprof-test-big.gif \
+@WITH_CPU_PROFILER_TRUE@ doc/pprof-test.gif \
+@WITH_CPU_PROFILER_TRUE@ doc/pprof-vsnprintf-big.gif \
+@WITH_CPU_PROFILER_TRUE@ doc/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_68 = libtcmalloc_and_profiler.la
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_69 = tcmalloc_and_profiler_unittest
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_70 = libtcmalloc_and_profiler.la
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(am__dist_doc_DATA_DIST) \
+ $(am__perftoolsinclude_HEADERS_DIST) $(dist_man_MANS) \
+ $(googleinclude_HEADERS) $(noinst_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/configure $(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 TODO compile config.guess \
+ config.sub depcomp install-sh ltmain.sh missing mkinstalldirs
+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/compiler_characteristics.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/namespaces.m4 \
+ $(top_srcdir)/m4/pc_from_ucontext.m4 \
+ $(top_srcdir)/m4/program_invocation_name.m4 \
+ $(top_srcdir)/m4/stl_namespace.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = src/gperftools/tcmalloc.h \
+ src/windows/gperftools/tcmalloc.h
+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 = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
+ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
+ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(googleincludedir)" \
+ "$(DESTDIR)$(perftoolsincludedir)" \
+ "$(DESTDIR)$(perftoolsincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
+liblogging_la_LIBADD =
+am__objects_1 =
+am_liblogging_la_OBJECTS = logging.lo dynamic_annotations.lo \
+ $(am__objects_1)
+liblogging_la_OBJECTS = $(am_liblogging_la_OBJECTS)
+@WITH_CPU_PROFILER_TRUE@libprofiler_la_DEPENDENCIES = \
+@WITH_CPU_PROFILER_TRUE@ libstacktrace.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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.h \
+ src/base/dynamic_annotations.h src/third_party/valgrind.h \
+ src/gperftools/profiler.h src/gperftools/stacktrace.h
+@WITH_CPU_PROFILER_TRUE@am__objects_2 = $(am__objects_1) \
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
+@WITH_CPU_PROFILER_TRUE@am__objects_3 = $(am__objects_2) \
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
+@WITH_CPU_PROFILER_TRUE@am_libprofiler_la_OBJECTS = profiler.lo \
+@WITH_CPU_PROFILER_TRUE@ profile-handler.lo profiledata.lo \
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_3)
+libprofiler_la_OBJECTS = $(am_libprofiler_la_OBJECTS)
+libprofiler_la_LINK = $(LIBTOOL) --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)
+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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.h
+@MINGW_FALSE@am_libspinlock_la_OBJECTS = spinlock.lo \
+@MINGW_FALSE@ spinlock_internal.lo atomicops-internals-x86.lo \
+@MINGW_FALSE@ $(am__objects_1)
+@MINGW_TRUE@am_libspinlock_la_OBJECTS = spinlock.lo \
+@MINGW_TRUE@ spinlock_internal.lo $(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_config.h src/stacktrace_generic-inl.h \
+ src/stacktrace_libunwind-inl.h src/stacktrace_arm-inl.h \
+ src/stacktrace_powerpc-inl.h src/stacktrace_x86-inl.h \
+ src/stacktrace_win32-inl.h src/base/elf_mem_image.h \
+ src/base/vdso_support.h src/gperftools/stacktrace.h
+@WITH_STACK_TRACE_TRUE@am__objects_4 = $(am__objects_1) \
+@WITH_STACK_TRACE_TRUE@ $(am__objects_1)
+@WITH_STACK_TRACE_TRUE@am_libstacktrace_la_OBJECTS = stacktrace.lo \
+@WITH_STACK_TRACE_TRUE@ elf_mem_image.lo vdso_support.lo \
+@WITH_STACK_TRACE_TRUE@ $(am__objects_4)
+libstacktrace_la_OBJECTS = $(am_libstacktrace_la_OBJECTS)
+libstacktrace_la_LINK = $(LIBTOOL) --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 = 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@ $(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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.h \
+ src/base/logging.h src/base/dynamic_annotations.h \
+ src/third_party/valgrind.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/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \
+ src/gperftools/malloc_extension.h \
+ src/gperftools/malloc_extension_c.h \
+ src/gperftools/stacktrace.h src/gperftools/heap-profiler.h \
+ src/gperftools/heap-checker.h src/base/thread_lister.c \
+ src/base/linuxthreads.cc src/heap-checker.cc \
+ src/heap-checker-bcad.cc
+@MINGW_FALSE@am__objects_5 = libtcmalloc_la-tcmalloc.lo
+am__objects_6 = $(am__objects_1)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_7 = $(am__objects_6) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_8 = $(am__objects_1)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_9 = $(am__objects_7) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_8)
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_10 = thread_lister.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-linuxthreads.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-heap-checker.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-heap-checker-bcad.lo
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_11 = $(am__objects_10)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_la_OBJECTS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_11)
+libtcmalloc_la_OBJECTS = $(am_libtcmalloc_la_OBJECTS)
+libtcmalloc_la_LINK = $(LIBTOOL) --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@ $(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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.h \
+ src/base/logging.h src/base/dynamic_annotations.h \
+ src/third_party/valgrind.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/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \
+ src/gperftools/malloc_extension.h \
+ src/gperftools/malloc_extension_c.h \
+ src/gperftools/stacktrace.h src/gperftools/heap-profiler.h \
+ src/gperftools/heap-checker.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 = libtcmalloc_and_profiler_la-tcmalloc.lo
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_13 = thread_lister.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-linuxthreads.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-heap-checker.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-heap-checker-bcad.lo
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_14 = $(am__objects_13)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_15 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_12) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_14)
+@WITH_CPU_PROFILER_TRUE@am__objects_16 = libtcmalloc_and_profiler_la-profiler.lo \
+@WITH_CPU_PROFILER_TRUE@ libtcmalloc_and_profiler_la-profile-handler.lo \
+@WITH_CPU_PROFILER_TRUE@ libtcmalloc_and_profiler_la-profiledata.lo \
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_3)
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_OBJECTS = $(am__objects_15) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_16)
+libtcmalloc_and_profiler_la_OBJECTS = \
+ $(am_libtcmalloc_and_profiler_la_OBJECTS)
+libtcmalloc_and_profiler_la_LINK = $(LIBTOOL) --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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.h \
+ src/base/logging.h src/base/dynamic_annotations.h \
+ src/third_party/valgrind.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/gperftools/malloc_hook.h src/gperftools/malloc_hook_c.h \
+ src/gperftools/malloc_extension.h \
+ src/gperftools/malloc_extension_c.h \
+ src/gperftools/stacktrace.h src/gperftools/heap-profiler.h \
+ src/gperftools/heap-checker.h
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_17 = thread_lister.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-linuxthreads.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-heap-checker.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-heap-checker-bcad.lo
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_debug_la_OBJECTS = libtcmalloc_debug_la-debugallocation.lo \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_17) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9)
+libtcmalloc_debug_la_OBJECTS = $(am_libtcmalloc_debug_la_OBJECTS)
+libtcmalloc_debug_la_LINK = $(LIBTOOL) --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/maybe_threads.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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.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/stacktrace.h src/base/logging.h \
+ src/base/dynamic_annotations.h src/third_party/valgrind.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/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/memory_region_map.cc
+@MINGW_FALSE@am__objects_18 = libtcmalloc_internal_la-system-alloc.lo
+@MINGW_FALSE@am__objects_19 = \
+@MINGW_FALSE@ libtcmalloc_internal_la-maybe_threads.lo
+am__objects_20 = $(am__objects_6) $(am__objects_1)
+am__objects_21 = libtcmalloc_internal_la-common.lo \
+ libtcmalloc_internal_la-internal_logging.lo $(am__objects_18) \
+ libtcmalloc_internal_la-memfs_malloc.lo \
+ libtcmalloc_internal_la-central_freelist.lo \
+ libtcmalloc_internal_la-page_heap.lo \
+ libtcmalloc_internal_la-sampler.lo \
+ libtcmalloc_internal_la-span.lo \
+ libtcmalloc_internal_la-stack_trace_table.lo \
+ libtcmalloc_internal_la-static_vars.lo \
+ libtcmalloc_internal_la-symbolize.lo \
+ libtcmalloc_internal_la-thread_cache.lo \
+ libtcmalloc_internal_la-malloc_hook.lo \
+ libtcmalloc_internal_la-malloc_extension.lo $(am__objects_19) \
+ $(am__objects_20)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_la_OBJECTS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_21) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-low_level_alloc.lo \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-heap-profile-table.lo \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-heap-profiler.lo \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-raw_printer.lo \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-memory_region_map.lo
+libtcmalloc_internal_la_OBJECTS = \
+ $(am_libtcmalloc_internal_la_OBJECTS)
+libtcmalloc_internal_la_LINK = $(LIBTOOL) --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 =
+libtcmalloc_minimal_la_DEPENDENCIES = libtcmalloc_minimal_internal.la \
+ $(am__DEPENDENCIES_1)
+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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.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/stacktrace.h
+@MINGW_FALSE@am__objects_22 = libtcmalloc_minimal_la-tcmalloc.lo
+am_libtcmalloc_minimal_la_OBJECTS = $(am__objects_22) \
+ $(am__objects_20)
+libtcmalloc_minimal_la_OBJECTS = $(am_libtcmalloc_minimal_la_OBJECTS)
+libtcmalloc_minimal_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) \
+ $(libtcmalloc_minimal_la_LDFLAGS) $(LDFLAGS) -o $@
+am__DEPENDENCIES_3 = libtcmalloc_minimal_internal.la \
+ $(am__DEPENDENCIES_1)
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_3)
+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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.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/stacktrace.h
+@WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_OBJECTS = libtcmalloc_minimal_debug_la-debugallocation.lo \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_20)
+libtcmalloc_minimal_debug_la_OBJECTS = \
+ $(am_libtcmalloc_minimal_debug_la_OBJECTS)
+libtcmalloc_minimal_debug_la_LINK = $(LIBTOOL) --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 = $(am__DEPENDENCIES_1) \
+ $(LIBSPINLOCK)
+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/maybe_threads.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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.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/maybe_threads.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/stacktrace.h
+@MINGW_FALSE@am__objects_23 = \
+@MINGW_FALSE@ libtcmalloc_minimal_internal_la-system-alloc.lo
+@MINGW_FALSE@am__objects_24 = \
+@MINGW_FALSE@ libtcmalloc_minimal_internal_la-maybe_threads.lo
+am_libtcmalloc_minimal_internal_la_OBJECTS = \
+ libtcmalloc_minimal_internal_la-common.lo \
+ libtcmalloc_minimal_internal_la-internal_logging.lo \
+ $(am__objects_23) \
+ libtcmalloc_minimal_internal_la-memfs_malloc.lo \
+ libtcmalloc_minimal_internal_la-central_freelist.lo \
+ libtcmalloc_minimal_internal_la-page_heap.lo \
+ libtcmalloc_minimal_internal_la-sampler.lo \
+ libtcmalloc_minimal_internal_la-span.lo \
+ libtcmalloc_minimal_internal_la-stack_trace_table.lo \
+ libtcmalloc_minimal_internal_la-static_vars.lo \
+ libtcmalloc_minimal_internal_la-symbolize.lo \
+ libtcmalloc_minimal_internal_la-thread_cache.lo \
+ libtcmalloc_minimal_internal_la-malloc_hook.lo \
+ libtcmalloc_minimal_internal_la-malloc_extension.lo \
+ $(am__objects_24) $(am__objects_20)
+libtcmalloc_minimal_internal_la_OBJECTS = \
+ $(am_libtcmalloc_minimal_internal_la_OBJECTS)
+libtcmalloc_minimal_internal_la_LINK = $(LIBTOOL) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) \
+ $(libtcmalloc_minimal_internal_la_LDFLAGS) $(LDFLAGS) -o $@
+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/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) port.lo \
+@MINGW_TRUE@ ia32_modrm_map.lo ia32_opcode_map.lo \
+@MINGW_TRUE@ mini_disassembler.lo patch_functions.lo \
+@MINGW_TRUE@ preamble_patcher.lo preamble_patcher_with_stub.lo
+libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS)
+@MINGW_TRUE@am_libwindows_la_rpath =
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+@WITH_DEBUGALLOC_TRUE@@WITH_STACK_TRACE_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_2 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test$(EXEEXT)
+@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_3 = \
+@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest$(EXEEXT)
+@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_4 = heap-checker_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_5 = sampling_debug_test$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_6 = heap-profiler_debug_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_7 = heap-checker_debug_unittest$(EXEEXT)
+@WITH_CPU_PROFILER_TRUE@am__EXEEXT_8 = 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_9 = stacktrace_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_10 = system_alloc_unittest$(EXEEXT)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@am__EXEEXT_11 = malloc_extension_c_test$(EXEEXT)
+@MINGW_FALSE@@OSX_FALSE@am__EXEEXT_12 = memalign_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@am__EXEEXT_13 = tcmalloc_minimal_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT)
+@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am__EXEEXT_14 = memalign_debug_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@am__EXEEXT_15 = realloc_debug_unittest$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_16 = tcmalloc_unittest$(EXEEXT)
+@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_17 = tcmalloc_both_unittest$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_18 = tcmalloc_large_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_19 = \
+@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_20 = 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_21 = 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_22 = tcmalloc_and_profiler_unittest$(EXEEXT)
+am__EXEEXT_23 = low_level_alloc_unittest$(EXEEXT) \
+ atomicops_unittest$(EXEEXT) $(am__EXEEXT_9) \
+ tcmalloc_minimal_unittest$(EXEEXT) \
+ tcmalloc_minimal_large_unittest$(EXEEXT) $(am__append_17) \
+ addressmap_unittest$(EXEEXT) $(am__EXEEXT_10) \
+ 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_11) $(am__EXEEXT_12) page_heap_test$(EXEEXT) \
+ pagemap_unittest$(EXEEXT) realloc_unittest$(EXEEXT) \
+ stack_trace_table_test$(EXEEXT) \
+ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_13) \
+ $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__append_29) \
+ $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18) \
+ $(am__EXEEXT_19) $(am__append_49) $(am__EXEEXT_20) \
+ $(am__append_58) $(am__append_60) $(am__EXEEXT_21) \
+ $(am__EXEEXT_22)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+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/third_party/valgrind.h src/windows/port.h \
+ src/windows/port.cc
+@MINGW_TRUE@am__objects_25 = addressmap_unittest-port.$(OBJEXT)
+am_addressmap_unittest_OBJECTS = \
+ addressmap_unittest-addressmap_unittest.$(OBJEXT) \
+ $(am__objects_6) $(am__objects_25)
+addressmap_unittest_OBJECTS = $(am_addressmap_unittest_OBJECTS)
+addressmap_unittest_DEPENDENCIES = liblogging.la
+addressmap_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am_atomicops_unittest_OBJECTS = atomicops_unittest.$(OBJEXT) \
+ $(am__objects_6)
+atomicops_unittest_OBJECTS = $(am_atomicops_unittest_OBJECTS)
+atomicops_unittest_DEPENDENCIES = $(LIBSPINLOCK)
+am_current_allocated_bytes_test_OBJECTS = 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) --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 = 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) --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 = frag_unittest-frag_unittest.$(OBJEXT)
+frag_unittest_OBJECTS = $(am_frag_unittest_OBJECTS)
+frag_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+frag_unittest_LINK = $(LIBTOOL) --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 = 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 src/third_party/valgrind.h
+@WITH_HEAP_CHECKER_TRUE@am__objects_26 = $(am__objects_1)
+@WITH_HEAP_CHECKER_TRUE@am__objects_27 = heap_checker_debug_unittest-heap-checker_unittest.$(OBJEXT) \
+@WITH_HEAP_CHECKER_TRUE@ $(am__objects_26)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am_heap_checker_debug_unittest_OBJECTS = $(am__objects_27)
+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) --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 src/third_party/valgrind.h
+@WITH_HEAP_CHECKER_TRUE@am_heap_checker_unittest_OBJECTS = heap_checker_unittest-heap-checker_unittest.$(OBJEXT) \
+@WITH_HEAP_CHECKER_TRUE@ $(am__objects_26)
+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) --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_28 = 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_28)
+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) --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 = 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) --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/maybe_threads.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/synchronization_profiling.h \
+ src/base/atomicops-internals-arm-generic.h \
+ src/base/atomicops-internals-arm-v6plus.h src/base/logging.h \
+ src/base/commandlineflags.h src/base/dynamic_annotations.h \
+ src/third_party/valgrind.h
+@MINGW_FALSE@am__objects_29 = \
+@MINGW_FALSE@ low_level_alloc_unittest-maybe_threads.$(OBJEXT)
+am__objects_30 = $(am__objects_1) $(am__objects_1)
+am_low_level_alloc_unittest_OBJECTS = \
+ low_level_alloc_unittest-low_level_alloc.$(OBJEXT) \
+ low_level_alloc_unittest-malloc_hook.$(OBJEXT) \
+ $(am__objects_29) \
+ low_level_alloc_unittest-low_level_alloc_unittest.$(OBJEXT) \
+ $(am__objects_30)
+low_level_alloc_unittest_OBJECTS = \
+ $(am_low_level_alloc_unittest_OBJECTS)
+low_level_alloc_unittest_DEPENDENCIES = $(LIBSPINLOCK)
+low_level_alloc_unittest_LINK = $(LIBTOOL) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) $(AM_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
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@am_malloc_extension_c_test_OBJECTS = malloc_extension_c_test-malloc_extension_c_test.$(OBJEXT)
+malloc_extension_c_test_OBJECTS = \
+ $(am_malloc_extension_c_test_OBJECTS)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_DEPENDENCIES = \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(LIBTCMALLOC_MINIMAL) \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__DEPENDENCIES_1)
+malloc_extension_c_test_LINK = $(LIBTOOL) --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_31 = \
+ malloc_extension_debug_test-malloc_extension_test.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@am_malloc_extension_debug_test_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_31)
+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) --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 = \
+ 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) \
+ $(malloc_extension_test_LDFLAGS) $(LDFLAGS) -o $@
+am_malloc_hook_test_OBJECTS = \
+ malloc_hook_test-malloc_hook_test.$(OBJEXT) \
+ 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) \
+ $(malloc_hook_test_LDFLAGS) $(LDFLAGS) -o $@
+am_markidle_unittest_OBJECTS = \
+ markidle_unittest-markidle_unittest.$(OBJEXT) \
+ markidle_unittest-testutil.$(OBJEXT)
+markidle_unittest_OBJECTS = $(am_markidle_unittest_OBJECTS)
+markidle_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+markidle_unittest_LINK = $(LIBTOOL) --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_32 = memalign_debug_unittest-memalign_unittest.$(OBJEXT) \
+@MINGW_FALSE@@OSX_FALSE@ memalign_debug_unittest-testutil.$(OBJEXT)
+@MINGW_FALSE@@OSX_FALSE@@WITH_DEBUGALLOC_TRUE@am_memalign_debug_unittest_OBJECTS = $(am__objects_32)
+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) --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 = memalign_unittest-memalign_unittest.$(OBJEXT) \
+@MINGW_FALSE@@OSX_FALSE@ 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(memalign_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_packed_cache_test_OBJECTS = \
+ 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) \
+ $(packed_cache_test_LDFLAGS) $(LDFLAGS) -o $@
+am_page_heap_test_OBJECTS = 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(page_heap_test_CXXFLAGS) $(CXXFLAGS) \
+ $(page_heap_test_LDFLAGS) $(LDFLAGS) -o $@
+am_pagemap_unittest_OBJECTS = \
+ pagemap_unittest-pagemap_unittest.$(OBJEXT)
+pagemap_unittest_OBJECTS = $(am_pagemap_unittest_OBJECTS)
+pagemap_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+pagemap_unittest_LINK = $(LIBTOOL) --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 = 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) --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 = \
+@WITH_CPU_PROFILER_TRUE@ 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_33 = profiler1_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@ 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_33)
+profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS)
+@WITH_CPU_PROFILER_TRUE@profiler1_unittest_DEPENDENCIES = \
+@WITH_CPU_PROFILER_TRUE@ $(LIBPROFILER)
+profiler1_unittest_LINK = $(LIBTOOL) --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_34 = profiler2_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@ 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_34)
+profiler2_unittest_OBJECTS = $(am_profiler2_unittest_OBJECTS)
+profiler2_unittest_LINK = $(LIBTOOL) --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_35 = profiler3_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@ 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_35)
+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) --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_36 = profiler4_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@ 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_36)
+profiler4_unittest_OBJECTS = $(am_profiler4_unittest_OBJECTS)
+profiler4_unittest_LINK = $(LIBTOOL) --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 = 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) --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_37 = realloc_debug_unittest-realloc_unittest.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@am_realloc_debug_unittest_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_37)
+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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(realloc_debug_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_realloc_unittest_OBJECTS = \
+ realloc_unittest-realloc_unittest.$(OBJEXT)
+realloc_unittest_OBJECTS = $(am_realloc_unittest_OBJECTS)
+realloc_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+realloc_unittest_LINK = $(LIBTOOL) --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_38 = sampler_debug_test-sampler_test.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_debug_test_OBJECTS = $(am__objects_38)
+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) --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 = 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) --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_39 = 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_39)
+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) --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 = 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) --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 src/windows/google/tcmalloc.h
+@WITH_HEAP_PROFILER_TRUE@am_simple_compat_test_OBJECTS = \
+@WITH_HEAP_PROFILER_TRUE@ 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(simple_compat_test_LDFLAGS) $(LDFLAGS) -o $@
+am_stack_trace_table_test_OBJECTS = \
+ 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) --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_config.h \
+ src/stacktrace_generic-inl.h src/stacktrace_libunwind-inl.h \
+ src/stacktrace_arm-inl.h src/stacktrace_powerpc-inl.h \
+ src/stacktrace_x86-inl.h src/stacktrace_win32-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 \
+ src/third_party/valgrind.h
+@WITH_STACK_TRACE_TRUE@am__objects_40 = $(am__objects_4) \
+@WITH_STACK_TRACE_TRUE@ $(am__objects_1)
+@WITH_STACK_TRACE_TRUE@am_stacktrace_unittest_OBJECTS = \
+@WITH_STACK_TRACE_TRUE@ stacktrace_unittest.$(OBJEXT) \
+@WITH_STACK_TRACE_TRUE@ $(am__objects_40)
+stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS)
+@WITH_STACK_TRACE_TRUE@stacktrace_unittest_DEPENDENCIES = \
+@WITH_STACK_TRACE_TRUE@ libstacktrace.la liblogging.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 = 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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(system_alloc_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am__tcmalloc_and_profiler_unittest_SOURCES_DIST = \
+ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \
+ src/tests/testutil.cc src/config_for_unittests.h \
+ src/gperftools/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_41 = tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_and_profiler_unittest-testutil.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_41)
+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) --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 src/config_for_unittests.h \
+ src/gperftools/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_42 = tcmalloc_both_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest-testutil.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@OSX_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_both_unittest_OBJECTS = $(am__objects_42)
+tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS)
+@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_4 = $(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_4 = $(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_4)
+tcmalloc_both_unittest_LINK = $(LIBTOOL) --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 \
+ src/config_for_unittests.h src/gperftools/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_43 = tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_debug_unittest-testutil.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_debug_unittest_OBJECTS = $(am__objects_43)
+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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(tcmalloc_debug_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 = 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) --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 src/config_for_unittests.h \
+ src/gperftools/malloc_extension.h
+am__objects_44 = \
+ tcmalloc_minimal_debug_unittest-tcmalloc_unittest.$(OBJEXT) \
+ tcmalloc_minimal_debug_unittest-testutil.$(OBJEXT) \
+ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@am_tcmalloc_minimal_debug_unittest_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_44)
+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) --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_unittest_OBJECTS = tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
+tcmalloc_minimal_large_unittest_OBJECTS = \
+ $(am_tcmalloc_minimal_large_unittest_OBJECTS)
+tcmalloc_minimal_large_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+tcmalloc_minimal_large_unittest_LINK = $(LIBTOOL) --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_SOURCES_DIST = \
+ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \
+ src/tests/testutil.cc src/config_for_unittests.h \
+ src/gperftools/malloc_extension.h
+am_tcmalloc_minimal_unittest_OBJECTS = \
+ tcmalloc_minimal_unittest-tcmalloc_unittest.$(OBJEXT) \
+ tcmalloc_minimal_unittest-testutil.$(OBJEXT) $(am__objects_1)
+tcmalloc_minimal_unittest_OBJECTS = \
+ $(am_tcmalloc_minimal_unittest_OBJECTS)
+tcmalloc_minimal_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ liblogging.la $(am__DEPENDENCIES_1)
+tcmalloc_minimal_unittest_LINK = $(LIBTOOL) --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 \
+ src/config_for_unittests.h src/gperftools/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_unittest_OBJECTS = tcmalloc_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_unittest-testutil.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+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) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(tcmalloc_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_thread_dealloc_unittest_OBJECTS = \
+ thread_dealloc_unittest-thread_dealloc_unittest.$(OBJEXT) \
+ thread_dealloc_unittest-testutil.$(OBJEXT)
+thread_dealloc_unittest_OBJECTS = \
+ $(am_thread_dealloc_unittest_OBJECTS)
+thread_dealloc_unittest_DEPENDENCIES = $(LIBTCMALLOC_MINIMAL) \
+ $(am__DEPENDENCIES_1)
+thread_dealloc_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(thread_dealloc_unittest_LDFLAGS) $(LDFLAGS) -o $@
+binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(liblogging_la_SOURCES) $(libprofiler_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_minimal_la_SOURCES) \
+ $(libtcmalloc_minimal_debug_la_SOURCES) \
+ $(libtcmalloc_minimal_internal_la_SOURCES) \
+ $(libwindows_la_SOURCES) $(addressmap_unittest_SOURCES) \
+ $(atomicops_unittest_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_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) \
+ $(tcmalloc_and_profiler_unittest_SOURCES) \
+ $(tcmalloc_both_unittest_SOURCES) \
+ $(tcmalloc_debug_unittest_SOURCES) \
+ $(tcmalloc_large_unittest_SOURCES) \
+ $(tcmalloc_minimal_debug_unittest_SOURCES) \
+ $(tcmalloc_minimal_large_unittest_SOURCES) \
+ $(tcmalloc_minimal_unittest_SOURCES) \
+ $(tcmalloc_unittest_SOURCES) \
+ $(thread_dealloc_unittest_SOURCES)
+DIST_SOURCES = $(liblogging_la_SOURCES) \
+ $(am__libprofiler_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_minimal_la_SOURCES_DIST) \
+ $(am__libtcmalloc_minimal_debug_la_SOURCES_DIST) \
+ $(am__libtcmalloc_minimal_internal_la_SOURCES_DIST) \
+ $(am__libwindows_la_SOURCES_DIST) \
+ $(am__addressmap_unittest_SOURCES_DIST) \
+ $(atomicops_unittest_SOURCES) \
+ $(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_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__tcmalloc_and_profiler_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_both_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_debug_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_large_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_minimal_debug_unittest_SOURCES_DIST) \
+ $(tcmalloc_minimal_large_unittest_SOURCES) \
+ $(am__tcmalloc_minimal_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_unittest_SOURCES_DIST) \
+ $(thread_dealloc_unittest_SOURCES)
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+am__dist_doc_DATA_DIST = AUTHORS COPYING ChangeLog INSTALL NEWS README \
+ README_windows.txt TODO doc/index.html doc/designstyle.css \
+ doc/pprof_remote_servers.html doc/tcmalloc.html \
+ doc/overview.gif doc/pageheap.gif doc/spanmap.gif \
+ doc/threadheap.gif doc/t-test1.times.txt \
+ doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \
+ doc/tcmalloc-opspersec.vs.size.1.threads.png \
+ doc/tcmalloc-opspersec.vs.size.12.threads.png \
+ doc/tcmalloc-opspersec.vs.size.16.threads.png \
+ doc/tcmalloc-opspersec.vs.size.2.threads.png \
+ doc/tcmalloc-opspersec.vs.size.20.threads.png \
+ doc/tcmalloc-opspersec.vs.size.3.threads.png \
+ doc/tcmalloc-opspersec.vs.size.4.threads.png \
+ doc/tcmalloc-opspersec.vs.size.5.threads.png \
+ doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \
+ doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \
+ doc/heapprofile.html doc/heap-example1.png \
+ doc/heap_checker.html doc/cpuprofile.html \
+ doc/cpuprofile-fileformat.html doc/pprof-test-big.gif \
+ doc/pprof-test.gif doc/pprof-vsnprintf-big.gif \
+ doc/pprof-vsnprintf.gif
+dist_docDATA_INSTALL = $(INSTALL_DATA)
+pkgconfigDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(dist_doc_DATA) $(pkgconfig_DATA)
+googleincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+nodist_perftoolsincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+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/heap-profiler.h src/gperftools/heap-checker.h \
+ src/gperftools/profiler.h
+perftoolsincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(googleinclude_HEADERS) $(nodist_perftoolsinclude_HEADERS) \
+ $(noinst_HEADERS) $(perftoolsinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).zip
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+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@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+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@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+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_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_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+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 = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
+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@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+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
+
+# This is so we can #include <gperftools/foo>
+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)
+
+# 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)
+@GCC_FALSE@NO_EXCEPTIONS =
+
+# We know our low-level code cannot trigger an exception. On some
+# systems, such as cygwin, it would be disastrous if they did, because
+# the exception handler might call malloc! If our low-level routines
+# raised an exception within the malloc, they'd deadlock. Luckily,
+# we control all this code, and do not need exceptions for it.
+@GCC_TRUE@NO_EXCEPTIONS = -fno-exceptions
+
+# 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_7)
+@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 malloc_stats -W mallopt -W mallinfo \
+@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_25) \
+ $(am__append_38) $(am__append_55) $(am__append_70)
+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_11) \
+ $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_32) \
+ $(am__append_62)
+# 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 \
+ src/windows/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 doc/index.html doc/designstyle.css \
+ $(am__append_14) doc/tcmalloc.html doc/overview.gif \
+ doc/pageheap.gif doc/spanmap.gif doc/threadheap.gif \
+ doc/t-test1.times.txt \
+ doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png \
+ doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png \
+ doc/tcmalloc-opspersec.vs.size.1.threads.png \
+ doc/tcmalloc-opspersec.vs.size.12.threads.png \
+ doc/tcmalloc-opspersec.vs.size.16.threads.png \
+ doc/tcmalloc-opspersec.vs.size.2.threads.png \
+ doc/tcmalloc-opspersec.vs.size.20.threads.png \
+ doc/tcmalloc-opspersec.vs.size.3.threads.png \
+ doc/tcmalloc-opspersec.vs.size.4.threads.png \
+ doc/tcmalloc-opspersec.vs.size.5.threads.png \
+ doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \
+ doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \
+ $(am__append_52) $(am__append_53) $(am__append_67)
+
+# 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_24) \
+ $(am__append_34) $(am__append_54) $(am__append_63) \
+ $(am__append_68)
+# This is for 'convenience libraries' -- basically just a container for sources
+
+### Making the library
+
+# As we describe at the top of this file, we want to turn off exceptions
+# for all files in this library -- except tcmalloc.cc which needs them
+# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
+# to separate into two libraries.
+noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_8) \
+ $(am__append_10) $(am__append_12) \
+ libtcmalloc_minimal_internal.la $(am__append_33)
+
+# Add this whether or not we're under MinGW, to keep the tarball complete.
+# Because we've commented out the test, above, we have to explicitly add
+# the test files to the tarball or automake will leave them out.
+WINDOWS_PROJECTS = gperftools.sln \
+ vsprojects/preamble_patcher_test/preamble_patcher_test.vcproj \
+ src/windows/preamble_patcher_test.cc src/windows/shortproc.asm \
+ src/windows/auto_testing_hook.h \
+ vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \
+ $(am__append_16) \
+ vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj \
+ vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj \
+ vsprojects/tmu-static/tmu-static.vcproj \
+ vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj \
+ vsprojects/addressmap_unittest/addressmap_unittest.vcproj \
+ vsprojects/packed-cache_test/packed-cache_test.vcproj \
+ vsprojects/frag_unittest/frag_unittest.vcproj \
+ vsprojects/markidle_unittest/markidle_unittest.vcproj \
+ vsprojects/current_allocated_bytes_test/current_allocated_bytes_test.vcproj \
+ vsprojects/malloc_hook_test/malloc_hook_test.vcproj \
+ vsprojects/malloc_extension_test/malloc_extension_test.vcproj \
+ vsprojects/page_heap_test/page_heap_test.vcproj \
+ vsprojects/pagemap_unittest/pagemap_unittest.vcproj \
+ vsprojects/realloc_unittest/realloc_unittest.vcproj \
+ vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj \
+ vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj \
+ $(am__append_43)
+# 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_15) $(am__append_42)
+# All script tests should be added here
+noinst_SCRIPTS = $(am__append_18) $(am__append_30) $(am__append_44) \
+ $(am__append_47) $(am__append_50) $(am__append_65)
+
+# 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 \
+ src/third_party/valgrind.h
+
+liblogging_la_SOURCES = src/base/logging.cc \
+ src/base/dynamic_annotations.c \
+ $(LOGGING_INCLUDES)
+
+SYSINFO_INCLUDES = src/base/sysinfo.h \
+ src/base/logging.h \
+ src/base/commandlineflags.h \
+ src/base/cycleclock.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_9)
+
+# 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/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/synchronization_profiling.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-windows.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@ $(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@MAYBE_THREADS_CC = src/maybe_threads.cc
+# windows has its own system for threads and system memory allocation.
+@MINGW_TRUE@MAYBE_THREADS_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 \
+ $(MAYBE_THREADS_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)
+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_config.h \
+@WITH_STACK_TRACE_TRUE@ src/stacktrace_generic-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_x86-inl.h \
+@WITH_STACK_TRACE_TRUE@ src/stacktrace_win32-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)
+@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
+
+### ------- pprof
+
+# If we are not compiling with stacktrace support, pprof is worthless
+@WITH_STACK_TRACE_TRUE@bin_SCRIPTS = src/pprof
+
+### Unittests
+@WITH_STACK_TRACE_TRUE@check_SCRIPTS = pprof_unittest
+
+### Documentation
+@WITH_STACK_TRACE_TRUE@dist_man_MANS = doc/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 \
+ src/maybe_threads.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/stacktrace.h
+
+TCMALLOC_MINIMAL_INCLUDES = $(S_TCMALLOC_MINIMAL_INCLUDES) $(SG_TCMALLOC_MINIMAL_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 \
+ $(MAYBE_THREADS_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 \
+ $(PTHREAD_CFLAGS) -DNDEBUG \
+ $(AM_CXXFLAGS) $(NO_EXCEPTIONS)
+
+libtcmalloc_minimal_internal_la_LDFLAGS = $(PTHREAD_CFLAGS)
+libtcmalloc_minimal_internal_la_LIBADD = $(PTHREAD_LIBS) $(LIBSPINLOCK)
+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 = $(PTHREAD_CFLAGS) -version-info @TCMALLOC_SO_VERSION@
+libtcmalloc_minimal_la_LIBADD = libtcmalloc_minimal_internal.la $(PTHREAD_LIBS)
+@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)
+
+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)
+@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_19)
+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)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_SOURCES = src/tests/malloc_extension_c_test.c \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ src/gperftools/malloc_extension.h \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ src/gperftools/malloc_extension_c.h
+
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_CFLAGS = \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(PTHREAD_CFLAGS) \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(AM_CFLAGS) \
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@ $(am__append_22)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+@ENABLE_STATIC_FALSE@@MINGW_FALSE@malloc_extension_c_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
+@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)
+
+### ------- 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@SG_TCMALLOC_INCLUDES = $(SG_TCMALLOC_MINIMAL_INCLUDES) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ 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_INCLUDES)
+@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@ src/memory_region_map.cc
+
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_CXXFLAGS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(NO_EXCEPTIONS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_36)
+@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 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_CC) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_35)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_37)
+@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 $(PTHREAD_LIBS)
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES =
+
+# 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_PROFILER_OR_CHECKER_TRUE@LIBTCMALLOC = libtcmalloc.la
+@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)
+
+# 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@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@ src/gperftools/stacktrace.h
+
+@WITH_CPU_PROFILER_TRUE@CPU_PROFILER_INCLUDES = $(S_CPU_PROFILER_INCLUDES) $(SG_CPU_PROFILER_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
+# 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)'
+@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.vcproj
+@WITH_CPU_PROFILER_TRUE@getpc_test_SOURCES = src/tests/getpc_test.cc src/getpc.h
+#WINDOWS_PROJECTS += vsprojects/profiledata_unittest/profiledata_unittest.vcproj
+@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_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 \
+ $(WINDOWS_PROJECTS) \
+ src/solaris/libstdc++.la
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
+ cd $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: 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__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+src/config.h: src/stamp-h1
+ @if test ! -f $@; then \
+ rm -f src/stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1; \
+ else :; fi
+
+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: $(am__configure_deps)
+ 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-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+liblogging.la: $(liblogging_la_OBJECTS) $(liblogging_la_DEPENDENCIES)
+ $(CXXLINK) $(liblogging_la_OBJECTS) $(liblogging_la_LIBADD) $(LIBS)
+libprofiler.la: $(libprofiler_la_OBJECTS) $(libprofiler_la_DEPENDENCIES)
+ $(libprofiler_la_LINK) $(am_libprofiler_la_rpath) $(libprofiler_la_OBJECTS) $(libprofiler_la_LIBADD) $(LIBS)
+libspinlock.la: $(libspinlock_la_OBJECTS) $(libspinlock_la_DEPENDENCIES)
+ $(CXXLINK) $(am_libspinlock_la_rpath) $(libspinlock_la_OBJECTS) $(libspinlock_la_LIBADD) $(LIBS)
+libstacktrace.la: $(libstacktrace_la_OBJECTS) $(libstacktrace_la_DEPENDENCIES)
+ $(libstacktrace_la_LINK) $(am_libstacktrace_la_rpath) $(libstacktrace_la_OBJECTS) $(libstacktrace_la_LIBADD) $(LIBS)
+libsysinfo.la: $(libsysinfo_la_OBJECTS) $(libsysinfo_la_DEPENDENCIES)
+ $(CXXLINK) $(libsysinfo_la_OBJECTS) $(libsysinfo_la_LIBADD) $(LIBS)
+libtcmalloc.la: $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_DEPENDENCIES)
+ $(libtcmalloc_la_LINK) $(am_libtcmalloc_la_rpath) $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_LIBADD) $(LIBS)
+libtcmalloc_and_profiler.la: $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_DEPENDENCIES)
+ $(libtcmalloc_and_profiler_la_LINK) $(am_libtcmalloc_and_profiler_la_rpath) $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_LIBADD) $(LIBS)
+libtcmalloc_debug.la: $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_DEPENDENCIES)
+ $(libtcmalloc_debug_la_LINK) $(am_libtcmalloc_debug_la_rpath) $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_LIBADD) $(LIBS)
+libtcmalloc_internal.la: $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_DEPENDENCIES)
+ $(libtcmalloc_internal_la_LINK) $(am_libtcmalloc_internal_la_rpath) $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_LIBADD) $(LIBS)
+libtcmalloc_minimal.la: $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_DEPENDENCIES)
+ $(libtcmalloc_minimal_la_LINK) -rpath $(libdir) $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_LIBADD) $(LIBS)
+libtcmalloc_minimal_debug.la: $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_DEPENDENCIES)
+ $(libtcmalloc_minimal_debug_la_LINK) $(am_libtcmalloc_minimal_debug_la_rpath) $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_LIBADD) $(LIBS)
+libtcmalloc_minimal_internal.la: $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_DEPENDENCIES)
+ $(libtcmalloc_minimal_internal_la_LINK) $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_LIBADD) $(LIBS)
+libwindows.la: $(libwindows_la_OBJECTS) $(libwindows_la_DEPENDENCIES)
+ $(CXXLINK) $(am_libwindows_la_rpath) $(libwindows_la_OBJECTS) $(libwindows_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+addressmap_unittest$(EXEEXT): $(addressmap_unittest_OBJECTS) $(addressmap_unittest_DEPENDENCIES)
+ @rm -f addressmap_unittest$(EXEEXT)
+ $(addressmap_unittest_LINK) $(addressmap_unittest_OBJECTS) $(addressmap_unittest_LDADD) $(LIBS)
+atomicops_unittest$(EXEEXT): $(atomicops_unittest_OBJECTS) $(atomicops_unittest_DEPENDENCIES)
+ @rm -f atomicops_unittest$(EXEEXT)
+ $(CXXLINK) $(atomicops_unittest_OBJECTS) $(atomicops_unittest_LDADD) $(LIBS)
+current_allocated_bytes_test$(EXEEXT): $(current_allocated_bytes_test_OBJECTS) $(current_allocated_bytes_test_DEPENDENCIES)
+ @rm -f current_allocated_bytes_test$(EXEEXT)
+ $(current_allocated_bytes_test_LINK) $(current_allocated_bytes_test_OBJECTS) $(current_allocated_bytes_test_LDADD) $(LIBS)
+debugallocation_test$(EXEEXT): $(debugallocation_test_OBJECTS) $(debugallocation_test_DEPENDENCIES)
+ @rm -f debugallocation_test$(EXEEXT)
+ $(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)
+@WITH_DEBUGALLOC_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(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)
+@WITH_STACK_TRACE_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT)
+@WITH_STACK_TRACE_FALSE@ $(LINK) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS)
+frag_unittest$(EXEEXT): $(frag_unittest_OBJECTS) $(frag_unittest_DEPENDENCIES)
+ @rm -f frag_unittest$(EXEEXT)
+ $(frag_unittest_LINK) $(frag_unittest_OBJECTS) $(frag_unittest_LDADD) $(LIBS)
+getpc_test$(EXEEXT): $(getpc_test_OBJECTS) $(getpc_test_DEPENDENCIES)
+ @rm -f getpc_test$(EXEEXT)
+ $(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)
+@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker-death_unittest.sh$(EXEEXT)
+@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_death_unittest_sh_OBJECTS) $(heap_checker_death_unittest_sh_LDADD) $(LIBS)
+heap-checker_debug_unittest$(EXEEXT): $(heap_checker_debug_unittest_OBJECTS) $(heap_checker_debug_unittest_DEPENDENCIES)
+ @rm -f heap-checker_debug_unittest$(EXEEXT)
+ $(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)
+@WITH_DEBUGALLOC_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(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)
+@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_LDADD) $(LIBS)
+heap-checker_unittest$(EXEEXT): $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_DEPENDENCIES)
+ @rm -f heap-checker_unittest$(EXEEXT)
+ $(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)
+@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_unittest.sh$(EXEEXT)
+@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_unittest_sh_OBJECTS) $(heap_checker_unittest_sh_LDADD) $(LIBS)
+heap-profiler_debug_unittest$(EXEEXT): $(heap_profiler_debug_unittest_OBJECTS) $(heap_profiler_debug_unittest_DEPENDENCIES)
+ @rm -f heap-profiler_debug_unittest$(EXEEXT)
+ $(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)
+@WITH_DEBUGALLOC_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(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)
+@WITH_HEAP_PROFILER_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_FALSE@ $(LINK) $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_LDADD) $(LIBS)
+heap-profiler_unittest$(EXEEXT): $(heap_profiler_unittest_OBJECTS) $(heap_profiler_unittest_DEPENDENCIES)
+ @rm -f heap-profiler_unittest$(EXEEXT)
+ $(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)
+@WITH_HEAP_PROFILER_FALSE@ @rm -f heap-profiler_unittest.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_FALSE@ $(LINK) $(heap_profiler_unittest_sh_OBJECTS) $(heap_profiler_unittest_sh_LDADD) $(LIBS)
+low_level_alloc_unittest$(EXEEXT): $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_DEPENDENCIES)
+ @rm -f low_level_alloc_unittest$(EXEEXT)
+ $(low_level_alloc_unittest_LINK) $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_LDADD) $(LIBS)
+malloc_extension_c_test$(EXEEXT): $(malloc_extension_c_test_OBJECTS) $(malloc_extension_c_test_DEPENDENCIES)
+ @rm -f malloc_extension_c_test$(EXEEXT)
+ $(malloc_extension_c_test_LINK) $(malloc_extension_c_test_OBJECTS) $(malloc_extension_c_test_LDADD) $(LIBS)
+malloc_extension_debug_test$(EXEEXT): $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_DEPENDENCIES)
+ @rm -f malloc_extension_debug_test$(EXEEXT)
+ $(malloc_extension_debug_test_LINK) $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_LDADD) $(LIBS)
+malloc_extension_test$(EXEEXT): $(malloc_extension_test_OBJECTS) $(malloc_extension_test_DEPENDENCIES)
+ @rm -f malloc_extension_test$(EXEEXT)
+ $(malloc_extension_test_LINK) $(malloc_extension_test_OBJECTS) $(malloc_extension_test_LDADD) $(LIBS)
+malloc_hook_test$(EXEEXT): $(malloc_hook_test_OBJECTS) $(malloc_hook_test_DEPENDENCIES)
+ @rm -f malloc_hook_test$(EXEEXT)
+ $(malloc_hook_test_LINK) $(malloc_hook_test_OBJECTS) $(malloc_hook_test_LDADD) $(LIBS)
+markidle_unittest$(EXEEXT): $(markidle_unittest_OBJECTS) $(markidle_unittest_DEPENDENCIES)
+ @rm -f markidle_unittest$(EXEEXT)
+ $(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)
+@ENABLE_STATIC_TRUE@ @rm -f maybe_threads_unittest.sh$(EXEEXT)
+@ENABLE_STATIC_TRUE@ $(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)
+@MINGW_TRUE@ @rm -f maybe_threads_unittest.sh$(EXEEXT)
+@MINGW_TRUE@ $(LINK) $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_LDADD) $(LIBS)
+memalign_debug_unittest$(EXEEXT): $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_DEPENDENCIES)
+ @rm -f memalign_debug_unittest$(EXEEXT)
+ $(memalign_debug_unittest_LINK) $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_LDADD) $(LIBS)
+memalign_unittest$(EXEEXT): $(memalign_unittest_OBJECTS) $(memalign_unittest_DEPENDENCIES)
+ @rm -f memalign_unittest$(EXEEXT)
+ $(memalign_unittest_LINK) $(memalign_unittest_OBJECTS) $(memalign_unittest_LDADD) $(LIBS)
+packed_cache_test$(EXEEXT): $(packed_cache_test_OBJECTS) $(packed_cache_test_DEPENDENCIES)
+ @rm -f packed_cache_test$(EXEEXT)
+ $(packed_cache_test_LINK) $(packed_cache_test_OBJECTS) $(packed_cache_test_LDADD) $(LIBS)
+page_heap_test$(EXEEXT): $(page_heap_test_OBJECTS) $(page_heap_test_DEPENDENCIES)
+ @rm -f page_heap_test$(EXEEXT)
+ $(page_heap_test_LINK) $(page_heap_test_OBJECTS) $(page_heap_test_LDADD) $(LIBS)
+pagemap_unittest$(EXEEXT): $(pagemap_unittest_OBJECTS) $(pagemap_unittest_DEPENDENCIES)
+ @rm -f pagemap_unittest$(EXEEXT)
+ $(pagemap_unittest_LINK) $(pagemap_unittest_OBJECTS) $(pagemap_unittest_LDADD) $(LIBS)
+profile_handler_unittest$(EXEEXT): $(profile_handler_unittest_OBJECTS) $(profile_handler_unittest_DEPENDENCIES)
+ @rm -f profile_handler_unittest$(EXEEXT)
+ $(profile_handler_unittest_LINK) $(profile_handler_unittest_OBJECTS) $(profile_handler_unittest_LDADD) $(LIBS)
+profiledata_unittest$(EXEEXT): $(profiledata_unittest_OBJECTS) $(profiledata_unittest_DEPENDENCIES)
+ @rm -f profiledata_unittest$(EXEEXT)
+ $(CXXLINK) $(profiledata_unittest_OBJECTS) $(profiledata_unittest_LDADD) $(LIBS)
+profiler1_unittest$(EXEEXT): $(profiler1_unittest_OBJECTS) $(profiler1_unittest_DEPENDENCIES)
+ @rm -f profiler1_unittest$(EXEEXT)
+ $(profiler1_unittest_LINK) $(profiler1_unittest_OBJECTS) $(profiler1_unittest_LDADD) $(LIBS)
+profiler2_unittest$(EXEEXT): $(profiler2_unittest_OBJECTS) $(profiler2_unittest_DEPENDENCIES)
+ @rm -f profiler2_unittest$(EXEEXT)
+ $(profiler2_unittest_LINK) $(profiler2_unittest_OBJECTS) $(profiler2_unittest_LDADD) $(LIBS)
+profiler3_unittest$(EXEEXT): $(profiler3_unittest_OBJECTS) $(profiler3_unittest_DEPENDENCIES)
+ @rm -f profiler3_unittest$(EXEEXT)
+ $(profiler3_unittest_LINK) $(profiler3_unittest_OBJECTS) $(profiler3_unittest_LDADD) $(LIBS)
+profiler4_unittest$(EXEEXT): $(profiler4_unittest_OBJECTS) $(profiler4_unittest_DEPENDENCIES)
+ @rm -f profiler4_unittest$(EXEEXT)
+ $(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)
+@WITH_CPU_PROFILER_FALSE@ @rm -f profiler_unittest.sh$(EXEEXT)
+@WITH_CPU_PROFILER_FALSE@ $(LINK) $(profiler_unittest_sh_OBJECTS) $(profiler_unittest_sh_LDADD) $(LIBS)
+raw_printer_test$(EXEEXT): $(raw_printer_test_OBJECTS) $(raw_printer_test_DEPENDENCIES)
+ @rm -f raw_printer_test$(EXEEXT)
+ $(raw_printer_test_LINK) $(raw_printer_test_OBJECTS) $(raw_printer_test_LDADD) $(LIBS)
+realloc_debug_unittest$(EXEEXT): $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_DEPENDENCIES)
+ @rm -f realloc_debug_unittest$(EXEEXT)
+ $(realloc_debug_unittest_LINK) $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_LDADD) $(LIBS)
+realloc_unittest$(EXEEXT): $(realloc_unittest_OBJECTS) $(realloc_unittest_DEPENDENCIES)
+ @rm -f realloc_unittest$(EXEEXT)
+ $(realloc_unittest_LINK) $(realloc_unittest_OBJECTS) $(realloc_unittest_LDADD) $(LIBS)
+sampler_debug_test$(EXEEXT): $(sampler_debug_test_OBJECTS) $(sampler_debug_test_DEPENDENCIES)
+ @rm -f sampler_debug_test$(EXEEXT)
+ $(sampler_debug_test_LINK) $(sampler_debug_test_OBJECTS) $(sampler_debug_test_LDADD) $(LIBS)
+sampler_test$(EXEEXT): $(sampler_test_OBJECTS) $(sampler_test_DEPENDENCIES)
+ @rm -f sampler_test$(EXEEXT)
+ $(sampler_test_LINK) $(sampler_test_OBJECTS) $(sampler_test_LDADD) $(LIBS)
+sampling_debug_test$(EXEEXT): $(sampling_debug_test_OBJECTS) $(sampling_debug_test_DEPENDENCIES)
+ @rm -f sampling_debug_test$(EXEEXT)
+ $(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)
+@WITH_DEBUGALLOC_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(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)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(LINK) $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_LDADD) $(LIBS)
+sampling_test$(EXEEXT): $(sampling_test_OBJECTS) $(sampling_test_DEPENDENCIES)
+ @rm -f sampling_test$(EXEEXT)
+ $(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)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f sampling_test.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(LINK) $(sampling_test_sh_OBJECTS) $(sampling_test_sh_LDADD) $(LIBS)
+simple_compat_test$(EXEEXT): $(simple_compat_test_OBJECTS) $(simple_compat_test_DEPENDENCIES)
+ @rm -f simple_compat_test$(EXEEXT)
+ $(simple_compat_test_LINK) $(simple_compat_test_OBJECTS) $(simple_compat_test_LDADD) $(LIBS)
+stack_trace_table_test$(EXEEXT): $(stack_trace_table_test_OBJECTS) $(stack_trace_table_test_DEPENDENCIES)
+ @rm -f stack_trace_table_test$(EXEEXT)
+ $(stack_trace_table_test_LINK) $(stack_trace_table_test_OBJECTS) $(stack_trace_table_test_LDADD) $(LIBS)
+stacktrace_unittest$(EXEEXT): $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_DEPENDENCIES)
+ @rm -f stacktrace_unittest$(EXEEXT)
+ $(CXXLINK) $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_LDADD) $(LIBS)
+system_alloc_unittest$(EXEEXT): $(system_alloc_unittest_OBJECTS) $(system_alloc_unittest_DEPENDENCIES)
+ @rm -f system_alloc_unittest$(EXEEXT)
+ $(system_alloc_unittest_LINK) $(system_alloc_unittest_OBJECTS) $(system_alloc_unittest_LDADD) $(LIBS)
+tcmalloc_and_profiler_unittest$(EXEEXT): $(tcmalloc_and_profiler_unittest_OBJECTS) $(tcmalloc_and_profiler_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_and_profiler_unittest$(EXEEXT)
+ $(tcmalloc_and_profiler_unittest_LINK) $(tcmalloc_and_profiler_unittest_OBJECTS) $(tcmalloc_and_profiler_unittest_LDADD) $(LIBS)
+tcmalloc_both_unittest$(EXEEXT): $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_both_unittest$(EXEEXT)
+ $(tcmalloc_both_unittest_LINK) $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_LDADD) $(LIBS)
+tcmalloc_debug_unittest$(EXEEXT): $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_debug_unittest$(EXEEXT)
+ $(tcmalloc_debug_unittest_LINK) $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_LDADD) $(LIBS)
+tcmalloc_large_unittest$(EXEEXT): $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_large_unittest$(EXEEXT)
+ $(tcmalloc_large_unittest_LINK) $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_LDADD) $(LIBS)
+tcmalloc_minimal_debug_unittest$(EXEEXT): $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_minimal_debug_unittest$(EXEEXT)
+ $(tcmalloc_minimal_debug_unittest_LINK) $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_LDADD) $(LIBS)
+tcmalloc_minimal_large_unittest$(EXEEXT): $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_minimal_large_unittest$(EXEEXT)
+ $(tcmalloc_minimal_large_unittest_LINK) $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_LDADD) $(LIBS)
+tcmalloc_minimal_unittest$(EXEEXT): $(tcmalloc_minimal_unittest_OBJECTS) $(tcmalloc_minimal_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_minimal_unittest$(EXEEXT)
+ $(tcmalloc_minimal_unittest_LINK) $(tcmalloc_minimal_unittest_OBJECTS) $(tcmalloc_minimal_unittest_LDADD) $(LIBS)
+tcmalloc_unittest$(EXEEXT): $(tcmalloc_unittest_OBJECTS) $(tcmalloc_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_unittest$(EXEEXT)
+ $(tcmalloc_unittest_LINK) $(tcmalloc_unittest_OBJECTS) $(tcmalloc_unittest_LDADD) $(LIBS)
+thread_dealloc_unittest$(EXEEXT): $(thread_dealloc_unittest_OBJECTS) $(thread_dealloc_unittest_DEPENDENCIES)
+ @rm -f thread_dealloc_unittest$(EXEEXT)
+ $(thread_dealloc_unittest_LINK) $(thread_dealloc_unittest_OBJECTS) $(thread_dealloc_unittest_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f $$d$$p; then \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addressmap_unittest-port.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops-internals-x86.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debugallocation_test-debugallocation_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamic_annotations.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf_mem_image.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frag_unittest-frag_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getpc_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ia32_modrm_map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ia32_opcode_map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-maybe_threads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-sampler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-span.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-heap-checker.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-maybe_threads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-maybe_threads.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_hook_test-malloc_hook_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_hook_test-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-markidle_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_debug_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-memalign_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mini_disassembler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packed_cache_test-packed-cache_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/page_heap_test-page_heap_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch_functions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preamble_patcher.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preamble_patcher_with_stub.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profile-handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiledata.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiledata_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler1_unittest-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler1_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler2_unittest-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler2_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler3_unittest-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler3_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler4_unittest-profiler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/profiler4_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_printer_test-raw_printer_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc_unittest-realloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampler_debug_test-sampler_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampler_test-sampler_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_debug_test-sampling_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_test-sampling_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple_compat_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock_internal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_dealloc_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_lister.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vdso_support.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+dynamic_annotations.lo: src/base/dynamic_annotations.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dynamic_annotations.lo -MD -MP -MF $(DEPDIR)/dynamic_annotations.Tpo -c -o dynamic_annotations.lo `test -f 'src/base/dynamic_annotations.c' || echo '$(srcdir)/'`src/base/dynamic_annotations.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/dynamic_annotations.Tpo $(DEPDIR)/dynamic_annotations.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/base/dynamic_annotations.c' object='dynamic_annotations.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dynamic_annotations.lo `test -f 'src/base/dynamic_annotations.c' || echo '$(srcdir)/'`src/base/dynamic_annotations.c
+
+thread_lister.lo: src/base/thread_lister.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread_lister.lo -MD -MP -MF $(DEPDIR)/thread_lister.Tpo -c -o thread_lister.lo `test -f 'src/base/thread_lister.c' || echo '$(srcdir)/'`src/base/thread_lister.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/thread_lister.Tpo $(DEPDIR)/thread_lister.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/base/thread_lister.c' object='thread_lister.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread_lister.lo `test -f 'src/base/thread_lister.c' || echo '$(srcdir)/'`src/base/thread_lister.c
+
+malloc_extension_c_test-malloc_extension_c_test.o: src/tests/malloc_extension_c_test.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -MT malloc_extension_c_test-malloc_extension_c_test.o -MD -MP -MF $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/tests/malloc_extension_c_test.c' object='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@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -c -o 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
+
+malloc_extension_c_test-malloc_extension_c_test.obj: src/tests/malloc_extension_c_test.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -MT malloc_extension_c_test-malloc_extension_c_test.obj -MD -MP -MF $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Tpo $(DEPDIR)/malloc_extension_c_test-malloc_extension_c_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/tests/malloc_extension_c_test.c' object='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@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_c_test_CFLAGS) $(CFLAGS) -c -o 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@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+logging.lo: src/base/logging.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT logging.lo -MD -MP -MF $(DEPDIR)/logging.Tpo -c -o logging.lo `test -f 'src/base/logging.cc' || echo '$(srcdir)/'`src/base/logging.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/logging.Tpo $(DEPDIR)/logging.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/logging.cc' object='logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o logging.lo `test -f 'src/base/logging.cc' || echo '$(srcdir)/'`src/base/logging.cc
+
+profiler.lo: src/profiler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT profiler.lo -MD -MP -MF $(DEPDIR)/profiler.Tpo -c -o profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler.Tpo $(DEPDIR)/profiler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profiler.cc' object='profiler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc
+
+profile-handler.lo: src/profile-handler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT profile-handler.lo -MD -MP -MF $(DEPDIR)/profile-handler.Tpo -c -o profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profile-handler.Tpo $(DEPDIR)/profile-handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profile-handler.cc' object='profile-handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc
+
+profiledata.lo: src/profiledata.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT profiledata.lo -MD -MP -MF $(DEPDIR)/profiledata.Tpo -c -o profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiledata.Tpo $(DEPDIR)/profiledata.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profiledata.cc' object='profiledata.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc
+
+spinlock.lo: src/base/spinlock.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT spinlock.lo -MD -MP -MF $(DEPDIR)/spinlock.Tpo -c -o spinlock.lo `test -f 'src/base/spinlock.cc' || echo '$(srcdir)/'`src/base/spinlock.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/spinlock.Tpo $(DEPDIR)/spinlock.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/spinlock.cc' object='spinlock.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o spinlock.lo `test -f 'src/base/spinlock.cc' || echo '$(srcdir)/'`src/base/spinlock.cc
+
+spinlock_internal.lo: src/base/spinlock_internal.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT spinlock_internal.lo -MD -MP -MF $(DEPDIR)/spinlock_internal.Tpo -c -o spinlock_internal.lo `test -f 'src/base/spinlock_internal.cc' || echo '$(srcdir)/'`src/base/spinlock_internal.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/spinlock_internal.Tpo $(DEPDIR)/spinlock_internal.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/spinlock_internal.cc' object='spinlock_internal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o spinlock_internal.lo `test -f 'src/base/spinlock_internal.cc' || echo '$(srcdir)/'`src/base/spinlock_internal.cc
+
+atomicops-internals-x86.lo: src/base/atomicops-internals-x86.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT atomicops-internals-x86.lo -MD -MP -MF $(DEPDIR)/atomicops-internals-x86.Tpo -c -o atomicops-internals-x86.lo `test -f 'src/base/atomicops-internals-x86.cc' || echo '$(srcdir)/'`src/base/atomicops-internals-x86.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/atomicops-internals-x86.Tpo $(DEPDIR)/atomicops-internals-x86.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/atomicops-internals-x86.cc' object='atomicops-internals-x86.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o atomicops-internals-x86.lo `test -f 'src/base/atomicops-internals-x86.cc' || echo '$(srcdir)/'`src/base/atomicops-internals-x86.cc
+
+stacktrace.lo: src/stacktrace.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT stacktrace.lo -MD -MP -MF $(DEPDIR)/stacktrace.Tpo -c -o stacktrace.lo `test -f 'src/stacktrace.cc' || echo '$(srcdir)/'`src/stacktrace.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace.Tpo $(DEPDIR)/stacktrace.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace.cc' object='stacktrace.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace.lo `test -f 'src/stacktrace.cc' || echo '$(srcdir)/'`src/stacktrace.cc
+
+elf_mem_image.lo: src/base/elf_mem_image.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT elf_mem_image.lo -MD -MP -MF $(DEPDIR)/elf_mem_image.Tpo -c -o elf_mem_image.lo `test -f 'src/base/elf_mem_image.cc' || echo '$(srcdir)/'`src/base/elf_mem_image.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/elf_mem_image.Tpo $(DEPDIR)/elf_mem_image.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/elf_mem_image.cc' object='elf_mem_image.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o elf_mem_image.lo `test -f 'src/base/elf_mem_image.cc' || echo '$(srcdir)/'`src/base/elf_mem_image.cc
+
+vdso_support.lo: src/base/vdso_support.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT vdso_support.lo -MD -MP -MF $(DEPDIR)/vdso_support.Tpo -c -o vdso_support.lo `test -f 'src/base/vdso_support.cc' || echo '$(srcdir)/'`src/base/vdso_support.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/vdso_support.Tpo $(DEPDIR)/vdso_support.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/vdso_support.cc' object='vdso_support.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o vdso_support.lo `test -f 'src/base/vdso_support.cc' || echo '$(srcdir)/'`src/base/vdso_support.cc
+
+sysinfo.lo: src/base/sysinfo.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sysinfo.lo -MD -MP -MF $(DEPDIR)/sysinfo.Tpo -c -o sysinfo.lo `test -f 'src/base/sysinfo.cc' || echo '$(srcdir)/'`src/base/sysinfo.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sysinfo.Tpo $(DEPDIR)/sysinfo.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/sysinfo.cc' object='sysinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sysinfo.lo `test -f 'src/base/sysinfo.cc' || echo '$(srcdir)/'`src/base/sysinfo.cc
+
+libtcmalloc_la-tcmalloc.lo: src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-tcmalloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo -c -o libtcmalloc_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_la-tcmalloc.Tpo $(DEPDIR)/libtcmalloc_la-tcmalloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tcmalloc.cc' object='libtcmalloc_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+
+libtcmalloc_la-linuxthreads.lo: src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-linuxthreads.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_la-linuxthreads.Tpo -c -o libtcmalloc_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_la-linuxthreads.Tpo $(DEPDIR)/libtcmalloc_la-linuxthreads.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/linuxthreads.cc' object='libtcmalloc_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+
+libtcmalloc_la-heap-checker.lo: src/heap-checker.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-heap-checker.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_la-heap-checker.Tpo -c -o libtcmalloc_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_la-heap-checker.Tpo $(DEPDIR)/libtcmalloc_la-heap-checker.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker.cc' object='libtcmalloc_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+
+libtcmalloc_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_la-heap-checker-bcad.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Tpo -c -o libtcmalloc_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Tpo $(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker-bcad.cc' object='libtcmalloc_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+
+libtcmalloc_and_profiler_la-tcmalloc.lo: src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-tcmalloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Tpo -c -o libtcmalloc_and_profiler_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tcmalloc.cc' object='libtcmalloc_and_profiler_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+
+libtcmalloc_and_profiler_la-linuxthreads.lo: src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-linuxthreads.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Tpo -c -o libtcmalloc_and_profiler_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-linuxthreads.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/linuxthreads.cc' object='libtcmalloc_and_profiler_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+
+libtcmalloc_and_profiler_la-heap-checker.lo: src/heap-checker.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-heap-checker.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Tpo -c -o libtcmalloc_and_profiler_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker.cc' object='libtcmalloc_and_profiler_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+
+libtcmalloc_and_profiler_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-heap-checker-bcad.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Tpo -c -o 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@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-heap-checker-bcad.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker-bcad.cc' object='libtcmalloc_and_profiler_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+
+libtcmalloc_and_profiler_la-profiler.lo: src/profiler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-profiler.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Tpo -c -o libtcmalloc_and_profiler_la-profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profiler.cc' object='libtcmalloc_and_profiler_la-profiler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-profiler.lo `test -f 'src/profiler.cc' || echo '$(srcdir)/'`src/profiler.cc
+
+libtcmalloc_and_profiler_la-profile-handler.lo: src/profile-handler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-profile-handler.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Tpo -c -o libtcmalloc_and_profiler_la-profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-profile-handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profile-handler.cc' object='libtcmalloc_and_profiler_la-profile-handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-profile-handler.lo `test -f 'src/profile-handler.cc' || echo '$(srcdir)/'`src/profile-handler.cc
+
+libtcmalloc_and_profiler_la-profiledata.lo: src/profiledata.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_and_profiler_la-profiledata.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Tpo -c -o libtcmalloc_and_profiler_la-profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Tpo $(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/profiledata.cc' object='libtcmalloc_and_profiler_la-profiledata.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc
+
+libtcmalloc_debug_la-debugallocation.lo: src/debugallocation.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-debugallocation.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo -c -o libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo $(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/debugallocation.cc' object='libtcmalloc_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+
+libtcmalloc_debug_la-linuxthreads.lo: src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-linuxthreads.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo -c -o libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo $(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/linuxthreads.cc' object='libtcmalloc_debug_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+
+libtcmalloc_debug_la-heap-checker.lo: src/heap-checker.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-heap-checker.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo -c -o libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo $(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker.cc' object='libtcmalloc_debug_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+
+libtcmalloc_debug_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-heap-checker-bcad.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo -c -o libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo $(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker-bcad.cc' object='libtcmalloc_debug_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+
+libtcmalloc_internal_la-common.lo: src/common.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-common.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-common.Tpo -c -o libtcmalloc_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-common.Tpo $(DEPDIR)/libtcmalloc_internal_la-common.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common.cc' object='libtcmalloc_internal_la-common.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc
+
+libtcmalloc_internal_la-internal_logging.lo: src/internal_logging.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-internal_logging.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-internal_logging.Tpo -c -o libtcmalloc_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-internal_logging.Tpo $(DEPDIR)/libtcmalloc_internal_la-internal_logging.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/internal_logging.cc' object='libtcmalloc_internal_la-internal_logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc
+
+libtcmalloc_internal_la-system-alloc.lo: src/system-alloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-system-alloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-system-alloc.Tpo -c -o libtcmalloc_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-system-alloc.Tpo $(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/system-alloc.cc' object='libtcmalloc_internal_la-system-alloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
+
+libtcmalloc_internal_la-memfs_malloc.lo: src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-memfs_malloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Tpo -c -o libtcmalloc_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Tpo $(DEPDIR)/libtcmalloc_internal_la-memfs_malloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/memfs_malloc.cc' object='libtcmalloc_internal_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+
+libtcmalloc_internal_la-central_freelist.lo: src/central_freelist.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-central_freelist.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-central_freelist.Tpo -c -o libtcmalloc_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-central_freelist.Tpo $(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/central_freelist.cc' object='libtcmalloc_internal_la-central_freelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc
+
+libtcmalloc_internal_la-page_heap.lo: src/page_heap.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-page_heap.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-page_heap.Tpo -c -o libtcmalloc_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-page_heap.Tpo $(DEPDIR)/libtcmalloc_internal_la-page_heap.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/page_heap.cc' object='libtcmalloc_internal_la-page_heap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc
+
+libtcmalloc_internal_la-sampler.lo: src/sampler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-sampler.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-sampler.Tpo -c -o libtcmalloc_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-sampler.Tpo $(DEPDIR)/libtcmalloc_internal_la-sampler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/sampler.cc' object='libtcmalloc_internal_la-sampler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc
+
+libtcmalloc_internal_la-span.lo: src/span.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-span.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-span.Tpo -c -o libtcmalloc_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-span.Tpo $(DEPDIR)/libtcmalloc_internal_la-span.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/span.cc' object='libtcmalloc_internal_la-span.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc
+
+libtcmalloc_internal_la-stack_trace_table.lo: src/stack_trace_table.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-stack_trace_table.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Tpo -c -o libtcmalloc_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Tpo $(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stack_trace_table.cc' object='libtcmalloc_internal_la-stack_trace_table.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc
+
+libtcmalloc_internal_la-static_vars.lo: src/static_vars.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-static_vars.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-static_vars.Tpo -c -o libtcmalloc_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-static_vars.Tpo $(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/static_vars.cc' object='libtcmalloc_internal_la-static_vars.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+
+libtcmalloc_internal_la-symbolize.lo: src/symbolize.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-symbolize.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo -c -o libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo $(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize.cc' object='libtcmalloc_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+
+libtcmalloc_internal_la-thread_cache.lo: src/thread_cache.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-thread_cache.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo -c -o libtcmalloc_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo $(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/thread_cache.cc' object='libtcmalloc_internal_la-thread_cache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc
+
+libtcmalloc_internal_la-malloc_hook.lo: src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-malloc_hook.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Tpo -c -o libtcmalloc_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Tpo $(DEPDIR)/libtcmalloc_internal_la-malloc_hook.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_hook.cc' object='libtcmalloc_internal_la-malloc_hook.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+
+libtcmalloc_internal_la-malloc_extension.lo: src/malloc_extension.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-malloc_extension.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Tpo -c -o libtcmalloc_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Tpo $(DEPDIR)/libtcmalloc_internal_la-malloc_extension.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_extension.cc' object='libtcmalloc_internal_la-malloc_extension.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc
+
+libtcmalloc_internal_la-maybe_threads.lo: src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-maybe_threads.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-maybe_threads.Tpo -c -o libtcmalloc_internal_la-maybe_threads.lo `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-maybe_threads.Tpo $(DEPDIR)/libtcmalloc_internal_la-maybe_threads.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/maybe_threads.cc' object='libtcmalloc_internal_la-maybe_threads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-maybe_threads.lo `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+
+libtcmalloc_internal_la-low_level_alloc.lo: src/base/low_level_alloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-low_level_alloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Tpo -c -o 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@ mv -f $(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Tpo $(DEPDIR)/libtcmalloc_internal_la-low_level_alloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/low_level_alloc.cc' object='libtcmalloc_internal_la-low_level_alloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-low_level_alloc.lo `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc
+
+libtcmalloc_internal_la-heap-profile-table.lo: src/heap-profile-table.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-heap-profile-table.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Tpo -c -o libtcmalloc_internal_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Tpo $(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-profile-table.cc' object='libtcmalloc_internal_la-heap-profile-table.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-heap-profile-table.lo `test -f 'src/heap-profile-table.cc' || echo '$(srcdir)/'`src/heap-profile-table.cc
+
+libtcmalloc_internal_la-heap-profiler.lo: src/heap-profiler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-heap-profiler.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Tpo -c -o libtcmalloc_internal_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Tpo $(DEPDIR)/libtcmalloc_internal_la-heap-profiler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-profiler.cc' object='libtcmalloc_internal_la-heap-profiler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-heap-profiler.lo `test -f 'src/heap-profiler.cc' || echo '$(srcdir)/'`src/heap-profiler.cc
+
+libtcmalloc_internal_la-raw_printer.lo: src/raw_printer.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-raw_printer.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-raw_printer.Tpo -c -o libtcmalloc_internal_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-raw_printer.Tpo $(DEPDIR)/libtcmalloc_internal_la-raw_printer.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/raw_printer.cc' object='libtcmalloc_internal_la-raw_printer.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-raw_printer.lo `test -f 'src/raw_printer.cc' || echo '$(srcdir)/'`src/raw_printer.cc
+
+libtcmalloc_internal_la-memory_region_map.lo: src/memory_region_map.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-memory_region_map.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Tpo -c -o libtcmalloc_internal_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Tpo $(DEPDIR)/libtcmalloc_internal_la-memory_region_map.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/memory_region_map.cc' object='libtcmalloc_internal_la-memory_region_map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-memory_region_map.lo `test -f 'src/memory_region_map.cc' || echo '$(srcdir)/'`src/memory_region_map.cc
+
+libtcmalloc_minimal_la-tcmalloc.lo: src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_la-tcmalloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo -c -o libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Tpo $(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tcmalloc.cc' object='libtcmalloc_minimal_la-tcmalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+
+libtcmalloc_minimal_debug_la-debugallocation.lo: src/debugallocation.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_debug_la-debugallocation.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo -c -o libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo $(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/debugallocation.cc' object='libtcmalloc_minimal_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+
+libtcmalloc_minimal_internal_la-common.lo: src/common.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-common.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo -c -o libtcmalloc_minimal_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common.cc' object='libtcmalloc_minimal_internal_la-common.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc
+
+libtcmalloc_minimal_internal_la-internal_logging.lo: src/internal_logging.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-internal_logging.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Tpo -c -o libtcmalloc_minimal_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/internal_logging.cc' object='libtcmalloc_minimal_internal_la-internal_logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-internal_logging.lo `test -f 'src/internal_logging.cc' || echo '$(srcdir)/'`src/internal_logging.cc
+
+libtcmalloc_minimal_internal_la-system-alloc.lo: src/system-alloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-system-alloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Tpo -c -o libtcmalloc_minimal_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/system-alloc.cc' object='libtcmalloc_minimal_internal_la-system-alloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-system-alloc.lo `test -f 'src/system-alloc.cc' || echo '$(srcdir)/'`src/system-alloc.cc
+
+libtcmalloc_minimal_internal_la-memfs_malloc.lo: src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-memfs_malloc.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Tpo -c -o libtcmalloc_minimal_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-memfs_malloc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/memfs_malloc.cc' object='libtcmalloc_minimal_internal_la-memfs_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-memfs_malloc.lo `test -f 'src/memfs_malloc.cc' || echo '$(srcdir)/'`src/memfs_malloc.cc
+
+libtcmalloc_minimal_internal_la-central_freelist.lo: src/central_freelist.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-central_freelist.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Tpo -c -o libtcmalloc_minimal_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/central_freelist.cc' object='libtcmalloc_minimal_internal_la-central_freelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-central_freelist.lo `test -f 'src/central_freelist.cc' || echo '$(srcdir)/'`src/central_freelist.cc
+
+libtcmalloc_minimal_internal_la-page_heap.lo: src/page_heap.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-page_heap.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Tpo -c -o libtcmalloc_minimal_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-page_heap.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/page_heap.cc' object='libtcmalloc_minimal_internal_la-page_heap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-page_heap.lo `test -f 'src/page_heap.cc' || echo '$(srcdir)/'`src/page_heap.cc
+
+libtcmalloc_minimal_internal_la-sampler.lo: src/sampler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-sampler.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Tpo -c -o libtcmalloc_minimal_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-sampler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/sampler.cc' object='libtcmalloc_minimal_internal_la-sampler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-sampler.lo `test -f 'src/sampler.cc' || echo '$(srcdir)/'`src/sampler.cc
+
+libtcmalloc_minimal_internal_la-span.lo: src/span.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-span.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-span.Tpo -c -o libtcmalloc_minimal_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-span.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/span.cc' object='libtcmalloc_minimal_internal_la-span.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-span.lo `test -f 'src/span.cc' || echo '$(srcdir)/'`src/span.cc
+
+libtcmalloc_minimal_internal_la-stack_trace_table.lo: src/stack_trace_table.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-stack_trace_table.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Tpo -c -o 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@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stack_trace_table.cc' object='libtcmalloc_minimal_internal_la-stack_trace_table.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-stack_trace_table.lo `test -f 'src/stack_trace_table.cc' || echo '$(srcdir)/'`src/stack_trace_table.cc
+
+libtcmalloc_minimal_internal_la-static_vars.lo: src/static_vars.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-static_vars.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Tpo -c -o libtcmalloc_minimal_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/static_vars.cc' object='libtcmalloc_minimal_internal_la-static_vars.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+
+libtcmalloc_minimal_internal_la-symbolize.lo: src/symbolize.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-symbolize.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo -c -o libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize.cc' object='libtcmalloc_minimal_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+
+libtcmalloc_minimal_internal_la-thread_cache.lo: src/thread_cache.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-thread_cache.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo -c -o libtcmalloc_minimal_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/thread_cache.cc' object='libtcmalloc_minimal_internal_la-thread_cache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc
+
+libtcmalloc_minimal_internal_la-malloc_hook.lo: src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-malloc_hook.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Tpo -c -o libtcmalloc_minimal_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_hook.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_hook.cc' object='libtcmalloc_minimal_internal_la-malloc_hook.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-malloc_hook.lo `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+
+libtcmalloc_minimal_internal_la-malloc_extension.lo: src/malloc_extension.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-malloc_extension.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Tpo -c -o libtcmalloc_minimal_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-malloc_extension.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_extension.cc' object='libtcmalloc_minimal_internal_la-malloc_extension.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-malloc_extension.lo `test -f 'src/malloc_extension.cc' || echo '$(srcdir)/'`src/malloc_extension.cc
+
+libtcmalloc_minimal_internal_la-maybe_threads.lo: src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-maybe_threads.lo -MD -MP -MF $(DEPDIR)/libtcmalloc_minimal_internal_la-maybe_threads.Tpo -c -o libtcmalloc_minimal_internal_la-maybe_threads.lo `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libtcmalloc_minimal_internal_la-maybe_threads.Tpo $(DEPDIR)/libtcmalloc_minimal_internal_la-maybe_threads.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/maybe_threads.cc' object='libtcmalloc_minimal_internal_la-maybe_threads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-maybe_threads.lo `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+
+port.lo: src/windows/port.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT port.lo -MD -MP -MF $(DEPDIR)/port.Tpo -c -o port.lo `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/port.Tpo $(DEPDIR)/port.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/port.cc' object='port.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o port.lo `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc
+
+ia32_modrm_map.lo: src/windows/ia32_modrm_map.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ia32_modrm_map.lo -MD -MP -MF $(DEPDIR)/ia32_modrm_map.Tpo -c -o ia32_modrm_map.lo `test -f 'src/windows/ia32_modrm_map.cc' || echo '$(srcdir)/'`src/windows/ia32_modrm_map.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/ia32_modrm_map.Tpo $(DEPDIR)/ia32_modrm_map.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/ia32_modrm_map.cc' object='ia32_modrm_map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ia32_modrm_map.lo `test -f 'src/windows/ia32_modrm_map.cc' || echo '$(srcdir)/'`src/windows/ia32_modrm_map.cc
+
+ia32_opcode_map.lo: src/windows/ia32_opcode_map.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ia32_opcode_map.lo -MD -MP -MF $(DEPDIR)/ia32_opcode_map.Tpo -c -o ia32_opcode_map.lo `test -f 'src/windows/ia32_opcode_map.cc' || echo '$(srcdir)/'`src/windows/ia32_opcode_map.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/ia32_opcode_map.Tpo $(DEPDIR)/ia32_opcode_map.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/ia32_opcode_map.cc' object='ia32_opcode_map.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ia32_opcode_map.lo `test -f 'src/windows/ia32_opcode_map.cc' || echo '$(srcdir)/'`src/windows/ia32_opcode_map.cc
+
+mini_disassembler.lo: src/windows/mini_disassembler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mini_disassembler.lo -MD -MP -MF $(DEPDIR)/mini_disassembler.Tpo -c -o mini_disassembler.lo `test -f 'src/windows/mini_disassembler.cc' || echo '$(srcdir)/'`src/windows/mini_disassembler.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/mini_disassembler.Tpo $(DEPDIR)/mini_disassembler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/mini_disassembler.cc' object='mini_disassembler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mini_disassembler.lo `test -f 'src/windows/mini_disassembler.cc' || echo '$(srcdir)/'`src/windows/mini_disassembler.cc
+
+patch_functions.lo: src/windows/patch_functions.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT patch_functions.lo -MD -MP -MF $(DEPDIR)/patch_functions.Tpo -c -o patch_functions.lo `test -f 'src/windows/patch_functions.cc' || echo '$(srcdir)/'`src/windows/patch_functions.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/patch_functions.Tpo $(DEPDIR)/patch_functions.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/patch_functions.cc' object='patch_functions.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o patch_functions.lo `test -f 'src/windows/patch_functions.cc' || echo '$(srcdir)/'`src/windows/patch_functions.cc
+
+preamble_patcher.lo: src/windows/preamble_patcher.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT preamble_patcher.lo -MD -MP -MF $(DEPDIR)/preamble_patcher.Tpo -c -o preamble_patcher.lo `test -f 'src/windows/preamble_patcher.cc' || echo '$(srcdir)/'`src/windows/preamble_patcher.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/preamble_patcher.Tpo $(DEPDIR)/preamble_patcher.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/preamble_patcher.cc' object='preamble_patcher.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o preamble_patcher.lo `test -f 'src/windows/preamble_patcher.cc' || echo '$(srcdir)/'`src/windows/preamble_patcher.cc
+
+preamble_patcher_with_stub.lo: src/windows/preamble_patcher_with_stub.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT preamble_patcher_with_stub.lo -MD -MP -MF $(DEPDIR)/preamble_patcher_with_stub.Tpo -c -o preamble_patcher_with_stub.lo `test -f 'src/windows/preamble_patcher_with_stub.cc' || echo '$(srcdir)/'`src/windows/preamble_patcher_with_stub.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/preamble_patcher_with_stub.Tpo $(DEPDIR)/preamble_patcher_with_stub.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/preamble_patcher_with_stub.cc' object='preamble_patcher_with_stub.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o preamble_patcher_with_stub.lo `test -f 'src/windows/preamble_patcher_with_stub.cc' || echo '$(srcdir)/'`src/windows/preamble_patcher_with_stub.cc
+
+addressmap_unittest-addressmap_unittest.o: src/tests/addressmap_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT addressmap_unittest-addressmap_unittest.o -MD -MP -MF $(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo -c -o addressmap_unittest-addressmap_unittest.o `test -f 'src/tests/addressmap_unittest.cc' || echo '$(srcdir)/'`src/tests/addressmap_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo $(DEPDIR)/addressmap_unittest-addressmap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/addressmap_unittest.cc' object='addressmap_unittest-addressmap_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o addressmap_unittest-addressmap_unittest.o `test -f 'src/tests/addressmap_unittest.cc' || echo '$(srcdir)/'`src/tests/addressmap_unittest.cc
+
+addressmap_unittest-addressmap_unittest.obj: src/tests/addressmap_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT addressmap_unittest-addressmap_unittest.obj -MD -MP -MF $(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/addressmap_unittest-addressmap_unittest.Tpo $(DEPDIR)/addressmap_unittest-addressmap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/addressmap_unittest.cc' object='addressmap_unittest-addressmap_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+addressmap_unittest-port.o: src/windows/port.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT addressmap_unittest-port.o -MD -MP -MF $(DEPDIR)/addressmap_unittest-port.Tpo -c -o addressmap_unittest-port.o `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/addressmap_unittest-port.Tpo $(DEPDIR)/addressmap_unittest-port.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/port.cc' object='addressmap_unittest-port.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o addressmap_unittest-port.o `test -f 'src/windows/port.cc' || echo '$(srcdir)/'`src/windows/port.cc
+
+addressmap_unittest-port.obj: src/windows/port.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -MT addressmap_unittest-port.obj -MD -MP -MF $(DEPDIR)/addressmap_unittest-port.Tpo -c -o 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@ mv -f $(DEPDIR)/addressmap_unittest-port.Tpo $(DEPDIR)/addressmap_unittest-port.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/windows/port.cc' object='addressmap_unittest-port.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(addressmap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+atomicops_unittest.o: src/tests/atomicops_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT atomicops_unittest.o -MD -MP -MF $(DEPDIR)/atomicops_unittest.Tpo -c -o atomicops_unittest.o `test -f 'src/tests/atomicops_unittest.cc' || echo '$(srcdir)/'`src/tests/atomicops_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/atomicops_unittest.Tpo $(DEPDIR)/atomicops_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/atomicops_unittest.cc' object='atomicops_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o atomicops_unittest.o `test -f 'src/tests/atomicops_unittest.cc' || echo '$(srcdir)/'`src/tests/atomicops_unittest.cc
+
+atomicops_unittest.obj: src/tests/atomicops_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT atomicops_unittest.obj -MD -MP -MF $(DEPDIR)/atomicops_unittest.Tpo -c -o atomicops_unittest.obj `if test -f 'src/tests/atomicops_unittest.cc'; then $(CYGPATH_W) 'src/tests/atomicops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/atomicops_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/atomicops_unittest.Tpo $(DEPDIR)/atomicops_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/atomicops_unittest.cc' object='atomicops_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o atomicops_unittest.obj `if test -f 'src/tests/atomicops_unittest.cc'; then $(CYGPATH_W) 'src/tests/atomicops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/atomicops_unittest.cc'; fi`
+
+current_allocated_bytes_test-current_allocated_bytes_test.o: src/tests/current_allocated_bytes_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -MT current_allocated_bytes_test-current_allocated_bytes_test.o -MD -MP -MF $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo -c -o 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@ mv -f $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/current_allocated_bytes_test.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -c -o 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
+
+current_allocated_bytes_test-current_allocated_bytes_test.obj: src/tests/current_allocated_bytes_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -MT current_allocated_bytes_test-current_allocated_bytes_test.obj -MD -MP -MF $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo -c -o 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@ mv -f $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Tpo $(DEPDIR)/current_allocated_bytes_test-current_allocated_bytes_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/current_allocated_bytes_test.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(current_allocated_bytes_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+debugallocation_test-debugallocation_test.o: src/tests/debugallocation_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT debugallocation_test-debugallocation_test.o -MD -MP -MF $(DEPDIR)/debugallocation_test-debugallocation_test.Tpo -c -o debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/debugallocation_test-debugallocation_test.Tpo $(DEPDIR)/debugallocation_test-debugallocation_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/debugallocation_test.cc' object='debugallocation_test-debugallocation_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc
+
+debugallocation_test-debugallocation_test.obj: src/tests/debugallocation_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT debugallocation_test-debugallocation_test.obj -MD -MP -MF $(DEPDIR)/debugallocation_test-debugallocation_test.Tpo -c -o 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@ mv -f $(DEPDIR)/debugallocation_test-debugallocation_test.Tpo $(DEPDIR)/debugallocation_test-debugallocation_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/debugallocation_test.cc' object='debugallocation_test-debugallocation_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+frag_unittest-frag_unittest.o: src/tests/frag_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -MT frag_unittest-frag_unittest.o -MD -MP -MF $(DEPDIR)/frag_unittest-frag_unittest.Tpo -c -o frag_unittest-frag_unittest.o `test -f 'src/tests/frag_unittest.cc' || echo '$(srcdir)/'`src/tests/frag_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/frag_unittest-frag_unittest.Tpo $(DEPDIR)/frag_unittest-frag_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/frag_unittest.cc' object='frag_unittest-frag_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -c -o frag_unittest-frag_unittest.o `test -f 'src/tests/frag_unittest.cc' || echo '$(srcdir)/'`src/tests/frag_unittest.cc
+
+frag_unittest-frag_unittest.obj: src/tests/frag_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -MT frag_unittest-frag_unittest.obj -MD -MP -MF $(DEPDIR)/frag_unittest-frag_unittest.Tpo -c -o frag_unittest-frag_unittest.obj `if test -f 'src/tests/frag_unittest.cc'; then $(CYGPATH_W) 'src/tests/frag_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/frag_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/frag_unittest-frag_unittest.Tpo $(DEPDIR)/frag_unittest-frag_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/frag_unittest.cc' object='frag_unittest-frag_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -c -o frag_unittest-frag_unittest.obj `if test -f 'src/tests/frag_unittest.cc'; then $(CYGPATH_W) 'src/tests/frag_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/frag_unittest.cc'; fi`
+
+getpc_test.o: src/tests/getpc_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT getpc_test.o -MD -MP -MF $(DEPDIR)/getpc_test.Tpo -c -o getpc_test.o `test -f 'src/tests/getpc_test.cc' || echo '$(srcdir)/'`src/tests/getpc_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/getpc_test.Tpo $(DEPDIR)/getpc_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/getpc_test.cc' object='getpc_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o getpc_test.o `test -f 'src/tests/getpc_test.cc' || echo '$(srcdir)/'`src/tests/getpc_test.cc
+
+getpc_test.obj: src/tests/getpc_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT getpc_test.obj -MD -MP -MF $(DEPDIR)/getpc_test.Tpo -c -o getpc_test.obj `if test -f 'src/tests/getpc_test.cc'; then $(CYGPATH_W) 'src/tests/getpc_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/getpc_test.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/getpc_test.Tpo $(DEPDIR)/getpc_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/getpc_test.cc' object='getpc_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o getpc_test.obj `if test -f 'src/tests/getpc_test.cc'; then $(CYGPATH_W) 'src/tests/getpc_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/getpc_test.cc'; fi`
+
+heap_checker_debug_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_debug_unittest-heap-checker_unittest.o -MD -MP -MF $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_debug_unittest-heap-checker_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_checker_debug_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc
+
+heap_checker_debug_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_debug_unittest-heap-checker_unittest.obj -MD -MP -MF $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo $(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_debug_unittest-heap-checker_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+heap_checker_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_unittest-heap-checker_unittest.o -MD -MP -MF $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo -c -o heap_checker_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_unittest-heap-checker_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_checker_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc
+
+heap_checker_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_unittest-heap-checker_unittest.obj -MD -MP -MF $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo $(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_unittest-heap-checker_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+heap_profiler_debug_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_debug_unittest-heap-profiler_unittest.o -MD -MP -MF $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_debug_unittest-heap-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_profiler_debug_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc
+
+heap_profiler_debug_unittest-heap-profiler_unittest.obj: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_debug_unittest-heap-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo $(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_debug_unittest-heap-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+heap_profiler_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_unittest-heap-profiler_unittest.o -MD -MP -MF $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_unittest-heap-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_profiler_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc
+
+heap_profiler_unittest-heap-profiler_unittest.obj: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_unittest-heap-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo $(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_unittest-heap-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+low_level_alloc_unittest-low_level_alloc.o: src/base/low_level_alloc.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-low_level_alloc.o -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo -c -o 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@ mv -f $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/low_level_alloc.cc' object='low_level_alloc_unittest-low_level_alloc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o low_level_alloc_unittest-low_level_alloc.o `test -f 'src/base/low_level_alloc.cc' || echo '$(srcdir)/'`src/base/low_level_alloc.cc
+
+low_level_alloc_unittest-low_level_alloc.obj: src/base/low_level_alloc.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-low_level_alloc.obj -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo -c -o 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@ mv -f $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Tpo $(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/low_level_alloc.cc' object='low_level_alloc_unittest-low_level_alloc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+low_level_alloc_unittest-malloc_hook.o: src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-malloc_hook.o -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo -c -o low_level_alloc_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_hook.cc' object='low_level_alloc_unittest-malloc_hook.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o low_level_alloc_unittest-malloc_hook.o `test -f 'src/malloc_hook.cc' || echo '$(srcdir)/'`src/malloc_hook.cc
+
+low_level_alloc_unittest-malloc_hook.obj: src/malloc_hook.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-malloc_hook.obj -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo -c -o 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@ mv -f $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Tpo $(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/malloc_hook.cc' object='low_level_alloc_unittest-malloc_hook.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+low_level_alloc_unittest-maybe_threads.o: src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-maybe_threads.o -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Tpo -c -o low_level_alloc_unittest-maybe_threads.o `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Tpo $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/maybe_threads.cc' object='low_level_alloc_unittest-maybe_threads.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o low_level_alloc_unittest-maybe_threads.o `test -f 'src/maybe_threads.cc' || echo '$(srcdir)/'`src/maybe_threads.cc
+
+low_level_alloc_unittest-maybe_threads.obj: src/maybe_threads.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-maybe_threads.obj -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Tpo -c -o low_level_alloc_unittest-maybe_threads.obj `if test -f 'src/maybe_threads.cc'; then $(CYGPATH_W) 'src/maybe_threads.cc'; else $(CYGPATH_W) '$(srcdir)/src/maybe_threads.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Tpo $(DEPDIR)/low_level_alloc_unittest-maybe_threads.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/maybe_threads.cc' object='low_level_alloc_unittest-maybe_threads.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o low_level_alloc_unittest-maybe_threads.obj `if test -f 'src/maybe_threads.cc'; then $(CYGPATH_W) 'src/maybe_threads.cc'; else $(CYGPATH_W) '$(srcdir)/src/maybe_threads.cc'; fi`
+
+low_level_alloc_unittest-low_level_alloc_unittest.o: src/tests/low_level_alloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-low_level_alloc_unittest.o -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/low_level_alloc_unittest.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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
+
+low_level_alloc_unittest-low_level_alloc_unittest.obj: src/tests/low_level_alloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT low_level_alloc_unittest-low_level_alloc_unittest.obj -MD -MP -MF $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Tpo $(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/low_level_alloc_unittest.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+malloc_extension_debug_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_debug_test-malloc_extension_test.o -MD -MP -MF $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_debug_test-malloc_extension_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_extension_debug_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc
+
+malloc_extension_debug_test-malloc_extension_test.obj: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_debug_test-malloc_extension_test.obj -MD -MP -MF $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo $(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_debug_test-malloc_extension_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+malloc_extension_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_test-malloc_extension_test.o -MD -MP -MF $(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo $(DEPDIR)/malloc_extension_test-malloc_extension_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_test-malloc_extension_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_extension_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc
+
+malloc_extension_test-malloc_extension_test.obj: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_test-malloc_extension_test.obj -MD -MP -MF $(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo $(DEPDIR)/malloc_extension_test-malloc_extension_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_test-malloc_extension_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+malloc_hook_test-malloc_hook_test.o: src/tests/malloc_hook_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_hook_test-malloc_hook_test.o -MD -MP -MF $(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo $(DEPDIR)/malloc_hook_test-malloc_hook_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_hook_test.cc' object='malloc_hook_test-malloc_hook_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_hook_test-malloc_hook_test.o `test -f 'src/tests/malloc_hook_test.cc' || echo '$(srcdir)/'`src/tests/malloc_hook_test.cc
+
+malloc_hook_test-malloc_hook_test.obj: src/tests/malloc_hook_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_hook_test-malloc_hook_test.obj -MD -MP -MF $(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_hook_test-malloc_hook_test.Tpo $(DEPDIR)/malloc_hook_test-malloc_hook_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_hook_test.cc' object='malloc_hook_test-malloc_hook_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+malloc_hook_test-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_hook_test-testutil.o -MD -MP -MF $(DEPDIR)/malloc_hook_test-testutil.Tpo -c -o malloc_hook_test-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/malloc_hook_test-testutil.Tpo $(DEPDIR)/malloc_hook_test-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='malloc_hook_test-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_hook_test-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+malloc_hook_test-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_hook_test-testutil.obj -MD -MP -MF $(DEPDIR)/malloc_hook_test-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/malloc_hook_test-testutil.Tpo $(DEPDIR)/malloc_hook_test-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='malloc_hook_test-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_hook_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+markidle_unittest-markidle_unittest.o: src/tests/markidle_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT markidle_unittest-markidle_unittest.o -MD -MP -MF $(DEPDIR)/markidle_unittest-markidle_unittest.Tpo -c -o markidle_unittest-markidle_unittest.o `test -f 'src/tests/markidle_unittest.cc' || echo '$(srcdir)/'`src/tests/markidle_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/markidle_unittest-markidle_unittest.Tpo $(DEPDIR)/markidle_unittest-markidle_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/markidle_unittest.cc' object='markidle_unittest-markidle_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o markidle_unittest-markidle_unittest.o `test -f 'src/tests/markidle_unittest.cc' || echo '$(srcdir)/'`src/tests/markidle_unittest.cc
+
+markidle_unittest-markidle_unittest.obj: src/tests/markidle_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT markidle_unittest-markidle_unittest.obj -MD -MP -MF $(DEPDIR)/markidle_unittest-markidle_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/markidle_unittest-markidle_unittest.Tpo $(DEPDIR)/markidle_unittest-markidle_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/markidle_unittest.cc' object='markidle_unittest-markidle_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+markidle_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT markidle_unittest-testutil.o -MD -MP -MF $(DEPDIR)/markidle_unittest-testutil.Tpo -c -o markidle_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/markidle_unittest-testutil.Tpo $(DEPDIR)/markidle_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='markidle_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o markidle_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+markidle_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -MT markidle_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/markidle_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/markidle_unittest-testutil.Tpo $(DEPDIR)/markidle_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='markidle_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+memalign_debug_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-memalign_unittest.o -MD -MP -MF $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo -c -o memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_debug_unittest-memalign_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc
+
+memalign_debug_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-memalign_unittest.obj -MD -MP -MF $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo $(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_debug_unittest-memalign_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+memalign_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-testutil.o -MD -MP -MF $(DEPDIR)/memalign_debug_unittest-testutil.Tpo -c -o memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/memalign_debug_unittest-testutil.Tpo $(DEPDIR)/memalign_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+memalign_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/memalign_debug_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/memalign_debug_unittest-testutil.Tpo $(DEPDIR)/memalign_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+memalign_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-memalign_unittest.o -MD -MP -MF $(DEPDIR)/memalign_unittest-memalign_unittest.Tpo -c -o memalign_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/memalign_unittest-memalign_unittest.Tpo $(DEPDIR)/memalign_unittest-memalign_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_unittest-memalign_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc
+
+memalign_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-memalign_unittest.obj -MD -MP -MF $(DEPDIR)/memalign_unittest-memalign_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/memalign_unittest-memalign_unittest.Tpo $(DEPDIR)/memalign_unittest-memalign_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_unittest-memalign_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+memalign_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-testutil.o -MD -MP -MF $(DEPDIR)/memalign_unittest-testutil.Tpo -c -o memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/memalign_unittest-testutil.Tpo $(DEPDIR)/memalign_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+memalign_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/memalign_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/memalign_unittest-testutil.Tpo $(DEPDIR)/memalign_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+packed_cache_test-packed-cache_test.o: src/tests/packed-cache_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT packed_cache_test-packed-cache_test.o -MD -MP -MF $(DEPDIR)/packed_cache_test-packed-cache_test.Tpo -c -o 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@ mv -f $(DEPDIR)/packed_cache_test-packed-cache_test.Tpo $(DEPDIR)/packed_cache_test-packed-cache_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed_cache_test-packed-cache_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o packed_cache_test-packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc
+
+packed_cache_test-packed-cache_test.obj: src/tests/packed-cache_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT packed_cache_test-packed-cache_test.obj -MD -MP -MF $(DEPDIR)/packed_cache_test-packed-cache_test.Tpo -c -o 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@ mv -f $(DEPDIR)/packed_cache_test-packed-cache_test.Tpo $(DEPDIR)/packed_cache_test-packed-cache_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed_cache_test-packed-cache_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+page_heap_test-page_heap_test.o: src/tests/page_heap_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -MT page_heap_test-page_heap_test.o -MD -MP -MF $(DEPDIR)/page_heap_test-page_heap_test.Tpo -c -o 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@ mv -f $(DEPDIR)/page_heap_test-page_heap_test.Tpo $(DEPDIR)/page_heap_test-page_heap_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/page_heap_test.cc' object='page_heap_test-page_heap_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -c -o page_heap_test-page_heap_test.o `test -f 'src/tests/page_heap_test.cc' || echo '$(srcdir)/'`src/tests/page_heap_test.cc
+
+page_heap_test-page_heap_test.obj: src/tests/page_heap_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -MT page_heap_test-page_heap_test.obj -MD -MP -MF $(DEPDIR)/page_heap_test-page_heap_test.Tpo -c -o 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@ mv -f $(DEPDIR)/page_heap_test-page_heap_test.Tpo $(DEPDIR)/page_heap_test-page_heap_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/page_heap_test.cc' object='page_heap_test-page_heap_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(page_heap_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+pagemap_unittest-pagemap_unittest.o: src/tests/pagemap_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -MT pagemap_unittest-pagemap_unittest.o -MD -MP -MF $(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo -c -o pagemap_unittest-pagemap_unittest.o `test -f 'src/tests/pagemap_unittest.cc' || echo '$(srcdir)/'`src/tests/pagemap_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo $(DEPDIR)/pagemap_unittest-pagemap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/pagemap_unittest.cc' object='pagemap_unittest-pagemap_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o pagemap_unittest-pagemap_unittest.o `test -f 'src/tests/pagemap_unittest.cc' || echo '$(srcdir)/'`src/tests/pagemap_unittest.cc
+
+pagemap_unittest-pagemap_unittest.obj: src/tests/pagemap_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -MT pagemap_unittest-pagemap_unittest.obj -MD -MP -MF $(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo $(DEPDIR)/pagemap_unittest-pagemap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/pagemap_unittest.cc' object='pagemap_unittest-pagemap_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profile_handler_unittest-profile-handler_unittest.o: src/tests/profile-handler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -MT profile_handler_unittest-profile-handler_unittest.o -MD -MP -MF $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profile-handler_unittest.cc' object='profile_handler_unittest-profile-handler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profile_handler_unittest-profile-handler_unittest.o `test -f 'src/tests/profile-handler_unittest.cc' || echo '$(srcdir)/'`src/tests/profile-handler_unittest.cc
+
+profile_handler_unittest-profile-handler_unittest.obj: src/tests/profile-handler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -MT profile_handler_unittest-profile-handler_unittest.obj -MD -MP -MF $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Tpo $(DEPDIR)/profile_handler_unittest-profile-handler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profile-handler_unittest.cc' object='profile_handler_unittest-profile-handler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profile_handler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiledata_unittest.o: src/tests/profiledata_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT profiledata_unittest.o -MD -MP -MF $(DEPDIR)/profiledata_unittest.Tpo -c -o profiledata_unittest.o `test -f 'src/tests/profiledata_unittest.cc' || echo '$(srcdir)/'`src/tests/profiledata_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiledata_unittest.Tpo $(DEPDIR)/profiledata_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiledata_unittest.cc' object='profiledata_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profiledata_unittest.o `test -f 'src/tests/profiledata_unittest.cc' || echo '$(srcdir)/'`src/tests/profiledata_unittest.cc
+
+profiledata_unittest.obj: src/tests/profiledata_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT profiledata_unittest.obj -MD -MP -MF $(DEPDIR)/profiledata_unittest.Tpo -c -o profiledata_unittest.obj `if test -f 'src/tests/profiledata_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiledata_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiledata_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiledata_unittest.Tpo $(DEPDIR)/profiledata_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiledata_unittest.cc' object='profiledata_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o profiledata_unittest.obj `if test -f 'src/tests/profiledata_unittest.cc'; then $(CYGPATH_W) 'src/tests/profiledata_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/profiledata_unittest.cc'; fi`
+
+profiler1_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler1_unittest-profiler_unittest.o -MD -MP -MF $(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo -c -o profiler1_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler1_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler1_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler1_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+
+profiler1_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler1_unittest-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler1_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler1_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler1_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler1_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler1_unittest-testutil.o -MD -MP -MF $(DEPDIR)/profiler1_unittest-testutil.Tpo -c -o profiler1_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler1_unittest-testutil.Tpo $(DEPDIR)/profiler1_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler1_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler1_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+profiler1_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler1_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/profiler1_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler1_unittest-testutil.Tpo $(DEPDIR)/profiler1_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler1_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler1_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler2_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler2_unittest-profiler_unittest.o -MD -MP -MF $(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo -c -o profiler2_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler2_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler2_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler2_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+
+profiler2_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler2_unittest-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler2_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler2_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler2_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler2_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler2_unittest-testutil.o -MD -MP -MF $(DEPDIR)/profiler2_unittest-testutil.Tpo -c -o profiler2_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler2_unittest-testutil.Tpo $(DEPDIR)/profiler2_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler2_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler2_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+profiler2_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler2_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/profiler2_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler2_unittest-testutil.Tpo $(DEPDIR)/profiler2_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler2_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler2_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler3_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler3_unittest-profiler_unittest.o -MD -MP -MF $(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo -c -o profiler3_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler3_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler3_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler3_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+
+profiler3_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler3_unittest-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler3_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler3_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler3_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler3_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler3_unittest-testutil.o -MD -MP -MF $(DEPDIR)/profiler3_unittest-testutil.Tpo -c -o profiler3_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler3_unittest-testutil.Tpo $(DEPDIR)/profiler3_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler3_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler3_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+profiler3_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler3_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/profiler3_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler3_unittest-testutil.Tpo $(DEPDIR)/profiler3_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler3_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler3_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler4_unittest-profiler_unittest.o: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler4_unittest-profiler_unittest.o -MD -MP -MF $(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo -c -o profiler4_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler4_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler4_unittest-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler4_unittest-profiler_unittest.o `test -f 'src/tests/profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/profiler_unittest.cc
+
+profiler4_unittest-profiler_unittest.obj: src/tests/profiler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler4_unittest-profiler_unittest.obj -MD -MP -MF $(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler4_unittest-profiler_unittest.Tpo $(DEPDIR)/profiler4_unittest-profiler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/profiler_unittest.cc' object='profiler4_unittest-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+profiler4_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler4_unittest-testutil.o -MD -MP -MF $(DEPDIR)/profiler4_unittest-testutil.Tpo -c -o profiler4_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/profiler4_unittest-testutil.Tpo $(DEPDIR)/profiler4_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler4_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o profiler4_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+profiler4_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -MT profiler4_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/profiler4_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/profiler4_unittest-testutil.Tpo $(DEPDIR)/profiler4_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='profiler4_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(profiler4_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+raw_printer_test-raw_printer_test.o: src/tests/raw_printer_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -MT raw_printer_test-raw_printer_test.o -MD -MP -MF $(DEPDIR)/raw_printer_test-raw_printer_test.Tpo -c -o 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@ mv -f $(DEPDIR)/raw_printer_test-raw_printer_test.Tpo $(DEPDIR)/raw_printer_test-raw_printer_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/raw_printer_test.cc' object='raw_printer_test-raw_printer_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -c -o raw_printer_test-raw_printer_test.o `test -f 'src/tests/raw_printer_test.cc' || echo '$(srcdir)/'`src/tests/raw_printer_test.cc
+
+raw_printer_test-raw_printer_test.obj: src/tests/raw_printer_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -MT raw_printer_test-raw_printer_test.obj -MD -MP -MF $(DEPDIR)/raw_printer_test-raw_printer_test.Tpo -c -o 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@ mv -f $(DEPDIR)/raw_printer_test-raw_printer_test.Tpo $(DEPDIR)/raw_printer_test-raw_printer_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/raw_printer_test.cc' object='raw_printer_test-raw_printer_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+realloc_debug_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_debug_unittest-realloc_unittest.o -MD -MP -MF $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo -c -o realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_debug_unittest-realloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc
+
+realloc_debug_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_debug_unittest-realloc_unittest.obj -MD -MP -MF $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo $(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_debug_unittest-realloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+realloc_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_unittest-realloc_unittest.o -MD -MP -MF $(DEPDIR)/realloc_unittest-realloc_unittest.Tpo -c -o realloc_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/realloc_unittest-realloc_unittest.Tpo $(DEPDIR)/realloc_unittest-realloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_unittest-realloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o realloc_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc
+
+realloc_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_unittest-realloc_unittest.obj -MD -MP -MF $(DEPDIR)/realloc_unittest-realloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/realloc_unittest-realloc_unittest.Tpo $(DEPDIR)/realloc_unittest-realloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_unittest-realloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+sampler_debug_test-sampler_test.o: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_debug_test-sampler_test.o -MD -MP -MF $(DEPDIR)/sampler_debug_test-sampler_test.Tpo -c -o sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sampler_debug_test-sampler_test.Tpo $(DEPDIR)/sampler_debug_test-sampler_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_debug_test-sampler_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc
+
+sampler_debug_test-sampler_test.obj: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_debug_test-sampler_test.obj -MD -MP -MF $(DEPDIR)/sampler_debug_test-sampler_test.Tpo -c -o 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@ mv -f $(DEPDIR)/sampler_debug_test-sampler_test.Tpo $(DEPDIR)/sampler_debug_test-sampler_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_debug_test-sampler_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+sampler_test-sampler_test.o: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_test-sampler_test.o -MD -MP -MF $(DEPDIR)/sampler_test-sampler_test.Tpo -c -o sampler_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sampler_test-sampler_test.Tpo $(DEPDIR)/sampler_test-sampler_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_test-sampler_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -c -o sampler_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc
+
+sampler_test-sampler_test.obj: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_test-sampler_test.obj -MD -MP -MF $(DEPDIR)/sampler_test-sampler_test.Tpo -c -o 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@ mv -f $(DEPDIR)/sampler_test-sampler_test.Tpo $(DEPDIR)/sampler_test-sampler_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_test-sampler_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+sampling_debug_test-sampling_test.o: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_debug_test-sampling_test.o -MD -MP -MF $(DEPDIR)/sampling_debug_test-sampling_test.Tpo -c -o sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sampling_debug_test-sampling_test.Tpo $(DEPDIR)/sampling_debug_test-sampling_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_debug_test-sampling_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc
+
+sampling_debug_test-sampling_test.obj: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_debug_test-sampling_test.obj -MD -MP -MF $(DEPDIR)/sampling_debug_test-sampling_test.Tpo -c -o 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@ mv -f $(DEPDIR)/sampling_debug_test-sampling_test.Tpo $(DEPDIR)/sampling_debug_test-sampling_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_debug_test-sampling_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+sampling_test-sampling_test.o: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_test-sampling_test.o -MD -MP -MF $(DEPDIR)/sampling_test-sampling_test.Tpo -c -o sampling_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/sampling_test-sampling_test.Tpo $(DEPDIR)/sampling_test-sampling_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_test-sampling_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -c -o sampling_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc
+
+sampling_test-sampling_test.obj: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_test-sampling_test.obj -MD -MP -MF $(DEPDIR)/sampling_test-sampling_test.Tpo -c -o 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@ mv -f $(DEPDIR)/sampling_test-sampling_test.Tpo $(DEPDIR)/sampling_test-sampling_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_test-sampling_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+simple_compat_test.o: src/tests/simple_compat_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT simple_compat_test.o -MD -MP -MF $(DEPDIR)/simple_compat_test.Tpo -c -o simple_compat_test.o `test -f 'src/tests/simple_compat_test.cc' || echo '$(srcdir)/'`src/tests/simple_compat_test.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/simple_compat_test.Tpo $(DEPDIR)/simple_compat_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/simple_compat_test.cc' object='simple_compat_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o simple_compat_test.o `test -f 'src/tests/simple_compat_test.cc' || echo '$(srcdir)/'`src/tests/simple_compat_test.cc
+
+simple_compat_test.obj: src/tests/simple_compat_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT simple_compat_test.obj -MD -MP -MF $(DEPDIR)/simple_compat_test.Tpo -c -o simple_compat_test.obj `if test -f 'src/tests/simple_compat_test.cc'; then $(CYGPATH_W) 'src/tests/simple_compat_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/simple_compat_test.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/simple_compat_test.Tpo $(DEPDIR)/simple_compat_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/simple_compat_test.cc' object='simple_compat_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o simple_compat_test.obj `if test -f 'src/tests/simple_compat_test.cc'; then $(CYGPATH_W) 'src/tests/simple_compat_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/simple_compat_test.cc'; fi`
+
+stack_trace_table_test-stack_trace_table_test.o: src/tests/stack_trace_table_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -MT stack_trace_table_test-stack_trace_table_test.o -MD -MP -MF $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo -c -o 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@ mv -f $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/stack_trace_table_test.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -c -o 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
+
+stack_trace_table_test-stack_trace_table_test.obj: src/tests/stack_trace_table_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -MT stack_trace_table_test-stack_trace_table_test.obj -MD -MP -MF $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo -c -o 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@ mv -f $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Tpo $(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/stack_trace_table_test.cc' object='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@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stack_trace_table_test_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+stacktrace_unittest.o: src/tests/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_unittest.o -MD -MP -MF $(DEPDIR)/stacktrace_unittest.Tpo -c -o stacktrace_unittest.o `test -f 'src/tests/stacktrace_unittest.cc' || echo '$(srcdir)/'`src/tests/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace_unittest.Tpo $(DEPDIR)/stacktrace_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/stacktrace_unittest.cc' object='stacktrace_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_unittest.o `test -f 'src/tests/stacktrace_unittest.cc' || echo '$(srcdir)/'`src/tests/stacktrace_unittest.cc
+
+stacktrace_unittest.obj: src/tests/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_unittest.obj -MD -MP -MF $(DEPDIR)/stacktrace_unittest.Tpo -c -o stacktrace_unittest.obj `if test -f 'src/tests/stacktrace_unittest.cc'; then $(CYGPATH_W) 'src/tests/stacktrace_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/stacktrace_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace_unittest.Tpo $(DEPDIR)/stacktrace_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/stacktrace_unittest.cc' object='stacktrace_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_unittest.obj `if test -f 'src/tests/stacktrace_unittest.cc'; then $(CYGPATH_W) 'src/tests/stacktrace_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/stacktrace_unittest.cc'; fi`
+
+system_alloc_unittest-system-alloc_unittest.o: src/tests/system-alloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT system_alloc_unittest-system-alloc_unittest.o -MD -MP -MF $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/system-alloc_unittest.cc' object='system_alloc_unittest-system-alloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o system_alloc_unittest-system-alloc_unittest.o `test -f 'src/tests/system-alloc_unittest.cc' || echo '$(srcdir)/'`src/tests/system-alloc_unittest.cc
+
+system_alloc_unittest-system-alloc_unittest.obj: src/tests/system-alloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT system_alloc_unittest-system-alloc_unittest.obj -MD -MP -MF $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Tpo $(DEPDIR)/system_alloc_unittest-system-alloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/system-alloc_unittest.cc' object='system_alloc_unittest-system-alloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(system_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_and_profiler_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_and_profiler_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_and_profiler_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_and_profiler_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_and_profiler_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_and_profiler_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_and_profiler_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_and_profiler_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_and_profiler_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo -c -o tcmalloc_and_profiler_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_and_profiler_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_and_profiler_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_and_profiler_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_and_profiler_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_and_profiler_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_and_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_both_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_both_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_both_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_both_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_both_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_both_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_both_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_both_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_both_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_both_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo -c -o tcmalloc_both_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_both_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_both_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_both_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_both_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_both_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_both_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_both_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_both_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo -c -o tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_large_unittest.cc' object='tcmalloc_large_unittest-tcmalloc_large_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc
+
+tcmalloc_large_unittest-tcmalloc_large_unittest.obj: src/tests/tcmalloc_large_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_large_unittest-tcmalloc_large_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo $(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_large_unittest.cc' object='tcmalloc_large_unittest-tcmalloc_large_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_minimal_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo -c -o tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_minimal_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_large_unittest.cc' object='tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc
+
+tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj: src/tests/tcmalloc_large_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_large_unittest.cc' object='tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_minimal_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_minimal_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_minimal_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_minimal_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo -c -o tcmalloc_minimal_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_minimal_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_unittest-tcmalloc_unittest.o -MD -MP -MF $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo -c -o tcmalloc_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_unittest-tcmalloc_unittest.obj -MD -MP -MF $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Tpo $(DEPDIR)/tcmalloc_unittest-tcmalloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+tcmalloc_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_unittest-testutil.o -MD -MP -MF $(DEPDIR)/tcmalloc_unittest-testutil.Tpo -c -o tcmalloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/tcmalloc_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/tcmalloc_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/tcmalloc_unittest-testutil.Tpo $(DEPDIR)/tcmalloc_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+thread_dealloc_unittest-thread_dealloc_unittest.o: src/tests/thread_dealloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT thread_dealloc_unittest-thread_dealloc_unittest.o -MD -MP -MF $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/thread_dealloc_unittest.cc' object='thread_dealloc_unittest-thread_dealloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o thread_dealloc_unittest-thread_dealloc_unittest.o `test -f 'src/tests/thread_dealloc_unittest.cc' || echo '$(srcdir)/'`src/tests/thread_dealloc_unittest.cc
+
+thread_dealloc_unittest-thread_dealloc_unittest.obj: src/tests/thread_dealloc_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT thread_dealloc_unittest-thread_dealloc_unittest.obj -MD -MP -MF $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo -c -o 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@ mv -f $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Tpo $(DEPDIR)/thread_dealloc_unittest-thread_dealloc_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/thread_dealloc_unittest.cc' object='thread_dealloc_unittest-thread_dealloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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`
+
+thread_dealloc_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT thread_dealloc_unittest-testutil.o -MD -MP -MF $(DEPDIR)/thread_dealloc_unittest-testutil.Tpo -c -o thread_dealloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/thread_dealloc_unittest-testutil.Tpo $(DEPDIR)/thread_dealloc_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='thread_dealloc_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o thread_dealloc_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+thread_dealloc_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT thread_dealloc_unittest-testutil.obj -MD -MP -MF $(DEPDIR)/thread_dealloc_unittest-testutil.Tpo -c -o 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@ mv -f $(DEPDIR)/thread_dealloc_unittest-testutil.Tpo $(DEPDIR)/thread_dealloc_unittest-testutil.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='thread_dealloc_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(thread_dealloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o 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
+
+distclean-libtool:
+ -rm -f libtool
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+install-dist_docDATA: $(dist_doc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
+ @list='$(dist_doc_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(dist_docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \
+ $(dist_docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \
+ done
+
+uninstall-dist_docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_doc_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(docdir)/$$f"; \
+ done
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(pkgconfigDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ $(pkgconfigDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(pkgconfigdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgconfigdir)/$$f"; \
+ done
+install-googleincludeHEADERS: $(googleinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(googleincludedir)" || $(MKDIR_P) "$(DESTDIR)$(googleincludedir)"
+ @list='$(googleinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(googleincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(googleincludedir)/$$f'"; \
+ $(googleincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(googleincludedir)/$$f"; \
+ done
+
+uninstall-googleincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(googleinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(googleincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(googleincludedir)/$$f"; \
+ done
+install-nodist_perftoolsincludeHEADERS: $(nodist_perftoolsinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(perftoolsincludedir)" || $(MKDIR_P) "$(DESTDIR)$(perftoolsincludedir)"
+ @list='$(nodist_perftoolsinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(nodist_perftoolsincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(perftoolsincludedir)/$$f'"; \
+ $(nodist_perftoolsincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(perftoolsincludedir)/$$f"; \
+ done
+
+uninstall-nodist_perftoolsincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_perftoolsinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(perftoolsincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(perftoolsincludedir)/$$f"; \
+ done
+install-perftoolsincludeHEADERS: $(perftoolsinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(perftoolsincludedir)" || $(MKDIR_P) "$(DESTDIR)$(perftoolsincludedir)"
+ @list='$(perftoolsinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(perftoolsincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(perftoolsincludedir)/$$f'"; \
+ $(perftoolsincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(perftoolsincludedir)/$$f"; \
+ done
+
+uninstall-perftoolsincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(perftoolsinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(perftoolsincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(perftoolsincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(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 $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__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*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(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
+ $(am__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:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { 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 $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \
+ $(HEADERS) all-local
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+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 -rf ./$(DEPDIR)
+ -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
+
+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-exec-am: install-binPROGRAMS install-binSCRIPTS \
+ install-exec-local install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man1
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -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: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am all-local am--refresh check check-TESTS \
+ check-am clean clean-binPROGRAMS clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \
+ dist-hook dist-lzma dist-shar dist-tarZ dist-zip distcheck \
+ distclean distclean-compile distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-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 \
+ tags 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
+
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@ # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_AND_NO_FP_BY_DEFAULT_TRUE@ # before setting this.
+@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@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
+
+# Windows wants write permission to .vcproj files and maybe even sln files.
+dist-hook:
+ test -e "$(distdir)/vsprojects" \
+ && chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/chromium/third_party/tcmalloc/vendor/NEWS b/chromium/third_party/tcmalloc/vendor/NEWS
new file mode 100644
index 00000000000..34ca1b0ef7a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/NEWS
@@ -0,0 +1,338 @@
+== 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 <gperftools/tcmalloc.h>`/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
+<google/tcmalloc.h>` 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/chromium/third_party/tcmalloc/vendor/README b/chromium/third_party/tcmalloc/vendor/README
new file mode 100644
index 00000000000..667bea1afc2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/README
@@ -0,0 +1,265 @@
+IMPORTANT NOTE FOR 64-BIT USERS
+-------------------------------
+There are known issues with some perftools functionality on x86_64
+systems. See 64-BIT ISSUES, below.
+
+
+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.
+
+NOTE: When compiling with programs with gcc, that you plan to link
+with libtcmalloc, it's safest to pass in the flags
+
+ -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+
+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 doc/heap-profiler.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 <path/to/binary> [binary args]
+3) Run pprof to analyze the heap usage
+ $ pprof <path/to/binary> /tmp/heapprof.0045.heap # run 'ls' to see options
+ $ pprof --gv <path/to/binary> /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 doc/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 <path/to/binary> [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 doc/cpu-profiler.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 <path/to/binary> [binary args]
+3) Run pprof to analyze the CPU usage
+ $ pprof <path/to/binary> /tmp/prof.out # -pg-like text output
+ $ pprof --gv <path/to/binary> /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 performace. (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=<pre> -- turns on heap profiling and dumps data using this prefix
+HEAPCHECK=<type> -- turns on heap checking with strictness 'type'
+CPUPROFILE=<file> -- 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().
+PROFILEFREQUENCY=x-- how many interrupts/second the cpu-profiler samples.
+
+TCMALLOC_DEBUG=<level> -- the higher level, the more messages malloc emits
+MALLOCSTATS=<level> -- prints memory-use stats at program-exit
+
+For a full list of variables, see the documentation pages:
+ doc/cpuprofile.html
+ doc/heapprofile.html
+ doc/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
+crashses.
+
+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/chromium/third_party/tcmalloc/vendor/README_windows.txt b/chromium/third_party/tcmalloc/vendor/README_windows.txt
new file mode 100644
index 00000000000..16ea9d6e923
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/README_windows.txt
@@ -0,0 +1,118 @@
+--- COMPILING
+
+This project has begun being ported to Windows. 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. 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/chromium/third_party/tcmalloc/vendor/TODO b/chromium/third_party/tcmalloc/vendor/TODO
new file mode 100644
index 00000000000..550f7e09b9d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/aclocal.m4 b/chromium/third_party/tcmalloc/vendor/aclocal.m4
new file mode 100644
index 00000000000..56700c7e744
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/aclocal.m4
@@ -0,0 +1,928 @@
+# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008 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_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(AC_AUTOCONF_VERSION, [2.65],,
+[m4_warning([this file was generated for autoconf 2.65.
+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, 2003, 2005, 2006, 2007 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.10'
+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.10.1], [],
+ [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 AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 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],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# 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.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$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
+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, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# 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.
+
+# serial 9
+
+# 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", "GCJ", or "OBJC".
+# 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
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" 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'.
+ 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
+ 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 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ 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
+ ;;
+ none) break ;;
+ esac
+ # 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.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} 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 sub/conftest.${OBJEXT-o} 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,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# 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.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _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. FIXME. This creates each `.P' file that we will
+# 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" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# 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.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 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.
+
+# serial 13
+
+# 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.
+
+# 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.60])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],
+[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], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [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)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. 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)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# 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, 2003, 2005 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
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 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.
+
+# serial 2
+
+# 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])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 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.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005
+# 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.
+
+# serial 5
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_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
+dnl Make sure AC_PROG_CC is never called again, or it will override our
+dnl setting of CC.
+m4_define([AC_PROG_CC],
+ [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# 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.
+
+# serial 5
+
+# 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 supports --run.
+# If it does, 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
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 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_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 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.
+
+# serial 3
+
+# _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],
+[AC_FOREACH([_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])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# 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.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# 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 (
+ 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
+ rm -f conftest.file
+ 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
+
+ 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)])
+
+# Copyright (C) 2001, 2003, 2005 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 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])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 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.
+
+# serial 2
+
+# _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.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+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 <conftest.tar])
+ grep GrepMe conftest.dir/file >/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/compiler_characteristics.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/namespaces.m4])
+m4_include([m4/pc_from_ucontext.m4])
+m4_include([m4/program_invocation_name.m4])
+m4_include([m4/stl_namespace.m4])
diff --git a/chromium/third_party/tcmalloc/vendor/autogen.sh b/chromium/third_party/tcmalloc/vendor/autogen.sh
new file mode 100644
index 00000000000..09396a8e648
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/autogen.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# Before using, you should figure out all the .m4 macros that your
+# configure.m4 script needs and make sure they exist in the m4/
+# directory.
+#
+# These are the files that this script might edit:
+# aclocal.m4 configure Makefile.in src/config.h.in \
+# depcomp config.guess config.sub install-sh missing mkinstalldirs \
+# ltmain.sh
+#
+# Here's a command you can run to see what files aclocal will import:
+# aclocal -I ../autoconf --output=- | sed -n 's/^m4_include..\([^]]*\).*/\1/p'
+
+set -ex
+rm -rf autom4te.cache
+
+trap 'rm -f aclocal.m4.tmp' EXIT
+
+# Returns the first binary in $* that exists, or the last arg, if none exists.
+WhichOf() {
+ for candidate in "$@"; do
+ if "$candidate" --version >/dev/null 2>&1; then
+ echo "$candidate"
+ return
+ fi
+ done
+ echo "$candidate" # the last one in $@
+}
+
+# Use version 1.9 of aclocal and automake if available.
+ACLOCAL=`WhichOf aclocal-1.9 aclocal`
+AUTOMAKE=`WhichOf automake-1.9 automake`
+LIBTOOLIZE=`WhichOf glibtoolize libtoolize15 libtoolize14 libtoolize`
+
+# aclocal tries to overwrite aclocal.m4 even if the contents haven't
+# changed, which is annoying when the file is not open for edit (in
+# p4). We work around this by writing to a temp file and just
+# updating the timestamp if the file hasn't change.
+"$ACLOCAL" --force -I m4 --output=aclocal.m4.tmp
+if cmp aclocal.m4.tmp aclocal.m4; then
+ touch aclocal.m4 # pretend that we regenerated the file
+ rm -f aclocal.m4.tmp
+else
+ mv aclocal.m4.tmp aclocal.m4 # we did set -e above, so we die if this fails
+fi
+
+grep -q '^[^#]*AC_PROG_LIBTOOL' configure.ac && "$LIBTOOLIZE" -c -f
+autoconf -f -W all,no-obsolete
+autoheader -f -W all
+"$AUTOMAKE" -a -c -f -W all
+
+rm -rf autom4te.cache
+exit 0
diff --git a/chromium/third_party/tcmalloc/vendor/compile b/chromium/third_party/tcmalloc/vendor/compile
new file mode 100644
index 00000000000..1b1d2321695
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/compile
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2005-05-14.22
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# 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 <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+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 <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+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 -e 's|^.*/||' -e '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
+ mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/config.guess b/chromium/third_party/tcmalloc/vendor/config.guess
new file mode 100644
index 00000000000..ca2a03ca4f1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-08'
+
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# 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 Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 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
+
+# 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 tupples: *-*-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=`(/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 ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ 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
+ # 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/[-_].*/\./'`
+ ;;
+ 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}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${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 ;;
+ 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'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ 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 ;;
+ 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:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ echo i386-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 <stdio.h> /* 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 <sys/systemcfg.h>
+
+ 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:*:[456])
+ 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/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ 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:BSD:*)
+ 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 <stdlib.h>
+ #include <unistd.h>
+
+ 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 __LP64__ >/dev/null
+ 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 <unistd.h>
+ 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:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-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-gnu`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 '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ 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-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ 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 ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${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-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; 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.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V: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' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/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 i386.
+ echo i386-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; } ;;
+ 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.0*:*)
+ 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 <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # 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 ;;
+ 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 ;;
+ 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
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ 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 ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-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 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+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`
+/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-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/config.sub b/chromium/third_party/tcmalloc/vendor/config.sub
new file mode 100644
index 00000000000..6759825a5b7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/config.sub
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# 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.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# 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.
+
+# 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
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 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-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ 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)
+ os=
+ basic_machine=$1
+ ;;
+ -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*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -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 \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | 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 \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-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-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | 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-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # 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-unknown
+ 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
+ ;;
+ 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
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ 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)
+ 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
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ 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
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ 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
+ ;;
+ i386-vsta | 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
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-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
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ 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
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-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) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ 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 | ppc64-le | powerpc64-little)
+ 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)
+ 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
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | 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
+ ;;
+ 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
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-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
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ 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
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ 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.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First 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* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -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* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # 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 | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -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
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -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
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -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
+ ;;
+ # 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
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ 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
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-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
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-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
+ ;;
+ -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-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/configure b/chromium/third_party/tcmalloc/vendor/configure
new file mode 100644
index 00000000000..1b446374c7f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/configure
@@ -0,0 +1,19825 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.65 for gperftools 2.0.
+#
+# Report bugs to <google-perftools@googlegroups.com>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
+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
+
+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"
+ 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 \$(( 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 :
+ # 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.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+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: google-perftools@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_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 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=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&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; }
+
+ # 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 -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+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
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# 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'"
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<_LT_EOF
+$*
+_LT_EOF
+ exit 0
+fi
+
+# 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
+
+if test -z "$lt_ECHO"; then
+ if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+ { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+ then
+ break
+ fi
+ done
+ fi
+
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+ else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$ECHO" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ ECHO='print -r'
+ elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ ECHO='printf %s\n'
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ ECHO="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ ECHO=echo
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, 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.0'
+PACKAGE_STRING='gperftools 2.0'
+PACKAGE_BUGREPORT='google-perftools@googlegroups.com'
+PACKAGE_URL=''
+
+ac_unique_file="README"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_list=
+ac_subst_vars='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
+PTHREAD_CFLAGS
+PTHREAD_LIBS
+PTHREAD_CC
+acx_pthread_config
+LIBSTDCXX_LA_LINKER_FLAG
+NANOSLEEP_LIBS
+HAVE_W_NO_UNUSED_RESULT_FALSE
+HAVE_W_NO_UNUSED_RESULT_TRUE
+I386_FALSE
+I386_TRUE
+X86_64_AND_NO_FP_BY_DEFAULT_FALSE
+X86_64_AND_NO_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
+USE_LIBTOOL_FALSE
+USE_LIBTOOL_TRUE
+LIBTOOL_DEPS
+CXXCPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+lt_ECHO
+RANLIB
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+LIBTOOL
+HAVE_OBJCOPY_WEAKEN_FALSE
+HAVE_OBJCOPY_WEAKEN_TRUE
+OBJCOPY
+GCC_FALSE
+GCC_TRUE
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+ac_ct_CC
+CFLAGS
+CC
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+TC_VERSION_PATCH
+TC_VERSION_MINOR
+TC_VERSION_MAJOR
+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
+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
+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'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_cpu_profiler
+enable_heap_profiler
+enable_heap_checker
+enable_debugalloc
+enable_minimal
+enable_dependency_tracking
+enable_fast_install
+enable_shared
+enable_static
+with_pic
+with_gnu_ld
+enable_libtool_lock
+enable_frame_pointers
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CPP
+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'
+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=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 ;;
+
+ -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
+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
+ $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ 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.0 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]
+ --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.0:";;
+ 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]
+ --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)
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=no]
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [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)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CC C compiler command
+ CFLAGS C compiler flags
+ CPP C preprocessor
+ 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 <google-perftools@googlegroups.com>.
+_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.0
+generated by GNU Autoconf 2.65
+
+Copyright (C) 2009 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_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_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; } >/dev/null && {
+ 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 ||
+ $as_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; test "x$as_lineno_stack" = x && { as_lineno=; 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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 <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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; test "x$as_lineno_stack" = x && { as_lineno=; 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; } >/dev/null && {
+ 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 ||
+ $as_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; test "x$as_lineno_stack" = x && { as_lineno=; 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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.$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;}
+( cat <<\_ASBOX
+## ------------------------------------------------ ##
+## Report this to google-perftools@googlegroups.com ##
+## ------------------------------------------------ ##
+_ASBOX
+ ) | 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR
+# ------------------------------------
+# Tests whether SYMBOL is declared, 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_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
+$as_echo_n "checking whether $2 is declared... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $2
+ (void) $2;
+#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; test "x$as_lineno_stack" = x && { as_lineno=; 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.0, which was
+generated by GNU Autoconf 2.65. 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
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ 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
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ 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
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ 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
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ 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
+ ac_site_file1=$CONFIG_SITE
+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"
+ 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
+
+as_fn_append ac_header_list " stdlib.h"
+as_fn_append ac_header_list " unistd.h"
+as_fn_append ac_header_list " sys/param.h"
+# 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=5:0:1
+PROFILER_SO_VERSION=3:0:3
+
+
+
+
+# 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
+ for ac_t in install-sh install.sh shtool; do
+ if test -f "$ac_dir/$ac_t"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/$ac_t -c"
+ break 2
+ fi
+ done
+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 test "${ac_cv_build+set}" = set; 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 test "${ac_cv_host+set}" = set; 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.10'
+
+# 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 test "${ac_cv_path_install+set}" = set; 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# 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 (
+ 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
+ rm -f conftest.file
+ 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
+
+ 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; }
+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`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+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
+
+{ $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 test "${ac_cv_path_mkdir+set}" = set; 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
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+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 test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; 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
+
+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.0'
+
+
+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"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# 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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_config_headers="$ac_config_headers src/config.h"
+
+
+# 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]*\(.*\)$'`
+
+
+
+
+
+# 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
+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
+
+# 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
+
+
+# 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 test "${ac_cv_prog_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+
+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_set_status 77
+as_fn_error "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 <stdio.h>
+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 test "${ac_cv_objext+set}" = set; 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 test "${ac_cv_cxx_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cxx_g+set}" = set; 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
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# 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='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+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 test "${am_cv_CXX_dependencies_compiler_type+set}" = set; 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'.
+ 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
+ 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 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ 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
+ ;;
+ none) break ;;
+ esac
+ # 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.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} 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 sub/conftest.${OBJEXT-o} 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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_c_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cc_g+set}" = set; 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 test "${ac_cv_prog_cc_c89+set}" = set; 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 <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* 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
+
+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 test "${am_cv_CC_dependencies_compiler_type+set}" = set; 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'.
+ 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
+ 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 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ 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
+ ;;
+ none) break ;;
+ esac
+ # 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.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} 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 sub/conftest.${OBJEXT-o} 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 test "${ac_cv_prog_CPP+set}" = set; 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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.$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 <ac_nonexistent.h>
+_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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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.$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 <ac_nonexistent.h>
+_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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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
+if test "x$CC" != xcc; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
+$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
+else
+ { $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; }
+fi
+set dummy $CC; ac_cc=`$as_echo "$2" |
+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; 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.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { { 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; } &&
+ test -f conftest2.$ac_objext && { { 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
+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+ if test "x$CC" != xcc; then
+ # Test first that cc exists at all.
+ if { ac_try='cc -c conftest.$ac_ext >&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_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+ rm -f conftest2.*
+ if { { 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; } &&
+ test -f conftest2.$ac_objext && { { 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
+ # cc works too.
+ :
+ else
+ # cc exists but doesn't like -o.
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+ fi
+ fi
+ fi
+else
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f core conftest*
+
+fi
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; 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; }
+
+$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_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
+
+ # shrug: autogen.sh suddenly needs this for some reason
+
+# 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 test "${ac_cv_prog_OBJCOPY+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${gpt_cv_objcopy_weaken+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+void foo() {} 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 $host_os in
+ *mingw*)
+ # Disabling fast install keeps libtool from creating wrapper scripts
+ # around the executables it builds. Such scripts have caused failures on
+ # MinGW. Using this option means an extra link step is executed during
+ # "make install".
+ # 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=no
+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
+
+
+
+
+
+
+ ;;
+esac
+
+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.2.6b'
+macro_revision='1.3017'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+{ $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 test "${ac_cv_path_SED+set}" = set; 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"
+ { test -f "$ac_path_SED" && $as_test_x "$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 test "${ac_cv_path_GREP+set}" = set; 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"
+ { test -f "$ac_path_GREP" && $as_test_x "$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 test "${ac_cv_path_EGREP+set}" = set; 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"
+ { test -f "$ac_path_EGREP" && $as_test_x "$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 test "${ac_cv_path_FGREP+set}" = set; 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"
+ { test -f "$ac_path_FGREP" && $as_test_x "$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 "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 test "${lt_cv_path_LD+set}" = set; 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 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&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 test "${lt_cv_prog_gnu_ld+set}" = set; 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 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&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 test "${lt_cv_path_NM+set}" = set; 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
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ 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 "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+ 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 test "${ac_cv_prog_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 -symbols" "link -dump -symbols"
+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 test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+
+
+ 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 test "${lt_cv_nm_interface+set}" = set; 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:5631: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:5634: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:5637: 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 test "${lt_cv_sys_max_cmd_len+set}" = set; 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;
+ ;;
+
+ 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;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # 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
+ ;;
+
+ 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"; 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"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+ = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 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"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+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 for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; 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
+ darwin*)
+ if test "$GCC" = yes; 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 test "${ac_cv_prog_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_deplibs_check_method+set}" = set; 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
+# which 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
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ 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
+ ;;
+
+gnu*)
+ 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]) 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 Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-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*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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
+ ;;
+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_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}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $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
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $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
+
+ 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
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# 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 test "${lt_cv_sys_global_symbol_pipe+set}" = set; 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 "$host_cpu" = ia64; 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
+
+# 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/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
+ # and D for any global 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};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print 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
+
+ # 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
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && 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
+#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. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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_save_LIBS="$LIBS"
+ lt_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_save_LIBS"
+ CFLAGS="$lt_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 "$pipe_works" = yes; 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && 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 which ABI we are using.
+ 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 which ABI we are using.
+ echo '#line 6842 "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 "$lt_cv_prog_gnu_ld" = yes; 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*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ 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*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|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"
+ ;;
+ ppc*-*linux*|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 test "${lt_cv_cc_needs_belf+set}" = set; 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 x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ 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*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ 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"
+
+
+ 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 test "${ac_cv_prog_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_apple_cc_single_mod+set}" = set; 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 test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; 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 test "${lt_cv_ld_exported_symbols_list+set}" = set; 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; }
+ 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[91]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[012]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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" != ":"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ 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 test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+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 <string.h>
+
+_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 <stdlib.h>
+
+_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 <ctype.h>
+#include <stdlib.h>
+#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
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = 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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+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 test "${ac_cv_prog_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_cxx_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cxx_g+set}" = set; 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 test "${am_cv_CXX_dependencies_compiler_type+set}" = set; 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'.
+ 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
+ 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 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ 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
+ ;;
+ none) break ;;
+ esac
+ # 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.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} 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 sub/conftest.${OBJEXT-o} 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
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; 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 test "${ac_cv_prog_CXXCPP+set}" = set; 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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.$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 <ac_nonexistent.h>
+_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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> 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 <limits.h>
+#else
+# include <assert.h>
+#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.$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 <ac_nonexistent.h>
+_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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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;}
+_lt_caught_CXX_error=yes; }
+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
+
+
+
+
+
+# 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; pic_mode="$withval"
+else
+ pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+
+
+
+
+# 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 test "${lt_cv_objdir+set}" = set; 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 "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# 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.
+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'
+
+# 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
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+ { $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 test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; 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"
+ # 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:8714: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:8718: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; 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=
+
+{ $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 test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ 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'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ 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
+ 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 "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ 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'
+ ;;
+
+ 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)
+ 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'
+ ;;
+ # 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'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # 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*)
+ # IBM XL C 8.0/Fortran 10.1 on PPC
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ *Sun\ F*)
+ # 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=''
+ ;;
+ 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*)
+ 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 which 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}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# 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 test "${lt_cv_prog_compiler_pic_works+set}" = set; 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"
+ # 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:9053: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:9057: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 x"$lt_cv_prog_compiler_pic_works" = xyes; 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 test "${lt_cv_prog_compiler_static_works+set}" = set; 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 "X$_lt_linker_boilerplate" | $Xsed -e '/^$/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 x"$lt_cv_prog_compiler_static_works" = xyes; 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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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:9158: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:9162: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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:9213: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:9217: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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_flag_spec_ld=
+ 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 "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu)
+ link_all_deplibs=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; 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 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 "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, 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 modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_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 <jrb3@best.com> 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'
+ 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/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+ 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 (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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
+ ;;
+
+ 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no
+ then
+ tmp_addflag=
+ 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; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # 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; $ECHO \"$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' ;;
+ xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ 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; $ECHO \"$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 "x$supports_anon_versioning" = xyes; 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
+ xlf*)
+ # 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=
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; 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 $compiler_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 $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'
+ 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 $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
+ ;;
+
+ 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 can not
+*** 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 $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
+
+ if test "$ld_shlibs" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU 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")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ 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,'
+
+ if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ link_all_deplibs=no
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ 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_use_runtimelinking" = yes; 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.
+ 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
+ }
+ }'
+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 "$aix_libpath"; then
+ 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 "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; 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 "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; 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.
+ 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
+ }
+ }'
+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 "$aix_libpath"; then
+ 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 "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; 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'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ 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.
+ 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 `$ECHO "X$deplibs" | $Xsed -e '\''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'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ allow_undefined_flag="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ 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
+ ;;
+
+ freebsd1*)
+ ld_shlibs=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 -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${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 "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld='+b $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 "$GCC" = yes -a "$with_gnu_ld" = no; 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 -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${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'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; 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 "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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.
+ 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) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -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
+ ;;
+
+ 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*)
+ 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; 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" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "X-set_version $verstring" | $Xsed` -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 "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${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 ${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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; 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 "$ld_shlibs" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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; }
+ $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
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
+$as_echo "$archive_cmds_need_lc" >&6; }
+ ;;
+ 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 "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+ # 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 -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # 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`
+ 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"
+ else
+ 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; }
+}'`
+ sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+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
+ 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
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; 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
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.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}'
+ else
+ # 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'
+ fi
+ 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=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $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
+ 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,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ 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="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ 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
+ ;;
+ 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
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # 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
+ 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
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+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[123]*) 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} $libname${shared_ext}'
+ 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
+ ;;
+
+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
+ 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 "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ 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'
+ ;;
+
+interix[3-9]*)
+ 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'
+ 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 "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ 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
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-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'
+ 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
+ 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 :
+ 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
+
+ # 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
+
+ # Append ld.so.conf contents 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;/^$/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
+ 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*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ 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
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+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
+ 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 "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ 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
+ 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=freebsd-elf
+ 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 "$with_gnu_ld" = yes; 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
+ 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
+ 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 "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $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 "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct" != no &&
+ # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; 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 "$hardcode_action" = relink ||
+ test "$inherit_rpath" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test "x$enable_dlopen" != xyes; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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
+
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; 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 test "${ac_cv_lib_dld_shl_load+set}" = set; 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" = x""yes; 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" = x""yes; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_svld_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_dld_dld_link+set}" = set; 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" = x""yes; then :
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && 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 test "${lt_cv_dlopen_self+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; 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 11597 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#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
+
+void fnord() { int i=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;
+ /* 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 "x$lt_cv_dlopen_self" = xyes; 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 test "${lt_cv_dlopen_self_static+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; 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 11693 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#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
+
+void fnord() { int i=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;
+ /* 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 which 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ 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 "$enable_shared" = yes || 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"
+
+
+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_flag_spec_ld_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
+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 "$_lt_caught_CXX_error" != yes; 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_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++"}
+ compiler=$CC
+ compiler_CXX=$CC
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+ else
+ lt_prog_compiler_no_builtin_flag_CXX=
+ fi
+
+ if test "$GXX" = yes; 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 "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 test "${lt_cv_path_LD+set}" = set; 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 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&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 test "${lt_cv_prog_gnu_ld+set}" = set; 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 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&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 "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -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 "\-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 "$host_cpu" = ia64; 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
+ # need to do runtime linking.
+ 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
+ ;;
+ 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,'
+
+ if test "$GXX" = yes; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ 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_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ 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
+ }
+ }'
+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 "$aix_libpath"; then
+ 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 "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; 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 "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; 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.
+ 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
+ }
+ }'
+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 "$aix_libpath"; then
+ 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 "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; 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'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> 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*)
+ # _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'
+ 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 (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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
+ ;;
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+ allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ 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 "$lt_cv_apple_cc_single_mod" != "yes"; 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
+
+ ;;
+
+ 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
+ ;;
+
+ freebsd[12]*)
+ # 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
+ ;;
+
+ gnu*)
+ ;;
+
+ 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 $output_objdir/$soname = $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; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; 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; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; 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 -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -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)
+ 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; $ECHO "X$list" | $Xsed'
+
+ 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 | $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 | $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 | $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 | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 will 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; $ECHO \"$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=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ xl*)
+ # 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 "x$supports_anon_versioning" = xyes; 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; $ECHO \"$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='echo'
+
+ # 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
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+
+ openbsd*)
+ 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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=echo
+ 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" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "X-set_version $verstring" | $Xsed` -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=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; 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" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${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 "\-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*)
+ # 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='echo'
+
+ # 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 "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $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 -nostdlib ${wl}-M $wl$lib.exp -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 "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $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 -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 "\-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 can NOT 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'
+ ;;
+ *)
+ 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 "$ld_shlibs_CXX" = no && 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
+
+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 $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p 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
+ ;;
+
+ *.$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 "$pre_test_object_deps_done" = no; 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
+
+# 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=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+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=
+
+{ $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; }
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; 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 "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+
+ 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'
+ ;;
+ 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=
+ ;;
+ 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 "$host_cpu" = ia64; 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
+ ;;
+ 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 "$host_cpu" != ia64; 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)
+ 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*)
+ # IBM XL 8.0 on PPC
+ 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*)
+ # 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 which 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}: result: $lt_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
+
+
+
+#
+# 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 test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; 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"
+ # 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:13649: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:13653: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; 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 test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; 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 "X$_lt_linker_boilerplate" | $Xsed -e '/^$/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 x"$lt_cv_prog_compiler_static_works_CXX" = xyes; 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 test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; 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:13748: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:13752: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; 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:13800: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:13804: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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'
+ 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 AIX nm, but means don't demangle with GNU 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")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ linux* | k*bsd*-gnu)
+ link_all_deplibs_CXX=no
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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; }
+ $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
+ archive_cmds_need_lc_CXX=no
+ else
+ 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*
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_CXX" >&5
+$as_echo "$archive_cmds_need_lc_CXX" >&6; }
+ ;;
+ 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
+ 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
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; 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
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.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}'
+ else
+ # 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'
+ fi
+ 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=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $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
+ 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,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ 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="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ 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
+ ;;
+ 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
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # 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
+ 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
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+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[123]*) 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} $libname${shared_ext}'
+ 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
+ ;;
+
+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
+ 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 "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ 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'
+ ;;
+
+interix[3-9]*)
+ 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'
+ 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 "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ 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
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-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'
+ 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
+ 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 :
+ 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
+
+ # 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
+
+ # Append ld.so.conf contents 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;/^$/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
+ 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*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ 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
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+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
+ 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 "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ 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
+ 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=freebsd-elf
+ 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 "$with_gnu_ld" = yes; 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
+ 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
+ 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 "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $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 "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; 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 "$hardcode_action_CXX" = relink ||
+ test "$inherit_rpath_CXX" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ 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 "$_lt_caught_CXX_error" != yes
+
+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:
+
+
+
+ if test "x$LIBTOOL" != "x"; then
+ USE_LIBTOOL_TRUE=
+ USE_LIBTOOL_FALSE='#'
+else
+ USE_LIBTOOL_TRUE='#'
+ USE_LIBTOOL_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if test "${ac_cv_c_inline+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5
+$as_echo_n "checking for __attribute__... " >&6; }
+ if test "${ac_cv___attribute__+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+ 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; }
+
+
+# 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 test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+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 <string.h>
+
+_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 <stdlib.h>
+
+_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 <ctype.h>
+#include <stdlib.h>
+#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" "__int64" "ac_cv_type___int64" "$ac_includes_default"
+if test "x$ac_cv_type___int64" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE___INT64 1
+_ACEOF
+
+
+fi
+ # defined in some windows platforms
+ac_fn_c_check_type "$LINENO" "struct mallinfo" "ac_cv_type_struct_mallinfo" "#include <malloc.h>
+"
+if test "x$ac_cv_type_struct_mallinfo" = x""yes; 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 <elf.h>
+"
+if test "x$ac_cv_type_Elf32_Versym" = x""yes; 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" = x""yes; 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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETEUID 1
+_ACEOF
+
+fi
+done
+ # for turning off services when run as root
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_FEATURES_H 1
+_ACEOF
+
+fi
+
+done
+ # for vdso_support.h
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+ # some systems define stuff there, others not
+for ac_header in sys/malloc.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/malloc.h" "ac_cv_header_sys_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_malloc_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+ # where some versions of OS X put malloc.h
+for ac_header in malloc/malloc.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "malloc/malloc.h" "ac_cv_header_malloc_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_malloc_malloc_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_MALLOC_MALLOC_H 1
+_ACEOF
+
+fi
+
+done
+ # another place OS X puts malloc.h (?)
+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" = x""yes; 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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EXECINFO_H 1
+_ACEOF
+
+fi
+
+done
+ # for stacktrace? and heapchecker_unittest
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUNWIND_H 1
+_ACEOF
+
+fi
+
+done
+ # for stacktrace
+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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; 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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_RESOURCE_H 1
+_ACEOF
+
+fi
+
+done
+ # for memalign_unittest.cc
+for ac_header in valgrind.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default"
+if test "x$ac_cv_header_valgrind_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VALGRIND_H 1
+_ACEOF
+
+fi
+
+done
+ # we have a local copy if this isn't found
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_CDEFS_H 1
+_ACEOF
+
+fi
+
+done
+ # Where glibc defines __THROW
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_FEATURES_H 1
+_ACEOF
+
+fi
+
+done
+ # Where __GLIBC__ is defined
+# We also need <ucontext.h>/<sys/ucontext.h>, 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 <stdlib.h>
+ #include <malloc.h>
+"
+if test "x$ac_cv_have_decl_cfree" = x""yes; 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 <stdlib.h>
+ #include <malloc.h>
+"
+if test "x$ac_cv_have_decl_posix_memalign" = x""yes; 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 <stdlib.h>
+ #include <malloc.h>
+"
+if test "x$ac_cv_have_decl_memalign" = x""yes; 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 <stdlib.h>
+ #include <malloc.h>
+"
+if test "x$ac_cv_have_decl_valloc" = x""yes; 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 <stdlib.h>
+ #include <malloc.h>
+"
+if test "x$ac_cv_have_decl_pvalloc" = x""yes; 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 need to check for mmap. cygwin supports mmap, but the autoconf
+# test doesn't work on cygwin:
+# http://www.cygwin.com/ml/cygwin/2002-04/msg00412.html
+# This workaround comes from
+# http://cygwin.com/ml/cygwin/2004-11/msg00138.html
+case "$host" in
+ *-*-cygwin*)
+ ac_cv_func_mmap_fixed_mapped=yes
+
+$as_echo "#define HAVE_MMAP 1" >>confdefs.h
+
+ ;;
+ *)
+
+
+ for ac_header in $ac_header_list
+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
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+for ac_func in getpagesize
+do :
+ ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
+if test "x$ac_cv_func_getpagesize" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETPAGESIZE 1
+_ACEOF
+
+fi
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5
+$as_echo_n "checking for working mmap... " >&6; }
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the file system buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propagated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+ char *data, *data2, *data3;
+ const char *cdata2;
+ int i, pagesize;
+ int fd, fd2;
+
+ pagesize = getpagesize ();
+
+ /* First, make a file with some known garbage in it. */
+ data = (char *) malloc (pagesize);
+ if (!data)
+ return 1;
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand ();
+ umask (0);
+ fd = creat ("conftest.mmap", 0600);
+ if (fd < 0)
+ return 2;
+ if (write (fd, data, pagesize) != pagesize)
+ return 3;
+ close (fd);
+
+ /* Next, check that the tail of a page is zero-filled. File must have
+ non-zero length, otherwise we risk SIGBUS for entire page. */
+ fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600);
+ if (fd2 < 0)
+ return 4;
+ cdata2 = "";
+ if (write (fd2, cdata2, 1) != 1)
+ return 5;
+ data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L);
+ if (data2 == MAP_FAILED)
+ return 6;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data2 + i))
+ return 7;
+ close (fd2);
+ if (munmap (data2, pagesize))
+ return 8;
+
+ /* Next, try to mmap the file at a fixed address which already has
+ something else allocated at it. If we can, also make sure that
+ we see the same garbage. */
+ fd = open ("conftest.mmap", O_RDWR);
+ if (fd < 0)
+ return 9;
+ if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ return 10;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ return 11;
+
+ /* Finally, make sure that changes to the mapped area do not
+ percolate back to the file as seen by read(). (This is a bug on
+ some variants of i386 svr4.0.) */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = (char *) malloc (pagesize);
+ if (!data3)
+ return 12;
+ if (read (fd, data3, pagesize) != pagesize)
+ return 13;
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ return 14;
+ close (fd);
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ ac_cv_func_mmap_fixed_mapped=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
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5
+$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; }
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+$as_echo "#define HAVE_MMAP 1" >>confdefs.h
+
+fi
+rm -f conftest.mmap conftest.txt
+
+ ;;
+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 <stdint.h>
+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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_UCONTEXT_H 1
+_ACEOF
+
+fi
+
+done
+
+ # Redhat 7 has <sys/ucontext.h>, but it barfs if we #include it directly
+ # (this was fixed in later redhats). <ucontext.h> 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" = x""yes; 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" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_CYGWIN_SIGNAL_H 1
+_ACEOF
+
+fi
+
+done
+ # ucontext on cywgin
+ { $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.uc_regs->gregs[PT_NIP]" # Linux (ppc)
+ 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.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_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_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 <cygwin/signal.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
+ 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 <sys/ucontext.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
+ 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 <ucontext.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
+ 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 <signal.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
+ 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 exists
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for backtrace in -lunwind" >&5
+$as_echo_n "checking for backtrace in -lunwind... " >&6; }
+if test "${ac_cv_lib_unwind_backtrace+set}" = set; 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" = x""yes; then :
+ UNWIND_LIBS=-lunwind
+else
+ UNWIND_LIBS=
+fi
+
+
+
+# On x86_64, instead of libunwind, we can choose to compile with frame-pointers
+# (This isn't needed on i386, where -fno-omit-frame-pointer is the default).
+# 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
+
+
+# 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 want to see if the current system is one of those.
+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
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -S -O2 -o fp.s"
+# This test will always fail because we don't name our output file properly.
+# We do our own determination of success/failure in the grep, below.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int f(int x) {return x;}
+int
+main ()
+{
+return f(0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ :
+else
+ :
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1; then
+ X86_64_AND_NO_FP_BY_DEFAULT_TRUE=
+ X86_64_AND_NO_FP_BY_DEFAULT_FALSE='#'
+else
+ X86_64_AND_NO_FP_BY_DEFAULT_TRUE='#'
+ X86_64_AND_NO_FP_BY_DEFAULT_FALSE=
+fi
+
+rm fp.s
+CFLAGS="$OLD_CFLAGS"
+
+# 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 test "${perftools_cv_w_no_unused_result+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ OLD_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wno-error -Wno-unused-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!)
+ 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
+
+
+# Defines PRIuS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking printf format code for printing a size_t and ssize_t" >&5
+$as_echo_n "checking printf format code for printing a size_t and ssize_t... " >&6; }
+if test "${ac_cv_formatting_prius_prefix+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stddef.h>
+int
+main ()
+{
+unsigned int v1 = 0; size_t v2 = 0; return (&v1 - &v2)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_formatting_prius_prefix=; ac_cv_prius_defined=1
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stddef.h>
+int
+main ()
+{
+unsigned long v1 = 0; size_t v2 = 0; return (&v1 - &v2)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_formatting_prius_prefix=l; ac_cv_prius_defined=1
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stddef.h>
+int
+main ()
+{
+unsigned long long v1 = 0; size_t v2 = 0; return (&v1 - &v2)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_formatting_prius_prefix=ll; ac_cv_prius_defined=1
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_formatting_prius_prefix" >&5
+$as_echo "$ac_cv_formatting_prius_prefix" >&6; }
+ if test -z "$ac_cv_prius_defined"; then
+ ac_cv_formatting_prius_prefix=z;
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define PRIuS "${ac_cv_formatting_prius_prefix}u"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PRIxS "${ac_cv_formatting_prius_prefix}x"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PRIdS "${ac_cv_formatting_prius_prefix}d"
+_ACEOF
+
+
+
+# Also make sure we get standard PRI... definitions, even with glibc.
+# We have to use AH_VERBATIM because we need the #ifdef guard (gcc buglet)
+
+
+# Check if __builtin_stack_pointer() is available (for elfcore.h)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_stack_pointer()" >&5
+$as_echo_n "checking for __builtin_stack_pointer()... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+void *sp = __builtin_stack_pointer()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_BUILTIN_STACK_POINTER 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
+
+# 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 <unistd.h>
+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
+{ $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__) && (defined(__i386__) || defined(__x86_64__)) && ((__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
+#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
+
+# glibc's __malloc_hook/etc were declared volatile starting in glibc 2.14
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if __malloc_hook is declared volatile" >&5
+$as_echo_n "checking if __malloc_hook is declared volatile... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <malloc.h>
+void* (* volatile __malloc_hook)(size_t, const void*) = 0;
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define MALLOC_HOOK_MAYBE_VOLATILE volatile" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ $as_echo "#define MALLOC_HOOK_MAYBE_VOLATILE /**/" >>confdefs.h
+
+ { $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
+
+# 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 <time.h>
+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 <time.h>
+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
+
+
+# We also need to check if the kernel supports __thread, which requires uname()
+ac_fn_c_check_decl "$LINENO" "uname" "ac_cv_have_decl_uname" "#include <sys/utsname.h>
+"
+if test "x$ac_cv_have_decl_uname" = x""yes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_UNAME $ac_have_decl
+_ACEOF
+
+
+# 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 test "${ac_cv_prog_acx_pthread_config+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 <pthread.h>
+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 <pthread.h>
+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 test "${ac_cv_prog_PTHREAD_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 <pthread.h>
+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 <pthread.h>
+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 <pthread.h>
+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 <pthread.h>
+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 <pthread.h>
+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
+
+
+
+# Find out what namespace 'normal' STL code lives in
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler implements namespaces" >&5
+$as_echo_n "checking whether the compiler implements namespaces... " >&6; }
+if test "${ac_cv_cxx_namespaces+set}" = set; 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. */
+namespace Outer {
+ namespace Inner { int i = 0; }}
+int
+main ()
+{
+using namespace Outer::Inner; return i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_cxx_namespaces=yes
+else
+ ac_cv_cxx_namespaces=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: $ac_cv_cxx_namespaces" >&5
+$as_echo "$ac_cv_cxx_namespaces" >&6; }
+ if test "$ac_cv_cxx_namespaces" = yes; then
+
+$as_echo "#define HAVE_NAMESPACES 1" >>confdefs.h
+
+ fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what namespace STL code is in" >&5
+$as_echo_n "checking what namespace STL code is in... " >&6; }
+if test "${ac_cv_cxx_stl_namespace+set}" = set; 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 <vector>
+int
+main ()
+{
+vector<int> t; return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_cxx_stl_namespace=none
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <vector>
+int
+main ()
+{
+std::vector<int> t; return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_cxx_stl_namespace=std
+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: $ac_cv_cxx_stl_namespace" >&5
+$as_echo "$ac_cv_cxx_stl_namespace" >&6; }
+ if test "$ac_cv_cxx_stl_namespace" = none; then
+
+$as_echo "#define STL_NAMESPACE /**/" >>confdefs.h
+
+ fi
+ if test "$ac_cv_cxx_stl_namespace" = std; then
+
+$as_echo "#define STL_NAMESPACE std" >>confdefs.h
+
+ 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 test "${ac_cv_have_program_invocation_name+set}" = set; 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
+
+
+
+# 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
+
+
+# Redhat 7 (and below?) has sys/ucontext.h, but if you try to #include
+# it directly, the compiler gets upset. So we pretend we don't have
+# it.
+if cat /etc/redhat-release 2>/dev/null | grep "Red Hat Linux release 7" >/dev/null 2>&1; then
+
+$as_echo "#define HAVE_SYS_UCONTEXT_H 0" >>confdefs.h
+
+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
+
+
+# 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
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ 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=
+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
+
+
+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__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 "${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 "${USE_LIBTOOL_TRUE}" && test -z "${USE_LIBTOOL_FALSE}"; then
+ as_fn_error "conditional \"USE_LIBTOOL\" 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 "${X86_64_AND_NO_FP_BY_DEFAULT_TRUE}" && test -z "${X86_64_AND_NO_FP_BY_DEFAULT_FALSE}"; then
+ as_fn_error "conditional \"X86_64_AND_NO_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 "${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.
+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 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=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&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 -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+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
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# 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.0, which was
+generated by GNU Autoconf 2.65. 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 <google-perftools@googlegroups.com>."
+
+_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.0
+configured by $0, generated by GNU Autoconf 2.65,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2009 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=$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"` ;;
+ 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" ac_aux_dir="$ac_aux_dir"
+
+
+# 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'
+enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
+macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
+enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
+host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
+host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
+host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
+build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
+build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
+build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
+SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
+Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
+GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
+EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
+FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
+LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
+NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
+LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
+exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
+AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
+GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
+SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
+ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
+need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
+LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
+libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
+version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
+striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_dirs='`$ECHO "X$compiler_lib_search_dirs" | $Xsed -e "$delay_single_quote_subst"`'
+predep_objects='`$ECHO "X$predep_objects" | $Xsed -e "$delay_single_quote_subst"`'
+postdep_objects='`$ECHO "X$postdep_objects" | $Xsed -e "$delay_single_quote_subst"`'
+predeps='`$ECHO "X$predeps" | $Xsed -e "$delay_single_quote_subst"`'
+postdeps='`$ECHO "X$postdeps" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_path='`$ECHO "X$compiler_lib_search_path" | $Xsed -e "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "X$LD_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "X$old_archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "X$compiler_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "X$GCC_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "X$lt_prog_compiler_no_builtin_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "X$lt_prog_compiler_wl_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "X$lt_prog_compiler_pic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "X$lt_prog_compiler_static_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "X$lt_cv_prog_compiler_c_o_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "X$archive_cmds_need_lc_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "X$enable_shared_with_static_runtimes_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "X$export_dynamic_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "X$whole_archive_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "X$compiler_needs_object_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "X$old_archive_from_new_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "X$old_archive_from_expsyms_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "X$archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "X$archive_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "X$module_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "X$module_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "X$with_gnu_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "X$allow_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "X$no_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "X$hardcode_libdir_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_CXX='`$ECHO "X$hardcode_libdir_flag_spec_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "X$hardcode_libdir_separator_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "X$hardcode_direct_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "X$hardcode_direct_absolute_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "X$hardcode_minus_L_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "X$hardcode_shlibpath_var_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "X$hardcode_automatic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "X$inherit_rpath_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "X$link_all_deplibs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path_CXX='`$ECHO "X$fix_srcfile_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "X$always_export_symbols_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "X$export_symbols_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "X$exclude_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "X$include_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "X$prelink_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "X$file_list_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "X$hardcode_action_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "X$compiler_lib_search_dirs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "X$predep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "X$postdep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "X$predeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "X$postdeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "X$compiler_lib_search_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+SHELL \
+ECHO \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+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_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+finish_eval \
+old_striplib \
+striplib \
+compiler_lib_search_dirs \
+predep_objects \
+postdep_objects \
+predeps \
+postdeps \
+compiler_lib_search_path \
+LD_CXX \
+compiler_CXX \
+lt_prog_compiler_no_builtin_flag_CXX \
+lt_prog_compiler_wl_CXX \
+lt_prog_compiler_pic_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_flag_spec_ld_CXX \
+hardcode_libdir_separator_CXX \
+fix_srcfile_path_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 "X\\\\\$\$var"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ 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 \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec \
+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; do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
+ ;;
+esac
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which 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'
+ TIMESTAMP='$TIMESTAMP'
+ 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=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$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 -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# 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 2>/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 {' >"$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 >>"\$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
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$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 < "$tmp/subs1.awk" > "$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 $(srcdir),
+# ${srcdir} and @srcdir@ 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[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+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 >"$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_t=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_t"; 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
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$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="$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 "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 >"$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 "$tmp/subs.awk" >$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' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$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 "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$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 "$tmp/defines.awk"' "$ac_file_inputs"
+ } >"$tmp/config.h" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$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 "$tmp/config.h" "$ac_file" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$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"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options which 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
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# 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 GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags="CXX "
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# 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
+
+# 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
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# 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
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# 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
+
+# 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 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 of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that does not interpret backslashes.
+ECHO=$lt_ECHO
+
+# 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
+
+# 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
+
+# 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
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# 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
+
+# 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
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# 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
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# 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
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# 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
+
+# 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
+
+ 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 "X${COLLECT_NAMES+set}" != Xset; 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 '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# 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"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname 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).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+
+# func_stripname 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).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1+=\$2"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+ ;;
+ esac
+
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$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
+
+# 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
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_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
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_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
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path_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
+
+# 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 $?
+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
+
diff --git a/chromium/third_party/tcmalloc/vendor/configure.ac b/chromium/third_party/tcmalloc/vendor/configure.ac
new file mode 100644
index 00000000000..4bd5460f9d9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/configure.ac
@@ -0,0 +1,421 @@
+## 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.57)
+
+AC_INIT(gperftools, 2.0, google-perftools@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=5:0:1
+PROFILER_SO_VERSION=3:0:3
+
+AC_SUBST(TCMALLOC_SO_VERSION)
+AC_SUBST(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])
+AM_CONFIG_HEADER(src/config.h)
+
+# 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)
+
+# 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
+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
+
+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
+
+
+# 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
+
+# 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([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)
+
+case $host_os in
+ *mingw*)
+ # Disabling fast install keeps libtool from creating wrapper scripts
+ # around the executables it builds. Such scripts have caused failures on
+ # MinGW. Using this option means an extra link step is executed during
+ # "make install".
+ AC_DISABLE_FAST_INSTALL
+ ;;
+ *)
+ AC_ENABLE_FAST_INSTALL
+ ;;
+esac
+
+AC_PROG_LIBTOOL
+AC_SUBST(LIBTOOL_DEPS)
+AM_CONDITIONAL(USE_LIBTOOL, test "x$LIBTOOL" != "x")
+
+AC_C_INLINE
+AX_C___ATTRIBUTE__
+
+# 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([__int64]) # defined in some windows platforms
+AC_CHECK_TYPES([struct mallinfo],,, [#include <malloc.h>])
+AC_CHECK_TYPES([Elf32_Versym],,, [#include <elf.h>]) # for vdso_support.h
+AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory
+AC_CHECK_FUNCS(geteuid) # for turning off services when run as root
+AC_CHECK_HEADERS(features.h) # for vdso_support.h
+AC_CHECK_HEADERS(malloc.h) # some systems define stuff there, others not
+AC_CHECK_HEADERS(sys/malloc.h) # where some versions of OS X put malloc.h
+AC_CHECK_HEADERS(malloc/malloc.h) # another place OS X puts malloc.h (?)
+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(libunwind.h) # for stacktrace
+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(valgrind.h) # we have a local copy if this isn't found
+AC_CHECK_HEADERS(sys/cdefs.h) # Where glibc defines __THROW
+AC_CHECK_HEADERS(features.h) # Where __GLIBC__ is defined
+# We also need <ucontext.h>/<sys/ucontext.h>, 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 <stdlib.h>
+ #include <malloc.h>])
+
+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 need to check for mmap. cygwin supports mmap, but the autoconf
+# test doesn't work on cygwin:
+# http://www.cygwin.com/ml/cygwin/2002-04/msg00412.html
+# This workaround comes from
+# http://cygwin.com/ml/cygwin/2004-11/msg00138.html
+case "$host" in
+ *-*-cygwin*)
+ ac_cv_func_mmap_fixed_mapped=yes
+ AC_DEFINE(HAVE_MMAP, 1,
+ [Define to 1 if you have a working `mmap' system call.])
+ ;;
+ *) AC_FUNC_MMAP
+ ;;
+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_TRY_COMPILE([#include <stdint.h>],
+ [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 exists
+AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind, UNWIND_LIBS=)
+AC_SUBST(UNWIND_LIBS)
+
+# On x86_64, instead of libunwind, we can choose to compile with frame-pointers
+# (This isn't needed on i386, where -fno-omit-frame-pointer is the default).
+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)
+
+# 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 want to see if the current system is one of those.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [return __x86_64__ == 1 ? 0 : 1])],
+ [is_x86_64=yes], [is_x86_64=no])
+OLD_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -S -O2 -o fp.s"
+# This test will always fail because we don't name our output file properly.
+# We do our own determination of success/failure in the grep, below.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int f(int x) {return x;}], [return f(0);])],
+ [:], [:])
+AM_CONDITIONAL(X86_64_AND_NO_FP_BY_DEFAULT,
+ test "$is_x86_64" = yes && ! grep 'mov.*rsp.*rbp' fp.s >/dev/null 2>&1)
+rm fp.s
+CFLAGS="$OLD_CFLAGS"
+
+# 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 -Wno-unused-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!)
+ 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)
+
+# Defines PRIuS
+AC_COMPILER_CHARACTERISTICS
+
+# Also make sure we get standard PRI... definitions, even with glibc.
+# We have to use AH_VERBATIM because we need the #ifdef guard (gcc buglet)
+AH_VERBATIM([__STDC_FORMAT_MACROS],
+ [/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif])
+
+# Check if __builtin_stack_pointer() is available (for elfcore.h)
+AC_MSG_CHECKING([for __builtin_stack_pointer()])
+AC_LINK_IFELSE([AC_LANG_PROGRAM(, [void *sp = __builtin_stack_pointer()])],
+ [AC_DEFINE(HAVE_BUILTIN_STACK_POINTER, 1,
+ Define to 1 if compiler supports __builtin_stack_pointer)
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])])
+
+# Check if __environ is available (for GetenvBeforeMain)
+AC_MSG_CHECKING([for __environ])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <unistd.h>],
+ [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
+AC_MSG_CHECKING([for __thread])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && ((__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
+#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])])
+
+# glibc's __malloc_hook/etc were declared volatile starting in glibc 2.14
+AC_MSG_CHECKING([if __malloc_hook is declared volatile])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <malloc.h>
+void* (* volatile __malloc_hook)(size_t, const void*) = 0;],)],
+ [AC_DEFINE(MALLOC_HOOK_MAYBE_VOLATILE, volatile,
+ Define to 'volatile' if __malloc_hook is declared volatile)
+ AC_MSG_RESULT([yes])],
+ [AC_DEFINE(MALLOC_HOOK_MAYBE_VOLATILE, )
+ 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)
+
+# We also need to check if the kernel supports __thread, which requires uname()
+AC_CHECK_DECLS(uname,,, [#include <sys/utsname.h>])
+
+# In fact, a lot of the code in this directory depends on pthreads
+ACX_PTHREAD
+
+# Find out what namespace 'normal' STL code lives in
+AC_CXX_STL_NAMESPACE
+
+# 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
+
+# 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)
+
+# Redhat 7 (and below?) has sys/ucontext.h, but if you try to #include
+# it directly, the compiler gets upset. So we pretend we don't have
+# it.
+if cat /etc/redhat-release 2>/dev/null | grep "Red Hat Linux release 7" >/dev/null 2>&1; then
+AC_DEFINE(HAVE_SYS_UCONTEXT_H, 0, [<sys/ucontext.h> is broken on redhat 7])
+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.
+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)
+
+# Write generated configuration file
+AC_CONFIG_FILES([Makefile
+ src/gperftools/tcmalloc.h src/windows/gperftools/tcmalloc.h])
+AC_OUTPUT
diff --git a/chromium/third_party/tcmalloc/vendor/depcomp b/chromium/third_party/tcmalloc/vendor/depcomp
new file mode 100644
index 00000000000..e5f9736c723
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/depcomp
@@ -0,0 +1,589 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2007-03-29.01
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# 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 <oliva@dcc.unicamp.br>.
+
+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 outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+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"
+
+# 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
+
+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 -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## 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).
+## - 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 -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## 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.
+ tr ' ' '
+' < "$tmpdepfile" |
+## 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.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -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 -eq 0; then :
+ else
+ 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 ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+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.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ 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 -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ 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.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ 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 -eq 0; then :
+ else
+ 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,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#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.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # 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.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#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 $1 != '--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:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ 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 $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ 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.
+ -*|$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"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ 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 $1 != '--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, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html b/chromium/third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html
new file mode 100644
index 00000000000..3f90e6bc78e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html
@@ -0,0 +1,264 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML>
+
+<HEAD>
+ <link rel="stylesheet" href="designstyle.css">
+ <title>Google CPU Profiler Binary Data File Format</title>
+</HEAD>
+
+<BODY>
+
+<h1>Google CPU Profiler Binary Data File Format</h1>
+
+<p align=right>
+ <i>Last modified
+ <script type=text/javascript>
+ var lm = new Date(document.lastModified);
+ document.write(lm.toDateString());
+ </script></i>
+</p>
+
+<p>This file documents the binary data file format produced by the
+Google CPU Profiler. For information about using the CPU Profiler,
+see <a href="cpuprofile.html">its user guide</a>.
+
+<p>The profiler source code, which generates files using this format, is at
+<code>src/profiler.cc</code></a>.
+
+
+<h2>CPU Profile Data File Structure</h2>
+
+<p>CPU profile data files each consist of four parts, in order:
+
+<ul>
+ <li> Binary header
+ <li> Binary profile records
+ <li> Binary trailer
+ <li> Text list of mapped objects
+</ul>
+
+<p>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).
+
+
+<h2>Binary Header</h2>
+
+<p>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.
+
+<p>
+<table summary="Header Format"
+ frame="box" rules="sides" cellpadding="5" width="50%">
+ <tr>
+ <th width="30%">slot</th>
+ <th width="70%">data</th>
+ </tr>
+
+ <tr>
+ <td>0</td>
+ <td>header count (0; must be 0)</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+ <td>header slots after this one (3; must be &gt;= 3)</td>
+ </tr>
+
+ <tr>
+ <td>2</td>
+ <td>format version (0; must be 0)</td>
+ </tr>
+
+ <tr>
+ <td>3</td>
+ <td>sampling period, in microseconds</td>
+ </tr>
+
+ <tr>
+ <td>4</td>
+ <td>padding (0)</td>
+ </tr>
+</table>
+
+<p>The headers currently generated for 32-bit and 64-bit little-endian
+(x86 and x86_64) profiles are shown below, for comparison.
+
+<p>
+<table summary="Header Example" frame="box" rules="sides" cellpadding="5">
+ <tr>
+ <th></th>
+ <th>hdr count</th>
+ <th>hdr words</th>
+ <th>version</th>
+ <th>sampling period</th>
+ <th>pad</th>
+ </tr>
+ <tr>
+ <td>32-bit or 64-bit (slots)</td>
+ <td>0</td>
+ <td>3</td>
+ <td>0</td>
+ <td>10000</td>
+ <td>0</td>
+ </tr>
+ <tr>
+ <td>32-bit (4-byte words in file)</td>
+ <td><tt>0x00000</tt></td>
+ <td><tt>0x00003</tt></td>
+ <td><tt>0x00000</tt></td>
+ <td><tt>0x02710</tt></td>
+ <td><tt>0x00000</tt></td>
+ </tr>
+ <tr>
+ <td>64-bit LE (4-byte words in file)</td>
+ <td><tt>0x00000&nbsp;0x00000</tt></td>
+ <td><tt>0x00003&nbsp;0x00000</tt></td>
+ <td><tt>0x00000&nbsp;0x00000</tt></td>
+ <td><tt>0x02710&nbsp;0x00000</tt></td>
+ <td><tt>0x00000&nbsp;0x00000</tt></td>
+ </tr>
+</table>
+
+<p>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.
+
+<p>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.
+
+
+<h2>Binary Profile Records</h2>
+
+<p>The binary profile record format is shown below.
+
+<p>
+<table summary="Profile Record Format"
+ frame="box" rules="sides" cellpadding="5" width="50%">
+ <tr>
+ <th width="30%">slot</th>
+ <th width="70%">data</th>
+ </tr>
+
+ <tr>
+ <td>0</td>
+ <td>sample count, must be &gt;= 1</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+ <td>number of call chain PCs (num_pcs), must be &gt;= 1</td>
+ </tr>
+
+ <tr>
+ <td>2 .. (num_pcs + 1)</td>
+ <td>call chain PCs, most-recently-called function first.
+ </tr>
+</table>
+
+<p>The total length of a given record is 2 + num_pcs.
+
+<p>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.
+
+<p><b>Note:</b> Some profile analysis tools terminate if they see
+<em>any</em> profile record with a call chain with its first entry
+having the address 0. (This is similar to the binary trailer.)
+
+<h3>Example</h3>
+
+This example shows the slots contained in a sample profile record.
+
+<p>
+<table summary="Profile Record Example"
+ frame="box" rules="sides" cellpadding="5">
+ <tr>
+ <td>5</td>
+ <td>3</td>
+ <td>0xa0000</td>
+ <td>0xc0000</td>
+ <td>0xe0000</td>
+ </tr>
+</table>
+
+<p>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.
+
+
+<h2>Binary Trailer</h2>
+
+<p>The binary trailer consists of three slots of data with fixed
+values, shown below.
+
+<p>
+<table summary="Trailer Format"
+ frame="box" rules="sides" cellpadding="5" width="50%">
+ <tr>
+ <th width="30%">slot</th>
+ <th width="70%">value</th>
+ </tr>
+
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+ <td>1</td>
+ </tr>
+
+ <tr>
+ <td>2</td>
+ <td>0</td>
+ </tr>
+</table>
+
+<p>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.
+
+
+<h2>Text List of Mapped Objects</h2>
+
+<p>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.
+
+<p>Each line is one of the following types:
+
+<ul>
+ <li>Build specifier, starting with "<tt>build=</tt>". For example:
+ <pre> build=/path/to/binary</pre>
+ Leading spaces on the line are ignored.
+
+ <li>Mapping line from ProcMapsIterator::FormatLine. For example:
+ <pre> 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so</pre>
+ The first address must start at the beginning of the line.
+</ul>
+
+<p>Unrecognized lines should be ignored by analysis tools.
+
+<p>When processing the paths see in mapping lines, occurrences of
+<tt>$build</tt> 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.
+
+<hr>
+<address>Chris Demetriou<br>
+<!-- Created: Mon Aug 27 12:18:26 PDT 2007 -->
+<!-- hhmts start -->
+Last modified: Mon Aug 27 12:18:26 PDT 2007 (cgd)
+<!-- hhmts end -->
+</address>
+</BODY>
+</HTML>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/cpuprofile.html b/chromium/third_party/tcmalloc/vendor/doc/cpuprofile.html
new file mode 100644
index 00000000000..769ec68f3d3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/cpuprofile.html
@@ -0,0 +1,521 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+
+<HEAD>
+ <link rel="stylesheet" href="designstyle.css">
+ <title>Gperftools CPU Profiler</title>
+</HEAD>
+
+<BODY>
+
+<p align=right>
+ <i>Last modified
+ <script type=text/javascript>
+ var lm = new Date(document.lastModified);
+ document.write(lm.toDateString());
+ </script></i>
+</p>
+
+<p>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.</p>
+
+<p>On the off-chance that you should need to understand it, the CPU
+profiler data file format is documented separately,
+<a href="cpuprofile-fileformat.html">here</a>.
+
+
+<H1>Linking in the Library</H1>
+
+<p>To install the CPU profiler into your executable, add
+<code>-lprofiler</code> to the link-time step for your executable.
+(It's also probably possible to add in the profiler at run-time using
+<code>LD_PRELOAD</code>, e.g.
+<code>% env LD_PRELOAD="/usr/lib/libprofiler.so" &lt;binary&gt;</code>,
+but this isn't necessarily recommended.)</p>
+
+<p>This does <i>not</i> turn on CPU profiling; it just inserts the
+code. For that reason, it's practical to just always link
+<code>-lprofiler</code> 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.)</p>
+
+
+<H1>Running the Code</H1>
+
+<p>There are several alternatives to actually turn on CPU profiling
+for a given run of an executable:</p>
+
+<ol>
+ <li> <p>Define the environment variable CPUPROFILE to the filename
+ to dump the profile to. For instance, if you had a version of
+ <code>/bin/ls</code> that had been linked against libprofiler,
+ you could run:</p>
+ <pre>% env CPUPROFILE=ls.prof /bin/ls</pre>
+
+ <li> <p>In your code, bracket the code you want profiled in calls to
+ <code>ProfilerStart()</code> and <code>ProfilerStop()</code>.
+ (These functions are declared in <code>&lt;gperftools/profiler.h&gt;</code>.)
+ <code>ProfilerStart()</code> will take
+ the profile-filename as an argument.</p>
+</ol>
+
+<p>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).</p>
+
+<p>For security reasons, CPU profiling will not write to a file -- and
+is thus not usable -- for setuid programs.</p>
+
+<p>See the include-file <code>gperftools/profiler.h</code> for
+advanced-use functions, including <code>ProfilerFlush()</code> and
+<code>ProfilerStartWithOptions()</code>.</p>
+
+
+<H2>Modifying Runtime Behavior</H2>
+
+<p>You can more finely control the behavior of the CPU profiler via
+environment variables.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>CPUPROFILE_FREQUENCY=<i>x</i></code></td>
+ <td>default: 100</td>
+ <td>
+ How many interrupts/second the cpu-profiler samples.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>CPUPROFILE_REALTIME=1</code></td>
+ <td>default: [not set]</td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+</table>
+
+
+<h1><a name="pprof">Analyzing the Output</a></h1>
+
+<p><code>pprof</code> 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 <code>-pg</code> output of <code>gcc</code>,
+and others show the data in the form of a dependency graph.</p>
+
+<p>pprof <b>requires</b> <code>perl5</code> to be installed to run.
+It also requires <code>dot</code> to be installed for any of the
+graphical output routines, and <code>gv</code> to be installed for
+<code>--gv</code> mode (described below).
+</p>
+
+<p>Here are some ways to call pprof. These are described in more
+detail below.</p>
+
+<pre>
+% 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
+</pre>
+
+
+<h3>Analyzing Text Output</h3>
+
+<p>Text mode has lines of output that look like this:</p>
+<pre>
+ 14 2.1% 17.2% 58 8.7% std::_Rb_tree::find
+</pre>
+
+<p>Here is how to interpret the columns:</p>
+<ol>
+ <li> Number of profiling samples in this function
+ <li> Percentage of profiling samples in this function
+ <li> Percentage of profiling samples in the functions printed so far
+ <li> Number of profiling samples in this function and its callees
+ <li> Percentage of profiling samples in this function and its callees
+ <li> Function name
+</ol>
+
+<h3>Analyzing Callgrind Output</h3>
+
+<p>Use <a href="http://kcachegrind.sourceforge.net">kcachegrind</a> to
+analyze your callgrind output:</p>
+<pre>
+% pprof --callgrind /bin/ls ls.prof > ls.callgrind
+% kcachegrind ls.callgrind
+</pre>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<h3>Node Information</h3>
+
+<p>In the various graphical modes of pprof, the output is a call graph
+annotated with timing information, like so:</p>
+
+<A HREF="pprof-test-big.gif">
+<center><table><tr><td>
+ <img src="pprof-test.gif">
+</td></tr></table></center>
+</A>
+
+<p>Each node represents a procedure. The directed edges indicate
+caller to callee relations. Each node is formatted as follows:</p>
+
+<center><pre>
+Class Name
+Method Name
+local (percentage)
+<b>of</b> cumulative (percentage)
+</pre></center>
+
+<p>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.</p>
+
+<p>For instance, the timing information for test_main_thread()
+indicates that 155 units (about 1.55 seconds) were spent executing the
+code in <code>test_main_thread()</code> and 200 units were spent while
+executing <code>test_main_thread()</code> and its callees such as
+<code>snprintf()</code>.</p>
+
+<p>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
+<code>main()</code>).</p>
+
+<h3>Edge Information</h3>
+
+<p>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
+<code>test_main_thread()</code> to <code>snprintf()</code> indicates
+that of the 200 samples in <code>test_main_thread()</code>, 37 are
+because of calls to <code>snprintf()</code>.</p>
+
+<p>Note that <code>test_main_thread()</code> has an edge to
+<code>vsnprintf()</code>, even though <code>test_main_thread()</code>
+doesn't call that function directly. This is because the code was
+compiled with <code>-O2</code>; the profile reflects the optimized
+control flow.</p>
+
+<h3>Meta Information</h3>
+
+<p>The top of the display should contain some meta information
+like:</p>
+<pre>
+ /tmp/profiler2_unittest
+ Total samples: 202
+ Focusing on: 202
+ Dropped nodes with &lt;= 1 abs(samples)
+ Dropped edges with &lt;= 0 samples
+</pre>
+
+<p>This section contains the name of the program, and the total
+samples collected during the profiling run. If the
+<code>--focus</code> option is on (see the <a href="#focus">Focus</a>
+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.</p>
+
+<h3><a name=focus>Focus and Ignore</a></h3>
+
+<p>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
+<code>vsnprintf()</code> libc call in <code>profiler2_unittest</code>
+as follows:</p>
+
+<pre>
+% pprof --gv --focus=vsnprintf /tmp/profiler2_unittest test.prof
+</pre>
+<A HREF="pprof-vsnprintf-big.gif">
+<center><table><tr><td>
+ <img src="pprof-vsnprintf.gif">
+</td></tr></table></center>
+</A>
+
+<p>Similarly, you can supply the <code>--ignore</code> option to
+ignore samples that match a specified regular expression. E.g., if
+you are interested in everything except calls to
+<code>snprintf()</code>, you can say:</p>
+<pre>
+% pprof --gv --ignore=snprintf /tmp/profiler2_unittest test.prof
+</pre>
+
+
+<h3>Interactive mode</a></h3>
+
+<p>By default -- if you don't specify any flags to the contrary --
+pprof runs in interactive mode. At the <code>(pprof)</code> prompt,
+you can run many of the commands described above. You can type
+<code>help</code> for a list of what commands are available in
+interactive mode.</p>
+
+<h3><a name=options>pprof Options</a></h3>
+
+For a complete list of pprof options, you can run <code>pprof
+--help</code>.
+
+<h4>Output Type</h4>
+
+<p>
+<center>
+<table frame=box rules=sides cellpadding=5 width=100%>
+<tr valign=top>
+ <td><code>--text</code></td>
+ <td>
+ Produces a textual listing. (Note: If you have an X display, and
+ <code>dot</code> and <code>gv</code> installed, you will probably
+ be happier with the <code>--gv</code> output.)
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--gv</code></td>
+ <td>
+ Generates annotated call-graph, converts to postscript, and
+ displays via gv (requres <code>dot</code> and <code>gv</code> be
+ installed).
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--dot</code></td>
+ <td>
+ Generates the annotated call-graph in dot format and
+ emits to stdout (requres <code>dot</code> be installed).
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--ps</code></td>
+ <td>
+ Generates the annotated call-graph in Postscript format and
+ emits to stdout (requres <code>dot</code> be installed).
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--pdf</code></td>
+ <td>
+ Generates the annotated call-graph in PDF format and emits to
+ stdout (requires <code>dot</code> and <code>ps2pdf</code> be
+ installed).
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--gif</code></td>
+ <td>
+ Generates the annotated call-graph in GIF format and
+ emits to stdout (requres <code>dot</code> be installed).
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--list=&lt;<i>regexp</i>&gt;</code></td>
+ <td>
+ <p>Outputs source-code listing of routines whose
+ name matches &lt;regexp&gt;. Each line
+ in the listing is annotated with flat and cumulative
+ sample counts.</p>
+
+ <p>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.</p>
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--disasm=&lt;<i>regexp</i>&gt;</code></td>
+ <td>
+ Generates disassembly of routines that match
+ &lt;regexp&gt;, annotated with flat and
+ cumulative sample counts and emits to stdout.
+ </td>
+</tr>
+</table>
+</center>
+
+<h4>Reporting Granularity</h4>
+
+<p>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 <code>--files</code> option seems to be particularly
+useless, and may be removed eventually.</p>
+
+<center>
+<table frame=box rules=sides cellpadding=5 width=100%>
+<tr valign=top>
+ <td><code>--addresses</code></td>
+ <td>
+ Produce one node per program address.
+ </td>
+</tr>
+ <td><code>--lines</code></td>
+ <td>
+ Produce one node per source line.
+ </td>
+</tr>
+ <td><code>--functions</code></td>
+ <td>
+ Produce one node per function (this is the default).
+ </td>
+</tr>
+ <td><code>--files</code></td>
+ <td>
+ Produce one node per source file.
+ </td>
+</tr>
+</table>
+</center>
+
+<h4>Controlling the Call Graph Display</h4>
+
+<p>Some nodes and edges are dropped to reduce clutter in the output
+display. The following options control this effect:</p>
+
+<center>
+<table frame=box rules=sides cellpadding=5 width=100%>
+<tr valign=top>
+ <td><code>--nodecount=&lt;n&gt;</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--nodefraction=&lt;f&gt;</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--edgefraction=&lt;f&gt;</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--focus=&lt;re&gt;</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+<tr valign=top>
+ <td><code>--ignore=&lt;re&gt;</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+</table>
+</center>
+
+<p>The dropped edges and nodes account for some count mismatches in
+the display. For example, the cumulative count for
+<code>snprintf()</code> 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.</p>
+
+
+<h1>Caveats</h1>
+
+<ul>
+ <li> If the program exits because of a signal, the generated profile
+ will be <font color=red>incomplete, and may perhaps be
+ completely empty</font>.
+ <li> The displayed graph may have disconnected regions because
+ of the edge-dropping heuristics described above.
+ <li> 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.
+ <li> 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.
+ <li> 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.
+ <li> 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 <code>./</code> to your filename:
+ <code>CPUPROFILE=./&Auml;gypten</code>.
+</ul>
+
+
+<hr>
+<address>Sanjay Ghemawat<br>
+<!-- Created: Tue Dec 19 10:43:14 PST 2000 -->
+<!-- hhmts start -->
+Last modified: Fri May 9 14:41:29 PDT 2008
+<!-- hhmts end -->
+</address>
+</BODY>
+</HTML>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/designstyle.css b/chromium/third_party/tcmalloc/vendor/doc/designstyle.css
new file mode 100644
index 00000000000..29299af1f49
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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 <code> tag for bits of code and <var> for variables and objects. */
+code,pre,samp,var {
+ color: #006000;
+}
+/* Use the <file> tag for file and directory paths and names. */
+file {
+ color: #905050;
+ font-family: monospace;
+}
+/* Use the <kbd> 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/chromium/third_party/tcmalloc/vendor/doc/heap-example1.png b/chromium/third_party/tcmalloc/vendor/doc/heap-example1.png
new file mode 100644
index 00000000000..9a14b6fb89e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/heap-example1.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/heap_checker.html b/chromium/third_party/tcmalloc/vendor/doc/heap_checker.html
new file mode 100644
index 00000000000..ea2ade63345
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/heap_checker.html
@@ -0,0 +1,534 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+
+<HEAD>
+ <link rel="stylesheet" href="designstyle.css">
+ <title>Gperftools Heap Leak Checker</title>
+</HEAD>
+
+<BODY>
+
+<p align=right>
+ <i>Last modified
+ <script type=text/javascript>
+ var lm = new Date(document.lastModified);
+ document.write(lm.toDateString());
+ </script></i>
+</p>
+
+<p>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.</p>
+
+
+<H1>Linking in the Library</H1>
+
+<p>The heap-checker is part of tcmalloc, so to install the heap
+checker into your executable, add <code>-ltcmalloc</code> 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 <code>LD_PRELOAD</code>:</p>
+<pre>% env LD_PRELOAD="/usr/lib/libtcmalloc.so" <binary></pre>
+
+<p>This does <i>not</i> turn on heap checking; it just inserts the
+code. For that reason, it's practical to just always link
+<code>-ltcmalloc</code> 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.</p>
+
+
+<h1>Running the Code</h1>
+
+<p>Note: For security reasons, heap profiling will not write to a file
+-- and is thus not usable -- for setuid programs.</p>
+
+<h2><a name="whole_program">Whole-program Heap Leak Checking</a></h2>
+
+<p>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 <code>main()</code>, 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 <code>exit(1)</code>) and prints a message
+describing how to track down the memory leak (using <A
+HREF="heapprofile.html#pprof">pprof</A>).</p>
+
+<p>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.</p>
+
+<p>Here's how to run a program with whole-program heap checking:</p>
+
+<ol>
+ <li> <p>Define the environment variable HEAPCHECK to the <A
+ HREF="#types">type of heap-checking</A> to do. For instance,
+ to heap-check
+ <code>/usr/local/bin/my_binary_compiled_with_tcmalloc</code>:</p>
+ <pre>% env HEAPCHECK=normal /usr/local/bin/my_binary_compiled_with_tcmalloc</pre>
+</ol>
+
+<p>No other action is required.</p>
+
+<p>Note that since the heap-checker uses the heap-profiling framework
+internally, it is not possible to run both the heap-checker and <A
+HREF="heapprofile.html">heap profiler</A> at the same time.</p>
+
+
+<h3><a name="types">Flavors of Heap Checking</a></h3>
+
+<p>These are the legal values when running a whole-program heap
+check:</p>
+<ol>
+ <li> <code>minimal</code>
+ <li> <code>normal</code>
+ <li> <code>strict</code>
+ <li> <code>draconian</code>
+</ol>
+
+<p>"Minimal" heap-checking starts as late as possible in a
+initialization, meaning you can leak some memory in your
+initialization routines (that run before <code>main()</code>, 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.</p>
+
+<p>"Normal" heap-checking tracks <A HREF="#live">live objects</A> and
+reports a leak for any data that is not reachable via a live object
+when the program exits.</p>
+
+<p>"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.</p>
+
+<p>"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
+<i>all</i> allocated memory is freed before program exit. (However,
+you can use <A HREF="#disable">IgnoreObject()</A> to re-enable
+liveness-checking on an object-by-object basis.)</p>
+
+<p>"Normal" mode, as the name implies, is the one used most often at
+Google. It's appropriate for everyday heap-checking use.</p>
+
+<p>In addition, there are two other possible modes:</p>
+<ul>
+ <li> <code>as-is</code>
+ <li> <code>local</code>
+</ul>
+<p><code>as-is</code> is the most flexible mode; it allows you to
+specify the various <A HREF="#options">knobs</A> of the heap checker
+explicitly. <code>local</code> activates the <A
+HREF="#explicit">explicit heap-check instrumentation</A>, but does not
+turn on any whole-program leak checking.</p>
+
+
+<h3><A NAME="tweaking">Tweaking whole-program checking</A></h3>
+
+<p>In some cases you want to check the whole program for memory leaks,
+but waiting for after <code>main()</code> 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
+<code>NoGlobalLeaks()</code>, to verify no global leaks have happened
+as of that point in the program.</p>
+
+<p>Alternately, doing the check after <code>main()</code> 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 <code>NoGlobalLeaks()</code> manually, near the end of
+<code>main()</code>, and then call <code>CancelGlobalCheck()</code> to
+turn off the automatic post-<code>main()</code> check.</p>
+
+<p>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 <code>REGISTER_HEAPCHECK_CLEANUP</code> (in
+<code>heap-checker.h</code>). This macro allows you to mark specific
+cleanup code as active only when the heap-checker is turned on.</p>
+
+
+<h2><a name="explicit">Explicit (Partial-program) Heap Leak Checking</h2>
+
+<p>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.</p>
+<p>To use this kind of checking code, bracket the code you want
+checked by creating a <code>HeapLeakChecker</code> object at the
+beginning of the code segment, and call
+<code>NoLeaks()</code> at the end. These functions, and all others
+referred to in this file, are declared in
+<code>&lt;gperftools/heap-checker.h&gt;</code>.
+</p>
+
+<p>Here's an example:</p>
+<pre>
+ 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");
+</pre>
+
+<p>Note that adding in the <code>HeapLeakChecker</code> 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:</p>
+<pre>% env HEAPCHECK=local /usr/local/bin/my_binary_compiled_with_tcmalloc</pre>
+<p>If you want to do whole-program leak checking in addition to this
+manual leak checking, you can run in <code>normal</code> or some other
+mode instead: they'll run the "local" checks in addition to the
+whole-program check.</p>
+
+
+<h2><a name="disable">Disabling Heap-checking of Known Leaks</a></h2>
+
+<p>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:</p>
+<pre>
+ ...
+ {
+ HeapLeakChecker::Disabler disabler;
+ &lt;leaky code&gt;
+ }
+ ...
+</pre>
+Any objects allocated by <code>leaky code</code> (including inside any
+routines called by <code>leaky code</code>) and any objects reachable
+from such objects are not reported as leaks.
+
+<p>Alternately, you can use <code>IgnoreObject()</code>, 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 <code>UnIgnoreObject()</code> to undo the
+effects of <code>IgnoreObject()</code>.</p>
+
+
+<h2><a name="options">Tuning the Heap Checker</h2>
+
+<p>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 <A HREF="#types">heap-check flavors</A> is enough, but in
+specialized cases more control can be helpful.</p>
+
+<p>
+These options are specified via environment varaiables.
+</p>
+
+<p>This first set of options controls sensitivity and accuracy. These
+options are ignored unless you run the heap checker in <A
+HREF="#types">as-is</A> mode.
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_AFTER_DESTRUCTORS</code></td>
+ <td>Default: false</td>
+ <td>
+ When true, do the final leak check after all other global
+ destructors have run. When false, do it after all
+ <code>REGISTER_HEAPCHECK_CLEANUP</code>, typically much earlier in
+ the global-destructor process.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_IGNORE_THREAD_LIVE</code></td>
+ <td>Default: true</td>
+ <td>
+ If true, ignore objects reachable from thread stacks and registers
+ (that is, do not report them as leaks).
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_IGNORE_GLOBAL_LIVE</code></td>
+ <td>Default: true</td>
+ <td>
+ If true, ignore objects reachable from global variables and data
+ (that is, do not report them as leaks).
+ </td>
+</tr>
+
+</table>
+
+<p>These options modify the behavior of whole-program leak
+checking.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_MAX_LEAKS</code></td>
+ <td>Default: 20</td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+
+</table>
+
+<p>These options apply to all types of leak checking.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_IDENTIFY_LEAKS</code></td>
+ <td>Default: false</td>
+ <td>
+ If true, generate the addresses of the leaked objects in the
+ generated memory leak profile files.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_TEST_POINTER_ALIGNMENT</code></td>
+ <td>Default: false</td>
+ <td>
+ If true, check all leaks to see if they might be due to the use
+ of unaligned pointers.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_POINTER_SOURCE_ALIGNMENT</code></td>
+ <td>Default: sizeof(void*)</td>
+ <td>
+ Alignment at which all pointers in memory are supposed to be located.
+ Use 1 if any alignment is ok.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>PPROF_PATH</code></td>
+ <td>Default: pprof</td>
+<td>
+ The location of the <code>pprof</code> executable.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_CHECK_DUMP_DIRECTORY</code></td>
+ <td>Default: /tmp</td>
+ <td>
+ Where the heap-profile files are kept while the program is running.
+ </td>
+</tr>
+
+</table>
+
+
+<h2>Tips for Handling Detected Leaks</h2>
+
+<p>What do you do when the heap leak checker detects a memory leak?
+First, you should run the reported <code>pprof</code> command;
+hopefully, that is enough to track down the location where the leak
+occurs.</p>
+
+<p>If the leak is a real leak, you should fix it!</p>
+
+<p>If you are sure that the reported leaks are not dangerous and there
+is no good way to fix them, then you can use
+<code>HeapLeakChecker::Disabler</code> and/or
+<code>HeapLeakChecker::IgnoreObject()</code> to disable heap-checking
+for certain parts of the codebase.</p>
+
+<p>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 <A
+HREF="#tweaking"><code>REGISTER_HEAPCHECK_CLEANUP</code></A>.</p>
+
+<h2>Hints for Debugging Detected Leaks</h2>
+
+<p>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.
+<br/>
+To get the addresses of all leaked objects
+ define the environment variable <code>HEAP_CHECK_IDENTIFY_LEAKS</code>
+ to be <code>1</code>.
+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.
+</p>
+
+<p>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.
+<br/>
+E.g. if the code of some <code>.cc</code> 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.
+<br/>
+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.
+</p>
+
+<p>
+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 <code>HEAP_CHECK_TEST_POINTER_ALIGNMENT</code>
+ to be <code>1</code>
+and then look closely at the generated leak report messages.
+</p>
+
+<h1>How It Works</h1>
+
+<p>When a <code>HeapLeakChecker</code> object is constructed, it dumps
+a memory-usage profile named
+<code>&lt;prefix&gt;.&lt;name&gt;-beg.heap</code> to a temporary
+directory. When <code>NoLeaks()</code>
+is called (for whole-program checking, this happens automatically at
+program-exit), it dumps another profile, named
+<code>&lt;prefix&gt;.&lt;name&gt;-end.heap</code>.
+(<code>&lt;prefix&gt;</code> is typically determined automatically,
+and <code>&lt;name&gt;</code> is typically <code>argv[0]</code>.) It
+then compares the two profiles. If the second profile shows
+more memory use than the first, the
+<code>NoLeaks()</code> function will
+return false. For "whole program" profiling, this will cause the
+executable to abort (via <code>exit(1)</code>). In all cases, it will
+print a message on how to process the dumped profiles to locate
+leaks.</p>
+
+<h3><A name=live>Detecting Live Objects</A></h3>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>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
+<code>malloc</code> is implemented, it may reuse a heap object
+address:</p>
+<pre>
+ 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
+</pre>
+
+<p>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
+<code>HeapLeakChecker</code> object was constructed. Note that for
+whole-program checks, a leak report <i>does</i> always correspond to a
+real leak (since there's no "before" to have created a false-live
+object).</p>
+
+<p>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.</p>
+
+
+<h3>Visualizing Leak with <code>pprof</code></h3>
+
+<p>
+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.
+</p>
+
+<h3>Leak-checking and Threads</h3>
+
+<p>At the time of HeapLeakChecker's construction and during
+<code>NoLeaks()</code> 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.</p>
+
+<p>In general, leak checking works correctly in the presence of
+threads. However, thread stack data liveness determination (via
+<code>base/thread_lister.h</code>) 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.</p>
+
+<p>Also, <code>thread_lister</code> only works for Linux pthreads;
+leak checking is unlikely to handle other thread implementations
+correctly.</p>
+
+<p>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:</p>
+<pre>
+ int* foo = new int [20];
+ HeapLeakChecker check("a_check");
+ foo = NULL;
+ // May fail to trigger.
+ if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak");
+</pre>
+
+
+<hr>
+<address>Maxim Lifantsev<br>
+<!-- Created: Tue Dec 19 10:43:14 PST 2000 -->
+<!-- hhmts start -->
+Last modified: Fri Jul 13 13:14:33 PDT 2007
+<!-- hhmts end -->
+</address>
+</body>
+</html>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/heapprofile.html b/chromium/third_party/tcmalloc/vendor/doc/heapprofile.html
new file mode 100644
index 00000000000..e9f6b15d10d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/heapprofile.html
@@ -0,0 +1,373 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+
+<HEAD>
+ <link rel="stylesheet" href="designstyle.css">
+ <title>Gperftools Heap Profiler</title>
+</HEAD>
+
+<BODY>
+
+<p align=right>
+ <i>Last modified
+ <script type=text/javascript>
+ var lm = new Date(document.lastModified);
+ document.write(lm.toDateString());
+ </script></i>
+</p>
+
+<p>This is the heap profiler we use at Google, to explore how C++
+programs manage memory. This facility can be useful for</p>
+<ul>
+ <li> Figuring out what is in the program heap at any given time
+ <li> Locating memory leaks
+ <li> Finding places that do a lot of allocation
+</ul>
+
+<p>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
+<code>malloc</code>, <code>calloc</code>, <code>realloc</code>, or,
+<code>new</code>.</p>
+
+<p>There are three parts to using it: linking the library into an
+application, running the code, and analyzing the output.</p>
+
+
+<h1>Linking in the Library</h1>
+
+<p>To install the heap profiler into your executable, add
+<code>-ltcmalloc</code> 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
+<code>LD_PRELOAD</code>:
+<pre>% env LD_PRELOAD="/usr/lib/libtcmalloc.so" &lt;binary&gt;</pre>
+
+<p>This does <i>not</i> turn on heap profiling; it just inserts the
+code. For that reason, it's practical to just always link
+<code>-ltcmalloc</code> 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.</p>
+
+
+<h1>Running the Code</h1>
+
+<p>There are several alternatives to actually turn on heap profiling
+for a given run of an executable:</p>
+
+<ol>
+ <li> <p>Define the environment variable HEAPPROFILE to the filename
+ to dump the profile to. For instance, to profile
+ <code>/usr/local/bin/my_binary_compiled_with_tcmalloc</code>:</p>
+ <pre>% env HEAPPROFILE=/tmp/mybin.hprof /usr/local/bin/my_binary_compiled_with_tcmalloc</pre>
+ <li> <p>In your code, bracket the code you want profiled in calls to
+ <code>HeapProfilerStart()</code> and <code>HeapProfilerStop()</code>.
+ (These functions are declared in <code>&lt;gperftools/heap-profiler.h&gt;</code>.)
+ <code>HeapProfilerStart()</code> will take the
+ profile-filename-prefix as an argument. Then, as often as
+ you'd like before calling <code>HeapProfilerStop()</code>, you
+ can use <code>HeapProfilerDump()</code> or
+ <code>GetHeapProfile()</code> to examine the profile. In case
+ it's useful, <code>IsHeapProfilerRunning()</code> will tell you
+ whether you've already called HeapProfilerStart() or not.</p>
+</ol>
+
+
+<p>For security reasons, heap profiling will not write to a file --
+and is thus not usable -- for setuid programs.</p>
+
+<H2>Modifying Runtime Behavior</H2>
+
+<p>You can more finely control the behavior of the heap profiler via
+environment variables.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>HEAP_PROFILE_ALLOCATION_INTERVAL</code></td>
+ <td>default: 1073741824 (1 Gb)</td>
+ <td>
+ Dump heap profiling information once every specified number of
+ bytes has been allocated by the program.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_PROFILE_INUSE_INTERVAL</code></td>
+ <td>default: 104857600 (100 Mb)</td>
+ <td>
+ Dump heap profiling information whenever the high-water memory
+ usage mark increases by the specified number of bytes.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_PROFILE_MMAP</code></td>
+ <td>default: false</td>
+ <td>
+ Profile <code>mmap</code>, <code>mremap</code> and <code>sbrk</code>
+ calls in addition
+ to <code>malloc</code>, <code>calloc</code>, <code>realloc</code>,
+ and <code>new</code>. <b>NOTE:</b> 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 <code>pprof</code>,
+ with something like
+ <code>pprof --ignore='DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc</code>.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_PROFILE_MMAP_ONLY</code></td>
+ <td>default: false</td>
+ <td>
+ Only profile <code>mmap</code>, <code>mremap</code>, and <code>sbrk</code>
+ calls; do not profile
+ <code>malloc</code>, <code>calloc</code>, <code>realloc</code>,
+ or <code>new</code>.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>HEAP_PROFILE_MMAP_LOG</code></td>
+ <td>default: false</td>
+ <td>
+ Log <code>mmap</code>/<code>munmap</code> calls.
+ </td>
+</tr>
+
+</table>
+
+<H2>Checking for Leaks</H2>
+
+<p>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 <A
+HREF="heap_checker.html">automatic heap-checking facility</A> built
+into tcmalloc.</p>
+
+
+<h1><a name="pprof">Analyzing the Output</a></h1>
+
+<p>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:</p>
+<pre>
+ &lt;prefix&gt;.0000.heap
+ &lt;prefix&gt;.0001.heap
+ &lt;prefix&gt;.0002.heap
+ ...
+</pre>
+<p>where <code>&lt;prefix&gt;</code> is the filename-prefix supplied
+when running the code (e.g. via the <code>HEAPPROFILE</code>
+environment variable). Note that if the supplied prefix
+does not start with a <code>/</code>, the profile files will be
+written to the program's working directory.</p>
+
+<p>The profile output can be viewed by passing it to the
+<code>pprof</code> tool -- the same tool that's used to analyze <A
+HREF="cpuprofile.html">CPU profiles</A>.
+
+<p>Here are some examples. These examples assume the binary is named
+<code>gfs_master</code>, and a sequence of heap profile files can be
+found in files named:</p>
+<pre>
+ /tmp/profile.0001.heap
+ /tmp/profile.0002.heap
+ ...
+ /tmp/profile.0100.heap
+</pre>
+
+<h3>Why is a process so big</h3>
+
+<pre>
+ % pprof --gv gfs_master /tmp/profile.0100.heap
+</pre>
+
+<p>This command will pop-up a <code>gv</code> window that displays
+the profile information as a directed graph. Here is a portion
+of the resulting output:</p>
+
+<p><center>
+<img src="heap-example1.png">
+</center></p>
+
+A few explanations:
+<ul>
+<li> <code>GFS_MasterChunk::AddServer</code> accounts for 255.6 MB
+ of the live memory, which is 25% of the total live memory.
+<li> <code>GFS_MasterChunkTable::UpdateState</code> 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.
+</ul>
+
+<h3>Comparing Profiles</h3>
+
+<p>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 <code>--base</code> option. For example:</p>
+<pre>
+ % pprof --base=/tmp/profile.0004.heap gfs_master /tmp/profile.0100.heap
+</pre>
+
+<p>The memory-usage in <code>/tmp/profile.0004.heap</code> will be
+subtracted from the memory-usage in
+<code>/tmp/profile.0100.heap</code> and the result will be
+displayed.</p>
+
+<h3>Text display</h3>
+
+<pre>
+% 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
+ ...
+</pre>
+
+<p>
+<ul>
+ <li> The first column contains the direct memory use in MB.
+ <li> The fourth column contains memory use by the procedure
+ and all of its callees.
+ <li> The second and fifth columns are just percentage
+ representations of the numbers in the first and fourth columns.
+ <li> The third column is a cumulative sum of the second column
+ (i.e., the <code>k</code>th entry in the third column is the
+ sum of the first <code>k</code> entries in the second column.)
+</ul>
+
+<h3>Ignoring or focusing on specific regions</h3>
+
+<p>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 <code>DataBuffer</code> are included:</p>
+<pre>
+% pprof --gv --focus=DataBuffer gfs_master /tmp/profile.0100.heap
+</pre>
+
+<p>Similarly, the following command will omit all paths subset of the
+call-graph. All paths in the call-graph that match the regular
+expression <code>DataBuffer</code> are discarded:</p>
+<pre>
+% pprof --gv --ignore=DataBuffer gfs_master /tmp/profile.0100.heap
+</pre>
+
+<h3>Total allocations + object-level information</h3>
+
+<p>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 <code>pprof</code>:</p>
+
+<center>
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>--inuse_space</code></td>
+ <td>
+ Display the number of in-use megabytes (i.e. space that has
+ been allocated but not freed). This is the default.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>--inuse_objects</code></td>
+ <td>
+ Display the number of in-use objects (i.e. number of
+ objects that have been allocated but not freed).
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>--alloc_space</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>--alloc_objects</code></td>
+ <td>
+ 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.
+ </td>
+
+</table>
+</center>
+
+
+<h3>Interactive mode</a></h3>
+
+<p>By default -- if you don't specify any flags to the contrary --
+pprof runs in interactive mode. At the <code>(pprof)</code> prompt,
+you can run many of the commands described above. You can type
+<code>help</code> for a list of what commands are available in
+interactive mode.</p>
+
+
+<h1>Caveats</h1>
+
+<ul>
+ <li> 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.
+
+ <li> 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 libary. This will artificially
+ inflate the count for that symbol.
+
+ <li> 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.
+
+ <li> 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.
+
+ <li> 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.
+
+ <li> 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 <code>./</code> to your filename:
+ <code>HEAPPROFILE=./&Auml;gypten</code>.
+</ul>
+
+<hr>
+<address>Sanjay Ghemawat
+<!-- Created: Tue Dec 19 10:43:14 PST 2000 -->
+</address>
+</body>
+</html>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/index.html b/chromium/third_party/tcmalloc/vendor/doc/index.html
new file mode 100644
index 00000000000..7b93ed3965c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/index.html
@@ -0,0 +1,20 @@
+<HTML>
+
+<HEAD>
+<title>Gperftools</title>
+</HEAD>
+
+<BODY>
+<ul>
+ <li> <A HREF="tcmalloc.html">thread-caching malloc</A>
+ <li> <A HREF="heap_checker.html">heap-checking using tcmalloc</A>
+ <li> <A HREF="heapprofile.html">heap-profiling using tcmalloc</A>
+ <li> <A HREF="cpuprofile.html">CPU profiler</A>
+</ul>
+
+<hr>
+Last modified: Thu Feb 2 14:40:47 PST 2012
+
+</BODY>
+
+</HTML>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/overview.dot b/chromium/third_party/tcmalloc/vendor/doc/overview.dot
new file mode 100644
index 00000000000..9966f56cfc8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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/chromium/third_party/tcmalloc/vendor/doc/overview.gif b/chromium/third_party/tcmalloc/vendor/doc/overview.gif
new file mode 100644
index 00000000000..43828dadec8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/overview.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pageheap.dot b/chromium/third_party/tcmalloc/vendor/doc/pageheap.dot
new file mode 100644
index 00000000000..82e5fd5f547
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pageheap.dot
@@ -0,0 +1,29 @@
+digraph PageHeap {
+rankdir=LR
+node [shape=box, width=0.3, height=0.3]
+nodesep=.05
+
+heap [shape=record, height=3, label="<f0>1 page|<f1>2 pages|<f2>3 pages|...|<f255>255 pages|<frest>rest"]
+O0 [shape=record, label=""]
+O1 [shape=record, label=""]
+O2 [shape=record, label="{|}"]
+O3 [shape=record, label="{|}"]
+O4 [shape=record, label="{||}"]
+O5 [shape=record, label="{||}"]
+O6 [shape=record, label="{|...|}"]
+O7 [shape=record, label="{|...|}"]
+O8 [shape=record, label="{|.....|}"]
+O9 [shape=record, label="{|.....|}"]
+sep1 [shape=plaintext, label="..."]
+sep2 [shape=plaintext, label="..."]
+sep3 [shape=plaintext, label="..."]
+sep4 [shape=plaintext, label="..."]
+sep5 [shape=plaintext, label="..."]
+
+heap:f0 -> O0 -> O1 -> sep1
+heap:f1 -> O2 -> O3 -> sep2
+heap:f2 -> O4 -> O5 -> sep3
+heap:f255 -> O6 -> O7 -> sep4
+heap:frest -> O8 -> O9 -> sep5
+
+}
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pageheap.gif b/chromium/third_party/tcmalloc/vendor/doc/pageheap.gif
new file mode 100644
index 00000000000..66329812ae1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pageheap.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pprof-test-big.gif b/chromium/third_party/tcmalloc/vendor/doc/pprof-test-big.gif
new file mode 100644
index 00000000000..67a1240fc10
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pprof-test-big.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pprof-test.gif b/chromium/third_party/tcmalloc/vendor/doc/pprof-test.gif
new file mode 100644
index 00000000000..9eeab8ad230
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pprof-test.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gif b/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gif
new file mode 100644
index 00000000000..2ab292abac5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gif b/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gif
new file mode 100644
index 00000000000..42a85472cae
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/pprof.1 b/chromium/third_party/tcmalloc/vendor/doc/pprof.1
new file mode 100644
index 00000000000..466228120f9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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<program> <profile>\fR
+.SH DESCRIPTION
+.IP
+Prints specified cpu- or heap-profile
+.SH OPTIONS
+.TP
+\fB\-\-cum\fR
+Sort by cumulative data
+.TP
+\fB\-\-base=\fR<base>
+Subtract <base> from <profile> 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<regexp>
+Generate source listing of matching routines
+.TP
+\fB\-\-disasm=\fR<regexp>
+Generate disassembly of matching routines
+.TP
+\fB\-\-dot\fR
+Generate DOT file to stdout
+.TP
+\fB\-\-ps\fR
+Generate Postcript 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<n>
+Show at most so many nodes [default=80]
+.TP
+\fB\-\-nodefraction=\fR<f>
+Hide nodes below <f>*total [default=.005]
+.TP
+\fB\-\-edgefraction=\fR<f>
+Hide edges below <f>*total [default=.001]
+.TP
+\fB\-\-focus=\fR<regexp>
+Focus on nodes matching <regexp>
+.TP
+\fB\-\-ignore=\fR<regexp>
+Ignore nodes matching <regexp>
+.TP
+\fB\-\-scale=\fR<n>
+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/chromium/third_party/tcmalloc/vendor/doc/pprof.see_also b/chromium/third_party/tcmalloc/vendor/doc/pprof.see_also
new file mode 100644
index 00000000000..f2caf521258
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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/chromium/third_party/tcmalloc/vendor/doc/pprof_remote_servers.html b/chromium/third_party/tcmalloc/vendor/doc/pprof_remote_servers.html
new file mode 100644
index 00000000000..dd29dfb9668
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/pprof_remote_servers.html
@@ -0,0 +1,260 @@
+<HTML>
+
+<HEAD>
+<title>pprof and Remote Servers</title>
+</HEAD>
+
+<BODY>
+
+<h1><code>pprof</code> and Remote Servers</h1>
+
+<p>In mid-2006, we added an experimental facility to <A
+HREF="cpu_profiler.html">pprof</A>, 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.</p>
+
+<p>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.</p>
+
+<p>To use <code>pprof</code> 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:</p>
+<pre>
+ % pprof internalweb.mycompany.com:80
+</pre>
+
+<p>The host must be listening on that port, and be able to accept HTTP/1.0
+requests -- sent via <code>wget</code> and <code>curl</code> -- for
+several urls. The following sections list the urls that
+<code>pprof</code> can send, and the responses it expects in
+return.</p>
+
+<p>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.:</p>
+<blockquote><pre>
+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
+</pre></blockquote>
+
+<h2> <code><b>/pprof/heap</b></code> </h2>
+
+<p><code>pprof</code> asks for the url <code>/pprof/heap</code> to
+get heap information. The actual url is controlled via the variable
+<code>HEAP_PAGE</code> in the <code>pprof</code> script, so you
+can change it if you'd like.</p>
+
+<p>There are two ways to get this data. The first is to call</p>
+<pre>
+ MallocExtension::instance()->GetHeapSample(&output);
+</pre>
+<p>and have the server send <code>output</code> back as an HTTP
+response to <code>pprof</code>. <code>MallocExtension</code> is
+defined in the header file <code>gperftools/malloc_extension.h</code>.</p>
+
+<p>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 <code>TCMALLOC_SAMPLE_PARAMETER</code> to a
+positive value, such as 524288, before running.</p>
+
+<p>The other way is to call <code>HeapProfileStart(filename)</code>
+(from <code>heap-profiler.h</code>), continue to do work, and then,
+some number of seconds later, call <code>GetHeapProfile()</code>
+(followed by <code>HeapProfilerStop()</code>). The server can send
+the output of <code>GetHeapProfile</code> back as the HTTP response to
+pprof. (Note you must <code>free()</code> this data after using it.)
+This is similar to how <A HREF="#profile">profile requests</A> are
+handled, below. This technique does not require the application to
+run with sampling turned on.</p>
+
+<p>Here's an example of what the output should look like:</p>
+<pre>
+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
+[...]
+</pre>
+
+
+<p> Older code may produce "version 1" heap profiles which look like this:<p/>
+<pre>
+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
+[...]
+</pre>
+<p>pprof accepts both old and new heap profiles and automatically
+detects which one you are using.</p>
+
+<h2> <code><b>/pprof/growth</b></code> </h2>
+
+<p><code>pprof</code> asks for the url <code>/pprof/growth</code> to
+get heap-profiling delta (growth) information. The actual url is
+controlled via the variable <code>GROWTH_PAGE</code> in the
+<code>pprof</code> script, so you can change it if you'd like.</p>
+
+<p>The server should respond by calling</p>
+<pre>
+ MallocExtension::instance()->GetHeapGrowthStacks(&output);
+</pre>
+<p>and sending <code>output</code> back as an HTTP response to
+<code>pprof</code>. <code>MallocExtension</code> is defined in the
+header file <code>gperftools/malloc_extension.h</code>.</p>
+
+<p>Here's an example, from an actual Google webserver, of what the
+output should look like:</p>
+<pre>
+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
+[...]
+</pre>
+
+
+<h2> <A NAME="profile"><code><b>/pprof/profile</b></code></A> </h2>
+
+<p><code>pprof</code> asks for the url
+<code>/pprof/profile?seconds=XX</code> to get cpu-profiling
+information. The actual url is controlled via the variable
+<code>PROFILE_PAGE</code> in the <code>pprof</code> script, so you can
+change it if you'd like.</p>
+
+<p>The server should respond by calling
+<code>ProfilerStart(filename)</code>, continuing to do its work, and
+then, XX seconds later, calling <code>ProfilerStop()</code>. (These
+functions are declared in <code>gperftools/profiler.h</code>.) The
+application is responsible for picking a unique filename for
+<code>ProfilerStart()</code>. After calling
+<code>ProfilerStop()</code>, the server should read the contents of
+<code>filename</code> and send them back as an HTTP response to
+<code>pprof</code>.</p>
+
+<p>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.</p>
+
+<p>The profiler output file is binary, but near the end of it, it
+should have lines of text somewhat like this:</p>
+<pre>
+01016000-01017000 rw-p 00015000 03:01 59314 /lib/ld-2.2.2.so
+</pre>
+
+<h2> <code><b>/pprof/pmuprofile</b></code> </h2>
+
+<code>pprof</code> asks for a url of the form
+<code>/pprof/pmuprofile?event=hw_event:unit_mask&period=nnn&seconds=xxx</code>
+to get cpu-profiling information. The actual url is controlled via the variable
+<code>PMUPROFILE_PAGE</code> in the <code>pprof</code> script, so you can
+change it if you'd like.</p>
+
+<p>
+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 <a href="http://perfmon2.sourceforge.net/">
+<code>libpfm</code></a>. It should collect a sample every nnn occurences
+of the event and stop the sampling after xxx seconds. Much of the code
+for <code>/pprof/profile</code> can be reused for this purpose.
+</p>
+
+<p>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.</p>
+
+<h2> <code><b>/pprof/contention</b></code> </h2>
+
+<p>This is intended to be able to profile (thread) lock contention in
+addition to CPU and memory use. It's not yet usable.</p>
+
+
+<h2> <code><b>/pprof/cmdline</b></code> </h2>
+
+<p><code>pprof</code> asks for the url <code>/pprof/cmdline</code> to
+figure out what application it's profiling. The actual url is
+controlled via the variable <code>PROGRAM_NAME_PAGE</code> in the
+<code>pprof</code> script, so you can change it if you'd like.</p>
+
+<p>The server should respond by reading the contents of
+<code>/proc/self/cmdline</code>, converting all internal NUL (\0)
+characters to newlines, and sending the result back as an HTTP
+response to <code>pprof</code>.</p>
+
+<p>Here's an example return value:<p>
+<pre>
+/root/server/custom_webserver
+80
+--configfile=/root/server/ws.config
+</pre>
+
+
+<h2> <code><b>/pprof/symbol</b></code> </h2>
+
+<p><code>pprof</code> asks for the url <code>/pprof/symbol</code> to
+map from hex addresses to variable names. The actual url is
+controlled via the variable <code>SYMBOL_PAGE</code> in the
+<code>pprof</code> script, so you can change it if you'd like.</p>
+
+<p>When the server receives a GET request for
+<code>/pprof/symbol</code>, it should return a line formatted like
+so:</p>
+<pre>
+ num_symbols: ###
+</pre>
+<p>where <code>###</code> 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).</p>
+
+<p>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 <code>+</code>, like so:</p>
+<pre>
+ curl -d '0x0824d061+0x0824d1cf' http://remote_host:80/pprof/symbol
+</pre>
+
+<p>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:</p>
+<pre>
+&lt;hex address&gt;&lt;tab&gt;&lt;function name&gt;
+</pre>
+<p>For instance:</p>
+<pre>
+0x08b2dabd _Update
+</pre>
+
+<p>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 <code>nm -C
+-n &lt;program name&gt;</code> to get the mappings at
+program-compile-time. Another, at least on Linux, is to call out to
+addr2line for every <code>pprof/symbol</code> call, for instance
+<code>addr2line -Cfse /proc/<getpid>/exe 0x12345678 0x876543210</code>
+(presumably with some caching!)</p>
+
+<p><code>pprof</code> itself does just this for local profiles (not
+ones that talk to remote servers); look at the subroutine
+<code>GetProcedureBoundaries</code>.</p>
+
+
+<hr>
+Last modified: Mon Jun 12 21:30:14 PDT 2006
+</body>
+</html>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/spanmap.dot b/chromium/third_party/tcmalloc/vendor/doc/spanmap.dot
new file mode 100644
index 00000000000..3cb42abe5b2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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="<f0>|<f1>|<f2>|<f3>|<f4>|<f5>|<f6>|<f7>|<f8>|<f9>|<f10>"]
+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/chromium/third_party/tcmalloc/vendor/doc/spanmap.gif b/chromium/third_party/tcmalloc/vendor/doc/spanmap.gif
new file mode 100644
index 00000000000..a0627f6a71a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/spanmap.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/t-test1.times.txt b/chromium/third_party/tcmalloc/vendor/doc/t-test1.times.txt
new file mode 100644
index 00000000000..016369385b2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
new file mode 100644
index 00000000000..8c0ae6b59c2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
new file mode 100644
index 00000000000..24b2a27410f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
new file mode 100644
index 00000000000..183a77b9c9f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
new file mode 100644
index 00000000000..db59d61ae02
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
new file mode 100644
index 00000000000..169546f2406
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
new file mode 100644
index 00000000000..62130213c3b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
new file mode 100644
index 00000000000..18715e3a5ab
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
new file mode 100644
index 00000000000..642e245b444
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
new file mode 100644
index 00000000000..aea1d676471
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
new file mode 100644
index 00000000000..3a080de7533
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
new file mode 100644
index 00000000000..48ebdb63e8a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
new file mode 100644
index 00000000000..3a99cbc8b1f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png
new file mode 100644
index 00000000000..37d406d81f6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png
new file mode 100644
index 00000000000..d45458ac1a0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png
new file mode 100644
index 00000000000..e8a3c9ff5f5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png
new file mode 100644
index 00000000000..52d7aee4903
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png
new file mode 100644
index 00000000000..da0328a6a7b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png
new file mode 100644
index 00000000000..1093e81ca6b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png
new file mode 100644
index 00000000000..d7c79ef328c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png
new file mode 100644
index 00000000000..779eec60bc0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png
new file mode 100644
index 00000000000..76c125ae8b2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/doc/tcmalloc.html b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc.html
new file mode 100644
index 00000000000..8d72c0c32a8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/tcmalloc.html
@@ -0,0 +1,765 @@
+<!doctype html public "-//w3c//dtd html 4.01 transitional//en">
+<!-- $Id: $ -->
+<html>
+<head>
+<title>TCMalloc : Thread-Caching Malloc</title>
+<link rel="stylesheet" href="designstyle.css">
+<style type="text/css">
+ em {
+ color: red;
+ font-style: normal;
+ }
+</style>
+</head>
+<body>
+
+<h1>TCMalloc : Thread-Caching Malloc</h1>
+
+<address>Sanjay Ghemawat</address>
+
+<h2><A name=motivation>Motivation</A></h2>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>Another benefit of TCMalloc is space-efficient representation of
+small objects. For example, N 8-byte objects can be allocated while
+using space approximately <code>8N * 1.01</code> 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 <code>16N</code> bytes.</p>
+
+
+<h2><A NAME="Usage">Usage</A></h2>
+
+<p>To use TCMalloc, just link TCMalloc into your application via the
+"-ltcmalloc" linker flag.</p>
+
+<p>You can use TCMalloc in applications you didn't compile yourself,
+by using LD_PRELOAD:</p>
+<pre>
+ $ LD_PRELOAD="/usr/lib/libtcmalloc.so" <binary>
+</pre>
+<p>LD_PRELOAD is tricky, and we don't necessarily recommend this mode
+of usage.</p>
+
+<p>TCMalloc includes a <A HREF="heap_checker.html">heap checker</A>
+and <A HREF="heapprofile.html">heap profiler</A> as well.</p>
+
+<p>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 <code>libtcmalloc_minimal</code>
+instead.</p>
+
+
+<h2><A NAME="Overview">Overview</A></h2>
+
+<p>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.</p>
+<center><img src="overview.gif"></center>
+
+<p>TCMalloc treats objects with size &lt;= 32K ("small" objects)
+differently from larger objects. Large objects are allocated directly
+from the central heap using a page-level allocator (a page is a 4K
+aligned region of memory). I.e., a large object is always
+page-aligned and occupies an integral number of pages.</p>
+
+<p>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.</p>
+
+
+<h2><A NAME="Small_Object_Allocation">Small Object Allocation</A></h2>
+
+<p>Each small object size maps to one of approximately 60 allocatable
+size-classes. For example, all allocations in the range 833 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.</p>
+
+<p>A thread cache contains a singly linked list of free objects per
+size-class.</p>
+<center><img src="threadheap.gif"></center>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<h3><A NAME="Sizing_Thread_Cache_Free_Lists">
+ Sizing Thread Cache Free Lists</A></h3>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<p>The psuedo-code below illustrates this slow-start algorithm. Note
+that <code>num_objects_to_move</code> 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 <code>num_objects_to_move</code>,
+the operation on the central free list has linear time complexity.
+The downside of always using <code>num_objects_to_move</code> 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.
+
+<pre>
+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;
+ }
+ }
+ }
+</pre>
+
+See also the section on <a href="#Garbage_Collection">Garbage Collection</a>
+to see how it affects the <code>max_length</code>.
+
+<h2><A NAME="Large_Object_Allocation">Large Object Allocation</A></h2>
+
+<p>A large object size (&gt; 32K) is rounded up to a page size (4K)
+and is handled by a central page heap. The central page heap is again
+an array of free lists. For <code>i &lt; 256</code>, the
+<code>k</code>th entry is a free list of runs that consist of
+<code>k</code> pages. The <code>256</code>th entry is a free list of
+runs that have length <code>&gt;= 256</code> pages: </p>
+<center><img src="pageheap.gif"></center>
+
+<p>An allocation for <code>k</code> pages is satisfied by looking in
+the <code>k</code>th free list. If that free list is empty, we look
+in the next free list, and so forth. Eventually, we look in the last
+free list if necessary. If that fails, we fetch memory from the
+system (using <code>sbrk</code>, <code>mmap</code>, or by mapping in
+portions of <code>/dev/mem</code>).</p>
+
+<p>If an allocation for <code>k</code> pages is satisfied by a run
+of pages of length &gt; <code>k</code>, the remainder of the
+run is re-inserted back into the appropriate free list in the
+page heap.</p>
+
+
+<h2><A NAME="Spans">Spans</A></h2>
+
+<p>The heap managed by TCMalloc consists of a set of pages. A run of
+contiguous pages is represented by a <code>Span</code> object. A span
+can either be <em>allocated</em>, or <em>free</em>. 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.</p>
+
+<p>A central array indexed by page number can be used to find the span to
+which a page belongs. For example, span <em>a</em> below occupies 2
+pages, span <em>b</em> occupies 1 page, span <em>c</em> occupies 5
+pages and span <em>d</em> occupies 3 pages.</p>
+<center><img src="spanmap.gif"></center>
+
+<p>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^15 entries (a 32-bit address spave has 2^20 4K pages, and
+the first level of tree divides the 2^20 pages by 2^5). This leads to
+a starting memory usage of 128KB of space (2^15*4 bytes) for the
+central array, which seems acceptable.</p>
+
+<p>On 64-bit machines, we use a 3-level radix tree.</p>
+
+
+<h2><A NAME="Deallocation">Deallocation</A></h2>
+
+<p>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.</p>
+
+<p>If the object is large, the span tells us the range of pages covered
+by the object. Suppose this range is <code>[p,q]</code>. We also
+lookup the spans for pages <code>p-1</code> and <code>q+1</code>. If
+either of these neighboring spans are free, we coalesce them with the
+<code>[p,q]</code> span. The resulting span is inserted into the
+appropriate free list in the page heap.</p>
+
+
+<h2>Central Free Lists for Small Objects</h2>
+
+<p>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.</p>
+
+<p>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.)</p>
+
+<p>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.</p>
+
+
+<h2><A NAME="Garbage_Collection">Garbage Collection of Thread Caches</A></h2>
+
+<p>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 <code>max_size</code>, garbage collection kicks in and then the
+thread competes with the other threads for a larger cache.</p>
+
+<p>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.</p>
+
+<p>The number of objects to be moved from a free list is determined
+using a per-list low-water-mark <code>L</code>. <code>L</code>
+records the minimum length of the list since the last garbage
+collection. Note that we could have shortened the list by
+<code>L</code> 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 <code>L/2</code>
+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.</p>
+
+<p>If a thread consistently deallocates more objects of a certain size
+than it allocates, this <code>L/2</code> behavior will cause at least
+<code>L/2</code> 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 <code>num_objects_to_move</code> (see also
+<a href="#Sizing_Thread_Cache_Free_Lists">Sizing Thread Cache Free Lists</a>).
+
+<pre>
+Garbage Collection
+ if (L != 0 && max_length > num_objects_to_move) {
+ max_length = max(max_length - num_objects_to_move, num_objects_to_move)
+ }
+</pre>
+
+<p>The fact that the thread cache went over its <code>max_size</code> is
+an indication that the thread would benefit from a larger cache. Simply
+increasing <code>max_size</code> 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.</p>
+
+<p>Each thread cache starts with a small <code>max_size</code>
+(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 <code>max_size</code>. If the sum of the thread cache
+sizes is less than --tcmalloc_max_total_thread_cache_bytes,
+<code>max_size</code> grows easily. If not, thread cache 1 will try
+to steal from thread cache 2 (picked round-robin) by decreasing thread
+cache 2's <code>max_size</code>. 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.</p>
+
+<h2><A NAME="performance">Performance Notes</A></h2>
+
+<h3>PTMalloc2 unittest</h3>
+
+<p>The PTMalloc2 package (now part of glibc) contains a unittest
+program <code>t-test1.c</code>. 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.</p>
+
+<p><code>t-test1</code> (included in
+<code>tests/tcmalloc/</code>, and compiled as
+<code>ptmalloc_unittest1</code>) 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
+<code>LD_PRELOAD=libtcmalloc.so</code>.
+
+<p>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
+<code>time</code> utility) is available in
+<code>t-test1.times.txt</code>.</p>
+
+<table>
+<tr>
+ <td><img src="tcmalloc-opspersec.vs.size.1.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.2.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.3.threads.png"></td>
+</tr>
+<tr>
+ <td><img src="tcmalloc-opspersec.vs.size.4.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.5.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.8.threads.png"></td>
+</tr>
+<tr>
+ <td><img src="tcmalloc-opspersec.vs.size.12.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.16.threads.png"></td>
+ <td><img src="tcmalloc-opspersec.vs.size.20.threads.png"></td>
+</tr>
+</table>
+
+
+<ul>
+ <li> TCMalloc is much more consistently scalable than PTMalloc2 - for
+ all thread counts &gt;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 &lt;1 million ops/sec for
+ larger allocations.
+
+ <li> 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.
+
+ <li> 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.
+
+ <li> 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.
+</ul>
+
+<p>Next, operations (millions) per second of CPU time vs number of
+threads, for max allocation size 64 bytes - 128 Kbytes.</p>
+
+<table>
+<tr>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.64.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.256.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.1024.bytes.png"></td>
+</tr>
+<tr>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.4096.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.8192.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.16384.bytes.png"></td>
+</tr>
+<tr>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.32768.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.65536.bytes.png"></td>
+ <td><img src="tcmalloc-opspercpusec.vs.threads.131072.bytes.png"></td>
+</tr>
+</table>
+
+<p>Here we see again that TCMalloc is both more consistent and more
+efficient than PTMalloc2. For max allocation sizes &lt;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).</p>
+
+
+<H2><A NAME="runtime">Modifying Runtime Behavior</A></H2>
+
+<p>You can more finely control the behavior of the tcmalloc via
+environment variables.</p>
+
+<p>Generally useful flags:</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>TCMALLOC_SAMPLE_PARAMETER</code></td>
+ <td>default: 0</td>
+ <td>
+ The approximate gap between sampling actions. That is, we
+ take one sample approximately once every
+ <code>tcmalloc_sample_parmeter</code> bytes of allocation.
+ This sampled heap information is available via
+ <code>MallocExtension::GetHeapSample()</code> or
+ <code>MallocExtension::ReadStackTraces()</code>. A reasonable
+ value is 524288.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_RELEASE_RATE</code></td>
+ <td>default: 1.0</td>
+ <td>
+ Rate at which we release unused memory to the system, via
+ <code>madvise(MADV_DONTNEED)</code>, 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].
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD</code></td>
+ <td>default: 1073741824</td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES</code></td>
+ <td>default: 16777216</td>
+ <td>
+ 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 <a href="#Garbage_Collection">
+ Garbage Collection</a> for more details.
+ </td>
+</tr>
+
+</table>
+
+<p>Advanced "tweaking" flags, that control more precisely how tcmalloc
+tries to allocate memory from the kernel.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>TCMALLOC_SKIP_MMAP</code></td>
+ <td>default: false</td>
+ <td>
+ If true, do not try to use <code>mmap</code> to obtain memory
+ from the kernel.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_SKIP_SBRK</code></td>
+ <td>default: false</td>
+ <td>
+ If true, do not try to use <code>sbrk</code> to obtain memory
+ from the kernel.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_DEVMEM_START</code></td>
+ <td>default: 0</td>
+ <td>
+ Physical memory starting location in MB for <code>/dev/mem</code>
+ allocation. Setting this to 0 disables <code>/dev/mem</code>
+ allocation.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_DEVMEM_LIMIT</code></td>
+ <td>default: 0</td>
+ <td>
+ Physical memory limit location in MB for <code>/dev/mem</code>
+ allocation. Setting this to 0 means no limit.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_DEVMEM_DEVICE</code></td>
+ <td>default: /dev/mem</td>
+ <td>
+ Device to use for allocating unmanaged memory.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_MALLOC_PATH</code></td>
+ <td>default: ""</td>
+ <td>
+ If set, specify a path where hugetlbfs or tmpfs is mounted.
+ This may allow for speedier allocations.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_LIMIT_MB</code></td>
+ <td>default: 0</td>
+ <td>
+ Limit total memfs allocation size to specified number of MB.
+ 0 means "no limit".
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_ABORT_ON_FAIL</code></td>
+ <td>default: false</td>
+ <td>
+ If true, abort() whenever memfs_malloc fails to satisfy an allocation.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_IGNORE_MMAP_FAIL</code></td>
+ <td>default: false</td>
+ <td>
+ If true, ignore failures from mmap.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_MAP_PRVIATE</code></td>
+ <td>default: false</td>
+ <td>
+ If true, use MAP_PRIVATE when mapping via memfs, not MAP_SHARED.
+ </td>
+</tr>
+
+</table>
+
+
+<H2><A NAME="compiletime">Modifying Behavior In Code</A></H2>
+
+<p>The <code>MallocExtension</code> class, in
+<code>malloc_extension.h</code>, provides a few knobs that you can
+tweak in your program, to affect tcmalloc's behavior.</p>
+
+<h3>Releasing Memory Back to the System</h3>
+
+<p>By default, tcmalloc will release no-longer-used memory back to the
+kernel gradually, over time. The <a
+href="#runtime">tcmalloc_release_rate</a> flag controls how quickly
+this happens. You can also force a release at a given point in the
+progam execution like so:</p>
+<pre>
+ MallocExtension::instance()->ReleaseFreeMemory();
+</pre>
+
+<p>You can also call <code>SetMemoryReleaseRate()</code> to change the
+<code>tcmalloc_release_rate</code> value at runtime, or
+<code>GetMemoryReleaseRate</code> to see what the current release rate
+is.</p>
+
+<h3>Memory Introspection</h3>
+
+<p>There are several routines for getting a human-readable form of the
+current memory usage:</p>
+<pre>
+ MallocExtension::instance()->GetStats(buffer, buffer_length);
+ MallocExtension::instance()->GetHeapSample(&string);
+ MallocExtension::instance()->GetHeapGrowthStacks(&string);
+</pre>
+
+<p>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.</p>
+
+<h3>Generic Tcmalloc Status</h3>
+
+<p>TCMalloc has support for setting and retrieving arbitrary
+'properties':</p>
+<pre>
+ MallocExtension::instance()->SetNumericProperty(property_name, value);
+ MallocExtension::instance()->GetNumericProperty(property_name, &value);
+</pre>
+
+<p>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
+<code>MallocExtension::instance()->GetNumericProperty("generic.heap_size",
+&value);</code>:</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>generic.current_allocated_bytes</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>generic.heap_size</code></td>
+ <td>
+ Bytes of system memory reserved by TCMalloc.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>tcmalloc.pageheap_free_bytes</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>tcmalloc.pageheap_unmapped_bytes</code></td>
+ <td>
+ 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.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>tcmalloc.slack_bytes</code></td>
+ <td>
+ Sum of pageheap_free_bytes and pageheap_unmapped_bytes. Provided
+ for backwards compatibility only. Do not use.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>tcmalloc.max_total_thread_cache_bytes</code></td>
+ <td>
+ A limit to how much memory TCMalloc dedicates for small objects.
+ Higher numbers trade off more memory use for -- in some situations
+ -- improved efficiency.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>tcmalloc.current_total_thread_cache_bytes</code></td>
+ <td>
+ A measure of some of the memory TCMalloc is using (for
+ small objects).
+ </td>
+</tr>
+
+</table>
+
+<h2><A NAME="caveats">Caveats</A></h2>
+
+<p>For some systems, TCMalloc may not work correctly with
+applications that aren't linked against <code>libpthread.so</code> (or
+the equivalent on your OS). It should work on Linux using glibc 2.3,
+but other OS/libc combinations have not been tested.</p>
+
+<p>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.</p>
+
+<p>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.</p>
+
+<hr>
+
+<address>Sanjay Ghemawat, Paul Menage<br>
+<!-- Created: Tue Dec 19 10:43:14 PST 2000 -->
+<!-- hhmts start -->
+Last modified: Sat Feb 24 13:11:38 PST 2007 (csilvers)
+<!-- hhmts end -->
+</address>
+
+</body>
+</html>
diff --git a/chromium/third_party/tcmalloc/vendor/doc/threadheap.dot b/chromium/third_party/tcmalloc/vendor/doc/threadheap.dot
new file mode 100644
index 00000000000..b2dba72038d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/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="<f0>class 0|<f1>class 1|<f2>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/chromium/third_party/tcmalloc/vendor/doc/threadheap.gif b/chromium/third_party/tcmalloc/vendor/doc/threadheap.gif
new file mode 100644
index 00000000000..c43d0a31018
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/doc/threadheap.gif
Binary files differ
diff --git a/chromium/third_party/tcmalloc/vendor/install-sh b/chromium/third_party/tcmalloc/vendor/install-sh
new file mode 100644
index 00000000000..a5897de6ea7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# 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.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# 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_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+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 the last 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.
+ -s $stripprog installed files.
+ -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
+"
+
+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
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+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
+ 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
+ trap '(exit $?); exit' 1 2 13 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 starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ 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
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # 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
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/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-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or 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
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && 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=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_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 && $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` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # 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 -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$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 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/ltmain.sh b/chromium/third_party/tcmalloc/vendor/ltmain.sh
new file mode 100644
index 00000000000..7ed280bc952
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/ltmain.sh
@@ -0,0 +1,8413 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.6b
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 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 GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+# --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
+# --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 informational messages (default)
+# --version print version information
+# -h, --help print short or 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.
+# 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)
+# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1
+# automake: $automake_version
+# autoconf: $autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION="2.2.6b Debian-2.2.6b-2ubuntu1"
+TIMESTAMP=""
+package_revision=1.3017
+
+# 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
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test \"\${$lt_var+set}\" = set; then
+ save_$lt_var=\$$lt_var
+ $lt_var=C
+ export $lt_var
+ lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+ lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+ fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+: ${CP="cp -f"}
+: ${ECHO="echo"}
+: ${EGREP="/bin/grep -E"}
+: ${FGREP="/bin/grep -F"}
+: ${GREP="/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/bin/sed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+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.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# 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"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# 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:
+# In the unlikely event $progname began with a '-', it would play havoc with
+# func_echo (imagine progname=-n), so we prepend ./ in that case:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+case $progname in
+ -*) progname=./$progname ;;
+esac
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=$func_dirname_result
+ progdir=`cd "$progdir" && pwd`
+ progpath="$progdir/$progname"
+ ;;
+ *)
+ save_IFS="$IFS"
+ IFS=:
+ for progdir in $PATH; do
+ IFS="$save_IFS"
+ test -x "$progdir/$progname" && break
+ done
+ IFS="$save_IFS"
+ test -n "$progdir" || progdir=`pwd`
+ progpath="$progdir/$progname"
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same. If an odd number of `\' preceded a '$'
+# in input to 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 '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+ s/$bs4/&\\
+/g
+ s/^$bs2$dollar/$bs&/
+ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+ s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+ $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $opt_verbose && 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_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+ $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ func_error ${1+"$@"}
+ func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information." ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ my_directory_path="$1"
+ my_dir_list=
+
+ if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+ # Protect directory names starting with `-'
+ case $my_directory_path in
+ -*) my_directory_path="./$my_directory_path" ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$my_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ my_dir_list="$my_directory_path:$my_dir_list"
+
+ # If the last portion added has no slash in it, the list is done
+ case $my_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+ done
+ my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+
+ save_mkdir_p_IFS="$IFS"; IFS=':'
+ for my_dir in $my_dir_list; do
+ IFS="$save_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 "$my_dir" 2>/dev/null || :
+ done
+ IFS="$save_mkdir_p_IFS"
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$my_directory_path" || \
+ func_fatal_error "Failed to create \`$1'"
+ fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$opt_dry_run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || \
+ func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+ fi
+
+ $ECHO "X$my_tmpdir" | $Xsed
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+ case $1 in
+ *[\\\`\"\$]*)
+ func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+ *)
+ func_quote_for_eval_unquoted_result="$1" ;;
+ esac
+
+ case $func_quote_for_eval_unquoted_result in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and and variable
+ # expansion for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+ ;;
+ *)
+ func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+ esac
+}
+
+
+# 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 ()
+{
+ case $1 in
+ *[\\\`\"]*)
+ my_arg=`$ECHO "X$1" | $Xsed \
+ -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+ *)
+ my_arg="$1" ;;
+ esac
+
+ case $my_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.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ my_arg="\"$my_arg\""
+ ;;
+ esac
+
+ func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent 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 ()
+{
+ my_cmd="$1"
+ my_fail_exp="${2-:}"
+
+ ${opt_silent-false} || {
+ func_quote_for_expand "$my_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ if ${opt_dry_run-false}; then :; else
+ eval "$my_cmd"
+ my_status=$?
+ if test "$my_status" -eq 0; then :; else
+ eval "(exit $my_status); $my_fail_exp"
+ fi
+ fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent 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 ()
+{
+ my_cmd="$1"
+ my_fail_exp="${2-:}"
+
+ ${opt_silent-false} || {
+ func_quote_for_expand "$my_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ if ${opt_dry_run-false}; then :; else
+ eval "$lt_user_locale
+ $my_cmd"
+ my_status=$?
+ eval "$lt_safe_locale"
+ if test "$my_status" -eq 0; then :; else
+ eval "(exit $my_status); $my_fail_exp"
+ fi
+ fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+ $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+ s/^# //
+ s/^# *$//
+ s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+ p
+ }' < "$progpath"
+ exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $SED -n '/^# Usage:/,/# -h/ {
+ s/^# //
+ s/^# *$//
+ s/\$progname/'$progname'/
+ p
+ }' < "$progpath"
+ $ECHO
+ $ECHO "run \`$progname --help | more' for full usage"
+ exit $?
+}
+
+# func_help
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $SED -n '/^# Usage:/,/# Report bugs to/ {
+ s/^# //
+ s/^# *$//
+ s*\$progname*'$progname'*
+ s*\$host*'"$host"'*
+ s*\$SHELL*'"$SHELL"'*
+ s*\$LTCC*'"$LTCC"'*
+ s*\$LTCFLAGS*'"$LTCFLAGS"'*
+ s*\$LD*'"$LD"'*
+ s/\$with_gnu_ld/'"$with_gnu_ld"'/
+ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+ p
+ }' < "$progpath"
+ exit $?
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ func_error "missing argument for $1"
+ exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+# Check that we have a working $ECHO.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell, and then maybe $ECHO will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# 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=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func_error ${1+"$@"}
+ func_error "See the $PACKAGE documentation for more information."
+ func_fatal_error "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 "$build_libtool_libs" = yes; then
+ $ECHO "enable shared libraries"
+ else
+ $ECHO "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; 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
+}
+
+# Parse options once, thoroughly. This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+ # 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
+ ;;
+ esac
+
+ # Parse non-mode specific arguments:
+ while test "$#" -gt 0; do
+ opt="$1"
+ shift
+
+ case $opt in
+ --config) func_config ;;
+
+ --debug) preserve_args="$preserve_args $opt"
+ func_echo "enabling shell trace mode"
+ opt_debug='set -x'
+ $opt_debug
+ ;;
+
+ -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ execute_dlfiles="$execute_dlfiles $1"
+ shift
+ ;;
+
+ --dry-run | -n) opt_dry_run=: ;;
+ --features) func_features ;;
+ --finish) mode="finish" ;;
+
+ --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ 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 $opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+
+ mode="$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_duplicate_deps=: ;;
+
+ --quiet|--silent) preserve_args="$preserve_args $opt"
+ opt_silent=:
+ ;;
+
+ --verbose| -v) preserve_args="$preserve_args $opt"
+ opt_silent=false
+ ;;
+
+ --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ preserve_args="$preserve_args $opt $1"
+ func_enable_tag "$1" # tagname is set here
+ shift
+ ;;
+
+ # Separate optargs to long options:
+ -dlopen=*|--mode=*|--tag=*)
+ func_opt_split "$opt"
+ set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+ shift
+ ;;
+
+ -\?|-h) func_usage ;;
+ --help) opt_help=: ;;
+ --version) func_version ;;
+
+ -*) func_fatal_help "unrecognized option \`$opt'" ;;
+
+ *) nonopt="$opt"
+ break
+ ;;
+ esac
+ done
+
+
+ case $host in
+ *cygwin* | *mingw* | *pw32* | *cegcc*)
+ # don't eliminate duplications in $postdeps and $predeps
+ opt_duplicate_compiler_generated_deps=:
+ ;;
+ *)
+ opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+ ;;
+ esac
+
+ # Having warned about all mis-specified options, bail out if
+ # anything was wrong.
+ $exit_cmd $EXIT_FAILURE
+}
+
+# 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
+}
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+$opt_help || {
+ # Sanity checks first:
+ func_check_version_match
+
+ if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ func_fatal_configuration "not configured to build any kind of library"
+ fi
+
+ test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; 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=$mode' for more information."
+}
+
+
+# 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 \
+ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# 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 "$lalib_p" = yes
+}
+
+# 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 ()
+{
+ func_lalib_p "$1"
+}
+
+# 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_ltwrapper_scriptname_result=""
+ if func_ltwrapper_executable_p "$1"; then
+ func_dirname_and_basename "$1" "" "."
+ func_stripname '' '.exe' "$func_basename_result"
+ func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+ fi
+}
+
+# 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 ()
+{
+ $opt_debug
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$save_ifs
+ eval cmd=\"$cmd\"
+ 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 ()
+{
+ $opt_debug
+ case $1 in
+ */* | *\\*) . "$1" ;;
+ *) . "./$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 ()
+{
+ $opt_debug
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ func_quote_for_eval "$arg"
+ CC_quoted="$CC_quoted $func_quote_for_eval_result"
+ done
+ 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 "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+ # 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_quote_for_eval "$arg"
+ CC_quoted="$CC_quoted $func_quote_for_eval_result"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+ # 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 "$build_libtool_libs" = yes; then
+ write_lobj=\'${2}\'
+ else
+ write_lobj=none
+ fi
+
+ if test "$build_old_libs" = yes; then
+ write_oldobj=\'${3}\'
+ else
+ write_oldobj=none
+ fi
+
+ $opt_dry_run || {
+ cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+ $MV "${write_libobj}T" "${write_libobj}"
+ }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $opt_debug
+ # 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)
+ pie_flag="$pie_flag $arg"
+ continue
+ ;;
+
+ -shared | -static | -prefer-pic | -prefer-non-pic)
+ later="$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_quote_for_eval "$arg"
+ lastarg="$lastarg $func_quote_for_eval_result"
+ done
+ IFS="$save_ifs"
+ func_stripname ' ' '' "$lastarg"
+ lastarg=$func_stripname_result
+
+ # Add the arguments to base_compile.
+ base_compile="$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_quote_for_eval "$lastarg"
+ base_compile="$base_compile $func_quote_for_eval_result"
+ 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 | *.obj | *.sx)
+ 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 "$build_libtool_libs" != yes && \
+ func_fatal_configuration "can not 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 "$build_old_libs" = yes; 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 "$pic_mode" = no && test "$deplibs_check_method" != pass_all; 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 "$compiler_c_o" = no; then
+ output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e '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 "$need_locks" = yes; 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 "$need_locks" = warn; 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
+ removelist="$removelist $output_obj"
+ $ECHO "$srcfile" > "$lockfile"
+ fi
+
+ $opt_dry_run || $RM $removelist
+ removelist="$removelist $lockfile"
+ trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ func_quote_for_eval "$srcfile"
+ qsrcfile=$func_quote_for_eval_result
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; 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
+ command="$command -o $lobj"
+ fi
+
+ func_show_eval_locale "$command" \
+ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+ if test "$need_locks" = warn &&
+ 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 "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ func_show_eval_locale "$command" \
+ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+ if test "$need_locks" = warn &&
+ 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 "$need_locks" != no; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+ # We need to display help for each of the modes.
+ case $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 building PIC objects only
+ -prefer-non-pic try to building 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
+
+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 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
+ -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
+ -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
+
+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 \`$mode'"
+ ;;
+ esac
+
+ $ECHO
+ $ECHO "Try \`$progname --help' for more information about other modes."
+
+ exit $?
+}
+
+ # Now that we've collected a possible --mode arg, show help if necessary
+ $opt_help && func_mode_help
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+ $opt_debug
+ # 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 $execute_dlfiles; do
+ test -f "$file" \
+ || func_fatal_help "\`$file' is not a file"
+
+ dir=
+ case $file in
+ *.la)
+ # 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
+ dir="$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
+ -*) ;;
+ *)
+ # 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_quote_for_eval "$file"
+ args="$args $func_quote_for_eval_result"
+ done
+
+ if test "X$opt_dry_run" = Xfalse; then
+ 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"
+ else
+ # 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
+ fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $opt_debug
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ 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" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ $opt_silent && exit $EXIT_SUCCESS
+
+ $ECHO "X----------------------------------------------------------------------" | $Xsed
+ $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 "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $opt_debug
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $ECHO "X$nonopt" | $GREP shtool >/dev/null; 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"
+ install_prog="$install_prog$func_quote_for_eval_result"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o)
+ prev=$arg
+ ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ func_quote_for_eval "$arg"
+ install_prog="$install_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 -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=yes
+ if test "$isdir" = yes; 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.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # 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 "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ func_dirname "$file" "/" ""
+ dir="$func_dirname_result"
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -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 "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "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_prog $dir/$srcname $destdir/$realname" \
+ 'exit $?'
+ tstripme="$stripme"
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ 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" && staticlibs="$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 "$build_old_libs" = yes; 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=yes
+ 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 "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "\`$lib' has not been installed in \`$libdir'"
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if test "$finalize" = yes; then
+ tmpdir=`func_mktempdir`
+ func_basename "$file$stripped_ext"
+ file="$func_basename_result"
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $opt_silent || {
+ 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 "X$file$stripped_ext" | $Xsed -e "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_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ func_show_eval "$old_striplib $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 "$mode" = install && 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 ()
+{
+ $opt_debug
+ my_outputname="$1"
+ my_originator="$2"
+ my_pic_p="${3-no}"
+ my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; 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 "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for progfile in $progfiles; do
+ func_verbose "extracting global C symbols from \`$progfile'"
+ $opt_dry_run || eval "$NM $progfile | $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"
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ 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 >/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
+
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols. */
+typedef struct {
+ const char *name;
+ void *address;
+} lt_dlsymlist;
+"
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs. */"
+ lt_dlsym_const= ;;
+ *osf5*)
+ echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+ lt_dlsym_const= ;;
+ *)
+ lt_dlsym_const=const ;;
+ esac
+
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+ { \"$my_originator\", (void *) 0 },"
+
+ 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" ;;
+ *)
+ if test "X$my_pic_p" != Xno; then
+ pic_flag_for_symtable=" $pic_flag"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ symtab_cflags=
+ for arg in $LTCFLAGS; do
+ case $arg in
+ -pie | -fpie | -fPIE) ;;
+ *) symtab_cflags="$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"'
+
+ # 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 "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ else
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ fi
+ ;;
+ *)
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "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 "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+}
+
+# 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.
+func_win32_libid ()
+{
+ $opt_debug
+ 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
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+ $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 |
+ $SED -n -e '
+ 1,100{
+ / I /{
+ s,.*,import,
+ p
+ q
+ }
+ }'`
+ 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_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ $opt_debug
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+ func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+ 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 ()
+{
+ $opt_debug
+ 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`
+ darwin_base_archive=`basename "$darwin_archive"`
+ 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 "$basename" | sort -u`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $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 | $NL2SP`
+ done
+
+ func_extract_archives_result="$my_oldobjs"
+}
+
+
+
+# func_emit_wrapper_part1 [arg=no]
+#
+# Emit the first part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part1 ()
+{
+ func_emit_wrapper_part1_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_part1_arg1=$1
+ fi
+
+ $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $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.
+Xsed='${SED} -e 1s/^X//'
+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
+ ECHO=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$ECHO works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$ECHO will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $ECHO "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+"
+}
+# end: func_emit_wrapper_part1
+
+# func_emit_wrapper_part2 [arg=no]
+#
+# Emit the second part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part2 ()
+{
+ func_emit_wrapper_part2_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_part2_arg1=$1
+ fi
+
+ $ECHO "\
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_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 \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+ $objdir ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; 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"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && 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 \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $ECHO "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $ECHO "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2* | *-cegcc*)
+ $ECHO "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $ECHO "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $ECHO "\
+ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+ exit 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\
+"
+}
+# end: func_emit_wrapper_part2
+
+
+# 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 in which it is stored is
+# the $objdir directory. This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+ func_emit_wrapper_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_arg1=$1
+ fi
+
+ # split this up so that func_emit_cwrapperexe_src
+ # can call each part independently.
+ func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
+ func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+# $build $host
+# mingw (msys) mingw [e.g. native]
+# cygwin mingw
+# *nix + wine mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin. Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+ func_to_host_path_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ case $build in
+ *mingw* ) # actually, msys
+ # awkward: cmd appends spaces to result
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_host_path_tmp1=`( cmd //c echo "$1" |\
+ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_host_path_tmp1=`cygpath -w "$1"`
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ * )
+ # Unfortunately, winepath does not exit with a non-zero
+ # error code, so we are forced to check the contents of
+ # stdout. On the other hand, if the command is not
+ # found, the shell will set an exit code of 127 and print
+ # *an error message* to stdout. So we must check for both
+ # error code of zero AND non-empty stdout, which explains
+ # the odd construction:
+ func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+ if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ else
+ # Allow warning below.
+ func_to_host_path_result=""
+ fi
+ ;;
+ esac
+ if test -z "$func_to_host_path_result" ; then
+ func_error "Could not determine host path corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback:
+ func_to_host_path_result="$1"
+ fi
+ ;;
+ esac
+ fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+# $build $host
+# mingw (msys) mingw [e.g. native]
+# cygwin mingw
+# *nix + wine mingw
+#
+# 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.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+ func_to_host_pathlist_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ # 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_to_host_pathlist_tmp2="$1"
+ # Once set for this call, this variable should not be
+ # reassigned. It is used in tha fallback case.
+ func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e 's|^:*||' -e 's|:*$||'`
+ case $build in
+ *mingw* ) # Actually, msys.
+ # Awkward: cmd appends spaces to result.
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
+ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ * )
+ # unfortunately, winepath doesn't convert pathlists
+ func_to_host_pathlist_result=""
+ func_to_host_pathlist_oldIFS=$IFS
+ IFS=:
+ for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+ IFS=$func_to_host_pathlist_oldIFS
+ if test -n "$func_to_host_pathlist_f" ; then
+ func_to_host_path "$func_to_host_pathlist_f"
+ if test -n "$func_to_host_path_result" ; then
+ if test -z "$func_to_host_pathlist_result" ; then
+ func_to_host_pathlist_result="$func_to_host_path_result"
+ else
+ func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
+ fi
+ fi
+ fi
+ IFS=:
+ done
+ IFS=$func_to_host_pathlist_oldIFS
+ ;;
+ esac
+ if test -z "$func_to_host_pathlist_result" ; then
+ func_error "Could not determine the host path(s) corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback. This may break if $1 contains DOS-style drive
+ # specifications. The fix is not to complicate the expression
+ # below, but for the user to provide a working wine installation
+ # with winepath so that path translation in the cross-to-mingw
+ # case works properly.
+ lt_replace_pathsep_nix_to_dos="s|:|;|g"
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+ $SED -e "$lt_replace_pathsep_nix_to_dos"`
+ fi
+ # Now, add the leading and trailing path separators back
+ case "$1" in
+ :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+ ;;
+ esac
+ case "$1" in
+ *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+}
+# end: func_to_host_pathlist
+
+# 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 <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "$SHELL $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+# include <io.h>
+# define HAVE_SETENV
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#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
+
+#ifdef _MSC_VER
+# define S_IXUSR _S_IEXEC
+# define stat _stat
+# ifndef _INTPTR_T_DEFINED
+# define intptr_t int
+# endif
+#endif
+
+#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 */
+
+#ifdef __CYGWIN__
+# define FOPEN_WB "wb"
+#endif
+
+#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 ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ (void) vfprintf (stderr, fmt, args);
+ va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+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_fatal (const char *message, ...);
+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_opt_process_env_set (const char *arg);
+void lt_opt_process_env_prepend (const char *arg);
+void lt_opt_process_env_append (const char *arg);
+int lt_split_name_value (const char *arg, char** name, char** value);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+
+static const char *script_text_part1 =
+EOF
+
+ func_emit_wrapper_part1 yes |
+ $SED -e 's/\([\\"]\)/\\\1/g' \
+ -e 's/^/ "/' -e 's/$/\\n"/'
+ echo ";"
+ cat <<EOF
+
+static const char *script_text_part2 =
+EOF
+ func_emit_wrapper_part2 yes |
+ $SED -e 's/\([\\"]\)/\\\1/g' \
+ -e 's/^/ "/' -e 's/$/\\n"/'
+ echo ";"
+
+ cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ func_to_host_pathlist "$temp_rpath"
+ cat <<EOF
+const char * LIB_PATH_VALUE = "$func_to_host_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * LIB_PATH_VALUE = "";
+EOF
+ fi
+
+ if test -n "$dllsearchpath"; then
+ func_to_host_pathlist "$dllsearchpath:"
+ cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE = "$func_to_host_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE = "";
+EOF
+ fi
+
+ if test "$fast_install" = yes; then
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+ else
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+ fi
+
+
+ cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH 5
+
+static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt = LTWRAPPER_OPTION_PREFIX "env-set";
+ /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt = LTWRAPPER_OPTION_PREFIX "env-prepend";
+ /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt = LTWRAPPER_OPTION_PREFIX "env-append";
+ /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int newargc;
+ char *tmp_pathspec;
+ char *actual_cwrapper_path;
+ char *actual_cwrapper_name;
+ char *target_name;
+ char *lt_argv_zero;
+ intptr_t rval = 127;
+
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ LTWRAPPER_DEBUGPRINTF (("(main) argv[0] : %s\n", argv[0]));
+ LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+ /* very simple arg parsing; don't want to rely on getopt */
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], dumpscript_opt) == 0)
+ {
+EOF
+ case "$host" in
+ *mingw* | *cygwin* )
+ # make stdout use "unix" line endings
+ echo " setmode(1,_O_BINARY);"
+ ;;
+ esac
+
+ cat <<"EOF"
+ printf ("%s", script_text_part1);
+ printf ("%s", script_text_part2);
+ return 0;
+ }
+ }
+
+ newargz = XMALLOC (char *, argc + 1);
+ tmp_pathspec = find_executable (argv[0]);
+ if (tmp_pathspec == NULL)
+ lt_fatal ("Couldn't find %s", argv[0]);
+ LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+ tmp_pathspec));
+
+ actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+ LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+ actual_cwrapper_path));
+ XFREE (tmp_pathspec);
+
+ actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+ strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+ /* wrapper name transforms */
+ strendzap (actual_cwrapper_name, ".exe");
+ tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+ XFREE (actual_cwrapper_name);
+ actual_cwrapper_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ /* target_name transforms -- use actual target program name; might have lt- prefix */
+ target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+ strendzap (target_name, ".exe");
+ tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+ XFREE (target_name);
+ target_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+ target_name));
+EOF
+
+ cat <<EOF
+ newargz[0] =
+ XMALLOC (char, (strlen (actual_cwrapper_path) +
+ strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+ strcpy (newargz[0], actual_cwrapper_path);
+ strcat (newargz[0], "$objdir");
+ strcat (newargz[0], "/");
+EOF
+
+ cat <<"EOF"
+ /* stop here, and copy so we don't have to do this twice */
+ tmp_pathspec = xstrdup (newargz[0]);
+
+ /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+ strcat (newargz[0], actual_cwrapper_name);
+
+ /* DO want the lt- prefix here if it exists, so use target_name */
+ lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+ XFREE (tmp_pathspec);
+ tmp_pathspec = NULL;
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ {
+ char* p;
+ while ((p = strchr (newargz[0], '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ }
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+ XFREE (target_name);
+ XFREE (actual_cwrapper_path);
+ XFREE (actual_cwrapper_name);
+
+ lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+ lt_setenv ("DUALCASE", "1"); /* for MSK sh */
+ lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+ newargc=0;
+ for (i = 1; i < argc; i++)
+ {
+ if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+ {
+ if (argv[i][env_set_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_set_opt_len + 1;
+ lt_opt_process_env_set (p);
+ }
+ else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_set (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_set_opt);
+ continue;
+ }
+ if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+ {
+ if (argv[i][env_prepend_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_prepend_opt_len + 1;
+ lt_opt_process_env_prepend (p);
+ }
+ else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_prepend_opt);
+ continue;
+ }
+ if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+ {
+ if (argv[i][env_append_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_append_opt_len + 1;
+ lt_opt_process_env_append (p);
+ }
+ else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_append (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_append_opt);
+ continue;
+ }
+ if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+ {
+ /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+ namespace, but it is not one of the ones we know about and
+ have already dealt with, above (inluding dump-script), then
+ report an error. Otherwise, targets might begin to believe
+ they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+ namespace. The first time any user complains about this, we'll
+ need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+ or a configure.ac-settable value.
+ */
+ lt_fatal ("Unrecognized option in %s namespace: '%s'",
+ ltwrapper_option_prefix, argv[i]);
+ }
+ /* otherwise ... */
+ newargz[++newargc] = xstrdup (argv[i]);
+ }
+ newargz[++newargc] = NULL;
+
+ LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+ for (i = 0; i < newargc; i++)
+ {
+ LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ /* execv doesn't actually work on mingw as expected on unix */
+ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+ if (rval == -1)
+ {
+ /* failed to start process */
+ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+ return 127;
+ }
+ return rval;
+EOF
+ ;;
+ *)
+ cat <<"EOF"
+ execv (lt_argv_zero, newargz);
+ return rval; /* =127, but avoids unused variable warning */
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void *p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+ string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable (const char *path)
+{
+ struct stat st;
+
+ LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n",
+ path ? (*path ? path : "EMPTY!") : "NULL!"));
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 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;
+
+ LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n",
+ path ? (*path ? path : "EMPTY!") : "NULL!"));
+ 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];
+ int tmp_len;
+ char *concat_name;
+
+ LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n",
+ wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+ 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 = 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 ("getcwd failed");
+ 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 ("getcwd failed");
+ 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)
+ {
+ LTWRAPPER_DEBUGPRINTF (("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
+ {
+ char *errstr = strerror (errno);
+ lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+ }
+ }
+ XFREE (tmp_pathspec);
+
+ if (!has_symlinks)
+ {
+ return xstrdup (pathspec);
+ }
+
+ tmp_pathspec = realpath (pathspec, buf);
+ if (tmp_pathspec == 0)
+ {
+ lt_fatal ("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 (strcmp (str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+ const char *message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ int 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)
+ {
+ int orig_value_len = strlen (orig_value);
+ int 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;
+}
+
+int
+lt_split_name_value (const char *arg, char** name, char** value)
+{
+ const char *p;
+ int len;
+ if (!arg || !*arg)
+ return 1;
+
+ p = strchr (arg, (int)'=');
+
+ if (!p)
+ return 1;
+
+ *value = xstrdup (++p);
+
+ len = strlen (arg) - strlen (*value);
+ *name = XMALLOC (char, len);
+ strncpy (*name, arg, len-1);
+ (*name)[len - 1] = '\0';
+
+ return 0;
+}
+
+void
+lt_opt_process_env_set (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
+ }
+
+ lt_setenv (name, value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_prepend (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_append (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 1);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ int len = strlen (new_value);
+ while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[len-1] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $opt_debug
+ 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
+ # which 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 which 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
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ 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 "$build_libtool_libs" != yes && \
+ func_fatal_configuration "can not build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test "$build_libtool_libs" = yes && 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
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$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 "*) ;;
+ *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat "$save_arg"`
+ do
+# moreargs="$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 "$pic_object" = none &&
+ test "$non_pic_object" = none; 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 "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$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 "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; 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 "$pic_object" = none ; 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
+ ;;
+ 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 "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ weak)
+ weak_libs="$weak_libs $arg"
+ prev=
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$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
+ ;;
+
+ -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$arg" = "X-export-symbols"; 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"
+ dir=$func_stripname_result
+ if test -z "$dir"; 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
+ # 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 "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ ::) dllsearchpath=$dir;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
+ # 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$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs System.ltframework"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ 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)
+ compiler_flags="$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)
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) new_inherited_linker_flags="$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
+ ;;
+
+ -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_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$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"
+ arg="$arg $wl$func_quote_for_eval_result"
+ compiler_flags="$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"
+ arg="$arg $wl$func_quote_for_eval_result"
+ compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+ linker_flags="$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"
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -F/path gives path to uninstalled frameworks, gcc on darwin
+ # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$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 "$pic_object" = none &&
+ test "$non_pic_object" = none; 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 "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$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 "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; 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 "$pic_object" = none ; 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.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ 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 "$export_dynamic" = yes && 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 \"X\${$shlibpath_var}\" \| \$Xsed -e \'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\"
+
+ func_dirname "$output" "/" ""
+ output_objdir="$func_dirname_result$objdir"
+ # 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_duplicate_deps ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; 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 "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$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=no
+ 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 "$linkmode,$pass" = "lib,link"; 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 "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; 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 "$linkmode,$pass" = "lib,dlpreopen"; then
+ # Collect and forward deplibs of preopened libtool libs
+ for lib in $dlprefiles; do
+ # Ignore non-libtool-libs
+ dependency_libs=
+ case $lib in
+ *.la) func_source "$lib" ;;
+ esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) deplibs="$deplibs $deplib" ;;
+ esac
+ done
+ done
+ libs="$dlprefiles"
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ if test "$linkmode" = lib ; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ func_warning "\`-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test "$linkmode" = lib; 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 "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # 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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; 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=no
+ func_dirname "$lib" "" "."
+ ladir="$func_dirname_result"
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ *.ltframework)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test "$linkmode" = lib ; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ *)
+ func_warning "\`-L' is ignored for archives/objects"
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ func_stripname '-R' '' "$deplib"
+ dir=$func_stripname_result
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; 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=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $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."
+ else
+ $ECHO
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+ fi
+
+ # 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 "X$inherited_linker_flags" | $Xsed -e '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 "*) ;;
+ *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+ esac
+ done
+ fi
+ dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; 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.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; 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=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ 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 "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; 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.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$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 "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ func_warning "library \`$lib' was moved."
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && 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
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$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 "$pass" = dlpreopen; then
+ if test -z "$libdir" && test "$linkmode" = prog; then
+ func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$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" && \
+ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; 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 "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; 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_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { { test "$prefer_static_libs" = no ||
+ test "$prefer_static_libs,$installed" = "built,yes"; } ||
+ 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:"*) ;;
+ *) temp_rpath="$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 "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ 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 "$use_static_libs" = built && test "$installed" = yes; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc*)
+ # No point in relinking DLLs because paths are not encoded
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=no
+ ;;
+ *)
+ if test "$installed" = no; then
+ notinst_deplibs="$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 "$shouldnotlink" = yes && test "$pass" = link; then
+ $ECHO
+ if test "$linkmode" = prog; 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 "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; 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 "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$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*)
+ 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 "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; 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 can not
+ # 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 "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes &&
+ test "$hardcode_direct_absolute" = no; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ func_fatal_configuration "unsupported hardcode properties"
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; 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 "$hardcode_direct" != yes &&
+ test "$hardcode_minus_L" != yes &&
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes &&
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; 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
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; 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 "$linkmode" = prog; 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 "$hardcode_direct" != unsupported; 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 "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; 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 can not 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 "$module" = yes; 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 "$build_old_libs" = no; 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 "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; 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 "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if $opt_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ path=
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ 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
+ compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+ linker_flags="$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 "$pass" = link; then
+ if test "$linkmode" = "prog"; then
+ compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+ finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ fi
+ fi
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # 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 "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_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 "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # 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
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ fi
+ if test "$linkmode" = prog || test "$linkmode" = lib; then
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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"
+ objs="$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 "$module" = no && \
+ func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+ if test "$need_lib_prefix" != no; 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 "$deplibs_check_method" != pass_all; 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!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ test "$dlself" != no && \
+ func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test "$#" -gt 1 && \
+ func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+ install_libdir="$1"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; 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
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|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"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current"
+ ;;
+
+ irix | nonstopux)
+ if test "X$lt_irix_increment" = "Xno"; 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 "$loop" -ne 0; 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)
+ 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 "$loop" -ne 0; 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.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ qnx)
+ major=".$current"
+ versuffix=".$current"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ 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 "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ func_warning "undefined symbols not allowed in $host shared libraries"
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" "yes"
+ libobjs="$libobjs $symfileobj"
+ test "X$libobjs" = "X " && libobjs=
+
+ if test "$mode" != relink; 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 "X$precious_files_regex" != "X"; then
+ if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ test -n "$removelist" && \
+ func_show_eval "${RM}r \$removelist"
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
+ # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
+ # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "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
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; 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 "*) ;;
+ *) dlfiles="$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 "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$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 "$build_libtool_need_lc" = "yes"; then
+ deplibs="$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 <<EOF
+ int main() { return 0; }
+EOF
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ $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 I believe you do not have"
+ $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+ $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ ;;
+ *)
+ newdeplibs="$newdeplibs $i"
+ ;;
+ esac
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ $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 a test_compile did reveal that the linker did not use this one"
+ $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning! Library $i is needed by this library but I was not able to"
+ $ECHO "*** make it link in! You will probably need to install it or some"
+ $ECHO "*** library that it depends on before this library will be fully"
+ $ECHO "*** functional. Installing it before continuing would be even better."
+ fi
+ ;;
+ *)
+ newdeplibs="$newdeplibs $i"
+ ;;
+ esac
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method; shift
+ file_magic_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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$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
+ # 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 "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+ $SED -e 10q |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$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.
+ newdeplibs="$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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$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 \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+ $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$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.
+ newdeplibs="$newdeplibs $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
+ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+ done
+ fi
+ if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' |
+ $GREP . >/dev/null; then
+ $ECHO
+ if test "X$deplibs_check_method" = "Xnone"; 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
+ fi
+ ;;
+ 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 "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; 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 "$build_old_libs" = no; 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 "$allow_undefined" = no; 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 "$build_old_libs" = no; 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 "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ deplibs=`$ECHO "X $deplibs" | $Xsed -e '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 "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$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 "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $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"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$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"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$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 "$mode" != relink && 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
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$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"
+ delfiles="$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
+ if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+ # 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
+ fi
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || 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 cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ func_len " $cmd"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ func_show_eval "$cmd" 'exit $?'
+ 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 "X$skipped_export" != "X:"; 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 "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test "X$skipped_export" != "X:" && 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
+ delfiles="$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 "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec" &&
+ test "$compiler_needs_object" = yes &&
+ 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"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; 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 "$module" = yes && 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 "X$skipped_export" != "X:" &&
+ 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
+ output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+
+ # 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 "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+ output=${output_objdir}/${output_la}.lnkscript
+ func_verbose "creating GNU ld script: $output"
+ $ECHO 'INPUT (' > $output
+ for obj in $save_libobjs
+ do
+ $ECHO "$obj" >> $output
+ done
+ $ECHO ')' >> $output
+ delfiles="$delfiles $output"
+ elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+ output=${output_objdir}/${output_la}.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test "$compiler_needs_object" = yes; then
+ firstobj="$1 "
+ shift
+ fi
+ for obj
+ do
+ $ECHO "$obj" >> $output
+ done
+ delfiles="$delfiles $output"
+ output=$firstobj\"$file_list_spec$output\"
+ 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 "X$objlist" = X ||
+ 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 "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$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~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+ fi
+ delfiles="$delfiles $output"
+
+ else
+ output=
+ fi
+
+ if ${skipped_export-false}; then
+ 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
+ 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_silent || {
+ 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 "$mode" = relink; 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
+
+ if ${skipped_export-false}; then
+ 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 "X$include_expsyms" | $Xsed | $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
+ delfiles="$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
+ 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 "$module" = yes && 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"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ libobjs="$libobjs $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $opt_silent || {
+ 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 "$mode" = relink; 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 "$mode" = relink; 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 "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec and hope we can get by with
+ # turning comma into space..
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ 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
+
+ if test "$build_libtool_libs" != yes; then
+ 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
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; 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"
+
+ test "$preload" = yes \
+ && test "$dlopen_support" = unknown \
+ && test "$dlopen_self" = unknown \
+ && test "$dlopen_self_static" = unknown && \
+ 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 "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+ finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e '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 "$tagname" = CXX ; then
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+ 10.[0123])
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ ;;
+ esac
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e '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 "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$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 "*) ;;
+ *) finalize_rpath="$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"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$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;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) dllsearchpath="$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"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$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 "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=yes
+ case $host in
+ *cygwin* | *mingw* )
+ if test "$build_libtool_libs" != yes; then
+ wrappers_required=no
+ fi
+ ;;
+ *cegcc)
+ # Disable wrappers for cegcc, we are cross compiling anyway.
+ wrappers_required=no
+ ;;
+ *)
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ wrappers_required=no
+ fi
+ ;;
+ esac
+ if test "$wrappers_required" = no; then
+ # Replace the output file specification.
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e '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=$?'
+
+ # 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
+ fi
+
+ 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
+ rpath="$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
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; 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 "X$link_command" | $Xsed -e '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 $?'
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # 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"
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$ECHO "X$link_command" | $Xsed -e '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 $?'
+
+ # 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 "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $ECHO for shipping.
+ if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$ECHO "X$ECHO" | $Xsed -e "$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
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ if test "$preload" = yes && test -f "$symfileobj"; then
+ oldobjs="$oldobjs $symfileobj"
+ fi
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; 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"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ oldobjs="$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"
+ generated="$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"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+ 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
+ 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 "X$oldobjs" = "X" ; 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 "$build_old_libs" = yes && 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 "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test "$installed" = yes; 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"
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "\`$deplib' is not a valid libtool archive"
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$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"
+ newdlfiles="$newdlfiles $libdir/$name"
+ ;;
+ *) newdlfiles="$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"
+ newdlprefiles="$newdlprefiles $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
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $RM $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $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 can not 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 "$installed" = no && test "$need_relink" = yes; 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
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+ func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $opt_debug
+ RM="$nonopt"
+ files=
+ rmforce=
+ 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) RM="$RM $arg"; rmforce=yes ;;
+ -*) RM="$RM $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ test -z "$RM" && \
+ func_fatal_help "you must specify an RM program"
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ func_dirname "$file" "" "."
+ dir="$func_dirname_result"
+ if test "X$dir" = X.; then
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ func_basename "$file"
+ name="$func_basename_result"
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ 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 test "$rmforce" = yes; 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
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || 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 "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" &&
+ test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; 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
+ rmfiles="$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
+ rmfiles="$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
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ func_show_eval "$RM $rmfiles" 'exit_status=1'
+ done
+ objdir="$origobjdir"
+
+ # 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
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+ func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+ help="$generic_help"
+ func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+ func_fatal_help "invalid operation mode \`$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
+# in which 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:
+# vi:sw=2
+
diff --git a/chromium/third_party/tcmalloc/vendor/m4/ac_have_attribute.m4 b/chromium/third_party/tcmalloc/vendor/m4/ac_have_attribute.m4
new file mode 100644
index 00000000000..19f4021e990
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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 <stdlib.h>
+ 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/chromium/third_party/tcmalloc/vendor/m4/acx_nanosleep.m4 b/chromium/third_party/tcmalloc/vendor/m4/acx_nanosleep.m4
new file mode 100644
index 00000000000..1d443926fa2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/acx_nanosleep.m4
@@ -0,0 +1,35 @@
+# Check for support for nanosleep. It's defined in <time.h>, 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 <time.h>],
+ [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 <time.h>],
+ [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/chromium/third_party/tcmalloc/vendor/m4/acx_pthread.m4 b/chromium/third_party/tcmalloc/vendor/m4/acx_pthread.m4
new file mode 100644
index 00000000000..89d42c7449e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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 <stevenj@alum.mit.edu>
+dnl @version 2006-05-29
+dnl @license GPLWithACException
+dnl
+dnl Checks for GCC shared/pthread inconsistency based on work by
+dnl Marcin Owsiany <marcin@owsiany.pl>
+
+
+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.h>],
+ [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 <pthread.h>], [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.h>],
+ [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.h>],
+ [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.h>],
+ [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.h>],
+ [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.h>],
+ [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/chromium/third_party/tcmalloc/vendor/m4/compiler_characteristics.m4 b/chromium/third_party/tcmalloc/vendor/m4/compiler_characteristics.m4
new file mode 100644
index 00000000000..2b628930ec8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/compiler_characteristics.m4
@@ -0,0 +1,24 @@
+# Check compiler characteristics (e.g. type sizes, PRIxx macros, ...)
+
+# If types $1 and $2 are compatible, perform action $3
+AC_DEFUN([AC_TYPES_COMPATIBLE],
+ [AC_TRY_COMPILE([#include <stddef.h>], [$1 v1 = 0; $2 v2 = 0; return (&v1 - &v2)], $3)])
+
+define(AC_PRIUS_COMMENT, [printf format code for printing a size_t and ssize_t])
+
+AC_DEFUN([AC_COMPILER_CHARACTERISTICS],
+ [AC_CACHE_CHECK(AC_PRIUS_COMMENT, ac_cv_formatting_prius_prefix,
+ [AC_TYPES_COMPATIBLE(unsigned int, size_t,
+ ac_cv_formatting_prius_prefix=; ac_cv_prius_defined=1)
+ AC_TYPES_COMPATIBLE(unsigned long, size_t,
+ ac_cv_formatting_prius_prefix=l; ac_cv_prius_defined=1)
+ AC_TYPES_COMPATIBLE(unsigned long long, size_t,
+ ac_cv_formatting_prius_prefix=ll; ac_cv_prius_defined=1
+ )])
+ if test -z "$ac_cv_prius_defined"; then
+ ac_cv_formatting_prius_prefix=z;
+ fi
+ AC_DEFINE_UNQUOTED(PRIuS, "${ac_cv_formatting_prius_prefix}u", AC_PRIUS_COMMENT)
+ AC_DEFINE_UNQUOTED(PRIxS, "${ac_cv_formatting_prius_prefix}x", AC_PRIUS_COMMENT)
+ AC_DEFINE_UNQUOTED(PRIdS, "${ac_cv_formatting_prius_prefix}d", AC_PRIUS_COMMENT)
+])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/install_prefix.m4 b/chromium/third_party/tcmalloc/vendor/m4/install_prefix.m4
new file mode 100644
index 00000000000..ef33f42e6b6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/m4/libtool.m4 b/chromium/third_party/tcmalloc/vendor/m4/libtool.m4
new file mode 100644
index 00000000000..a3fee5360f6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/libtool.m4
@@ -0,0 +1,7377 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 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) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# 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 GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 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.58])dnl We use AC_INCLUDES_DEFAULT
+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
+
+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_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _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
+_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_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which 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
+_LT_PROG_ECHO_BACKSLASH
+
+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 "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# 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.
+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'
+
+# 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_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 "X$][$1" | $Xsed -e "$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:
+#
+# <var>='`$ECHO "X$<var>" | $Xsed -e "$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'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ 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 "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+ lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+ ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_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])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+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 <bug-libtool@gnu.org>."
+
+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) 2008 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.
+if test "$no_create" != yes; then
+ lt_cl_success=:
+ test "$silent" = yes &&
+ 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)
+fi
+])# 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 which 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
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_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 "X${COLLECT_NAMES+set}" != Xset; 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 '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ _LT_PROG_XSI_SHELLFNS
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$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'
+ TIMESTAMP='$TIMESTAMP'
+ 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)],
+ [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
+
+
+# _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([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)])
+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], [])
+
+
+# _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 test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; 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"
+ ])
+ 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[[91]]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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" != ":"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# 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
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ _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 "$lt_cv_apple_cc_single_mod" != "yes"; 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
+# -----------------------
+# 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.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+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 "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<_LT_EOF
+[$]*
+_LT_EOF
+ exit 0
+fi
+
+# 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
+
+if test -z "$lt_ECHO"; then
+ if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+ { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+ then
+ break
+ fi
+ done
+ fi
+
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+ else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$ECHO" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ ECHO='print -r'
+ elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ ECHO='printf %s\n'
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ ECHO=echo
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+ [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _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 "x$enable_libtool_lock" != xno && 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 which ABI we are using.
+ 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 which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; 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*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ 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*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|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"
+ ;;
+ ppc*-*linux*|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 x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ 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*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ 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_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+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
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_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_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"
+ # 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:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 x"[$]$2" = xyes; 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 "X$_lt_linker_boilerplate" | $Xsed -e '/^$/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 x"[$]$2" = xyes; 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;
+ ;;
+
+ 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;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # 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
+ ;;
+
+ 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"; 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"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+ = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 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 "$cross_compiling" = yes; 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 __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#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
+
+void fnord() { int i=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;
+ /* 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 "x$enable_dlopen" != xyes; 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
+ ])
+ ;;
+
+ *)
+ 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 "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && 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 "x$lt_cv_dlopen_self" = xyes; 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:__oline__: $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:__oline__: \$? = $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 "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/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 "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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 in which 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 "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+ # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; 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 "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+ test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; 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_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
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+ # 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 -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # 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`
+ 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"
+ else
+ 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; }
+}'`
+ sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+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
+ 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
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; 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
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.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}'
+ else
+ # 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'
+ fi
+ 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=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $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
+ 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,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ 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="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ 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
+ ;;
+ 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
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # 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
+ 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
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+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[[123]]*) 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} $libname${shared_ext}'
+ 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
+ ;;
+
+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
+ 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 "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ 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'
+ ;;
+
+interix[[3-9]]*)
+ 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'
+ 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 "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ 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
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-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'
+ 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
+ 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],
+ [shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+ # 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
+
+ # Append ld.so.conf contents 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;/^$/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
+ 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*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ 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
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+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
+ 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 "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ 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
+ 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=freebsd-elf
+ 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 "$with_gnu_ld" = yes; 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
+ 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
+ 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 "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_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([], [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], [2],
+ [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which 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 which 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
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+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
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _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
+# which 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
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ 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
+ ;;
+
+gnu*)
+ 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]) 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 Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-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*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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
+ ;;
+esac
+])
+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_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
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ 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 "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+ 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:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:__oline__: $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:__oline__: 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_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-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 "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ _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([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 "$host_cpu" = ia64; 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
+
+# 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/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
+ # and D for any global 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};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print 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
+
+ # 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
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && 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
+#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. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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_save_LIBS="$LIBS"
+ lt_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_save_LIBS"
+ CFLAGS="$lt_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 "$pipe_works" = yes; 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
+
+_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_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_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)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; 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 "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ 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'])
+ ;;
+ 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)=
+ ;;
+ 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 "$host_cpu" = ia64; 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
+ ;;
+ 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 "$host_cpu" != ia64; 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)
+ 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*)
+ # IBM XL 8.0 on PPC
+ _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*)
+ # 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 "$GCC" = yes; 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 "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ 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'])
+ ;;
+
+ 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'
+ ;;
+
+ 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
+ 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 "$host_cpu" = ia64; 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
+ ;;
+
+ 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'])
+ ;;
+
+ 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)
+ 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'
+ ;;
+ # 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'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # 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*)
+ # IBM XL C 8.0/Fortran 10.1 on PPC
+ _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)='-Wl,'
+ ;;
+ *Sun\ F*)
+ # 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)=''
+ ;;
+ 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*)
+ _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 which 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_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+
+#
+# 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])
+
+#
+# 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_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'
+ 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 AIX nm, but means don't demangle with GNU 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")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ linux* | k*bsd*-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
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+ 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_flag_spec_ld, $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 "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; 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 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 "$host_cpu" != ia64; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, 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 modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_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 <jrb3@best.com> 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(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/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+ 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 (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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
+ ;;
+
+ 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no
+ then
+ tmp_addflag=
+ 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; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # 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; $ECHO \"$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' ;;
+ xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ 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; $ECHO \"$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 "x$supports_anon_versioning" = xyes; 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
+ xlf*)
+ # 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)=
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; 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 $compiler_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 $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'
+ 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 $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
+ ;;
+
+ 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 can not
+*** 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 $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
+
+ if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU 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")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ 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,'
+
+ if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ 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_use_runtimelinking" = yes; 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
+ _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 "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; 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
+ _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'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ 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.
+ _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 `$ECHO "X$deplibs" | $Xsed -e '\''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(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ 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
+ ;;
+
+ freebsd1*)
+ _LT_TAGVAR(ld_shlibs, $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 -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 "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${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 "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $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 "$GCC" = yes -a "$with_gnu_ld" = no; 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 -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${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'
+ ;;
+ *)
+ _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 "$with_gnu_ld" = no; 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 "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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.
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ AC_LINK_IFELSE(int foo(void) {},
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+ )
+ LDFLAGS="$save_LDFLAGS"
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -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" && $ECHO "X-set_version $verstring" | $Xsed` -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
+ ;;
+
+ 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*)
+ 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _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'
+ ;;
+ esac
+ 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
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; 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" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "$GCC" = yes; 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}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "X-set_version $verstring" | $Xsed` -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 "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${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 ${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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; 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 "$_LT_TAGVAR(ld_shlibs, $1)" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $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_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _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*
+ AC_MSG_RESULT([$_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_flag_spec_ld], [1],
+ [[If ld is used when linking, 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([], [fix_srcfile_path], [1],
+ [Fix the shell variable $srcfile for the compiler])
+_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([], [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 which 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ 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 "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _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],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+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_flag_spec_ld, $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(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 "$_lt_caught_CXX_error" != yes; 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_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++"}
+ 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 "$GXX" = yes; 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 "$GXX" = yes; 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 "$with_gnu_ld" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -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 "\-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 "$host_cpu" = ia64; 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
+ # need to do runtime linking.
+ 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
+ ;;
+ 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,'
+
+ if test "$GXX" = yes; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ 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_use_runtimelinking" = yes; 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
+ _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 "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; 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
+ _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'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> 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*)
+ # _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(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 (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ 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
+ ;;
+
+ freebsd[[12]]*)
+ # 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
+ ;;
+
+ gnu*)
+ ;;
+
+ 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 $output_objdir/$soname = $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; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $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 $with_gnu_ld = no; 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; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; 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 -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -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)
+ 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; $ECHO "X$list" | $Xsed'
+
+ _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 | $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 | $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 | $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 | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 will 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; $ECHO \"$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=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ xl*)
+ # 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 "x$supports_anon_versioning" = xyes; 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; $ECHO \"$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='echo'
+
+ # 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
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ openbsd*)
+ 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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=echo
+ 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" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -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" && $ECHO "X-set_version $verstring" | $Xsed` -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 "X-set_version $verstring" | $Xsed` -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=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; 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" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${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 "\-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*)
+ # 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='echo'
+
+ # 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 "$GXX" = yes && test "$with_gnu_ld" = no; 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 -nostdlib $LDFLAGS $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 -nostdlib ${wl}-M $wl$lib.exp -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 "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $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 -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 "\-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 can NOT 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(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 "$_LT_TAGVAR(ld_shlibs, $1)" = no && 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
+ 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 "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _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
+# 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
+])
+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 $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p 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
+ ;;
+
+ *.$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 "$pre_test_object_deps_done" = no; 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
+
+# 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)=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+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_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+ _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _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_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_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_flag_spec_ld, $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(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 "$_lt_disable_F77" != yes; 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
+ CC=${F77-"f77"}
+ 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ 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 "$enable_shared" = yes || 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"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+ _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _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_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_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_flag_spec_ld, $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(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 "$_lt_disable_FC" != yes; 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
+ CC=${FC-"f95"}
+ 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ 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 "$enable_shared" = yes || 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"
+fi # test "$_lt_disable_FC" != yes
+
+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_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+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
+
+## 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"
+])# _LT_LANG_GCJ_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_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+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"
+])# _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 "x${GCJFLAGS+set}" = xset || 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_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_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 $lt_ac_count -gt 10 && 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],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+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_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# 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"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname 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).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname 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).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]+=\$[2]"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+ ;;
+ esac
+])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/ltoptions.m4 b/chromium/third_party/tcmalloc/vendor/m4/ltoptions.m4
new file mode 100644
index 00000000000..34151a3ba62
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/ltoptions.m4
@@ -0,0 +1,368 @@
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 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 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_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], [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [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_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],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+
+test -z "$pic_mode" && 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/chromium/third_party/tcmalloc/vendor/m4/ltsugar.m4 b/chromium/third_party/tcmalloc/vendor/m4/ltsugar.m4
new file mode 100644
index 00000000000..9000a057d31
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/ltsugar.m4
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 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/chromium/third_party/tcmalloc/vendor/m4/ltversion.m4 b/chromium/third_party/tcmalloc/vendor/m4/ltversion.m4
new file mode 100644
index 00000000000..f3c53098024
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004 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.
+
+# Generated from ltversion.in.
+
+# serial 3017 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.6b])
+m4_define([LT_PACKAGE_REVISION], [1.3017])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.6b'
+macro_revision='1.3017'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/lt~obsolete.m4 b/chromium/third_party/tcmalloc/vendor/m4/lt~obsolete.m4
new file mode 100644
index 00000000000..637bb2066c4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/lt~obsolete.m4
@@ -0,0 +1,92 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007 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 4 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_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
+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])])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/namespaces.m4 b/chromium/third_party/tcmalloc/vendor/m4/namespaces.m4
new file mode 100644
index 00000000000..d78dbe4cc2e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/namespaces.m4
@@ -0,0 +1,15 @@
+# Checks whether the compiler implements namespaces
+AC_DEFUN([AC_CXX_NAMESPACES],
+ [AC_CACHE_CHECK(whether the compiler implements namespaces,
+ ac_cv_cxx_namespaces,
+ [AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([namespace Outer {
+ namespace Inner { int i = 0; }}],
+ [using namespace Outer::Inner; return i;],
+ ac_cv_cxx_namespaces=yes,
+ ac_cv_cxx_namespaces=no)
+ AC_LANG_RESTORE])
+ if test "$ac_cv_cxx_namespaces" = yes; then
+ AC_DEFINE(HAVE_NAMESPACES, 1, [define if the compiler implements namespaces])
+ fi])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/pc_from_ucontext.m4 b/chromium/third_party/tcmalloc/vendor/m4/pc_from_ucontext.m4
new file mode 100644
index 00000000000..dee73a1d62a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/pc_from_ucontext.m4
@@ -0,0 +1,96 @@
+# 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 <sys/ucontext.h>, but it barfs if we #include it directly
+ # (this was fixed in later redhats). <ucontext.h> 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, [<sys/ucontext.h> 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_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.uc_regs->gregs[[PT_NIP]]" # Linux (ppc)
+ 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.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_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_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 <cygwin/signal.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ elif test "x$ac_cv_header_sys_ucontext_h" = xyes; then
+ AC_TRY_COMPILE([#define _GNU_SOURCE 1
+ #include <sys/ucontext.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ elif test "x$ac_cv_header_ucontext_h" = xyes; then
+ AC_TRY_COMPILE([#define _GNU_SOURCE 1
+ #include <ucontext.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ 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 <signal.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ fi
+ done
+ fi
+ if ! $pc_field_found; then
+ [$1]
+ fi])
diff --git a/chromium/third_party/tcmalloc/vendor/m4/program_invocation_name.m4 b/chromium/third_party/tcmalloc/vendor/m4/program_invocation_name.m4
new file mode 100644
index 00000000000..6161f66d2e6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/m4/stl_namespace.m4 b/chromium/third_party/tcmalloc/vendor/m4/stl_namespace.m4
new file mode 100644
index 00000000000..989ad80696a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/m4/stl_namespace.m4
@@ -0,0 +1,25 @@
+# We check what namespace stl code like vector expects to be executed in
+
+AC_DEFUN([AC_CXX_STL_NAMESPACE],
+ [AC_CACHE_CHECK(
+ what namespace STL code is in,
+ ac_cv_cxx_stl_namespace,
+ [AC_REQUIRE([AC_CXX_NAMESPACES])
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_COMPILE([#include <vector>],
+ [vector<int> t; return 0;],
+ ac_cv_cxx_stl_namespace=none)
+ AC_TRY_COMPILE([#include <vector>],
+ [std::vector<int> t; return 0;],
+ ac_cv_cxx_stl_namespace=std)
+ AC_LANG_RESTORE])
+ if test "$ac_cv_cxx_stl_namespace" = none; then
+ AC_DEFINE(STL_NAMESPACE,,
+ [the namespace where STL code like vector<> is defined])
+ fi
+ if test "$ac_cv_cxx_stl_namespace" = std; then
+ AC_DEFINE(STL_NAMESPACE,std,
+ [the namespace where STL code like vector<> is defined])
+ fi
+])
diff --git a/chromium/third_party/tcmalloc/vendor/missing b/chromium/third_party/tcmalloc/vendor/missing
new file mode 100644
index 00000000000..1c8ff7049d8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# 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
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ 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
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/mkinstalldirs b/chromium/third_party/tcmalloc/vendor/mkinstalldirs
new file mode 100644
index 00000000000..ef7e16fdafe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/mkinstalldirs
@@ -0,0 +1,161 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2006-05-11.19
+
+# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+IFS=" "" $nl"
+errstatus=0
+dirmode=
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake@gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage"
+ exit $?
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --version)
+ echo "$0 $scriptversion"
+ exit $?
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error. This is a problem when calling mkinstalldirs
+# from a parallel make. We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
+case $dirmode in
+ '')
+ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ test -d ./-p && rmdir ./-p
+ test -d ./--version && rmdir ./--version
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+ test ! -d ./--version; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ else
+ # Clean up after NextStep and OpenStep mkdir.
+ for d in ./-m ./-p ./--version "./$dirmode";
+ do
+ test -d $d && rmdir $d
+ done
+ fi
+ ;;
+esac
+
+for file
+do
+ case $file in
+ /*) pathcomp=/ ;;
+ *) pathcomp= ;;
+ esac
+ oIFS=$IFS
+ IFS=/
+ set fnord $file
+ shift
+ IFS=$oIFS
+
+ for d
+ do
+ test "x$d" = x && continue
+
+ pathcomp=$pathcomp$d
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp=$pathcomp/
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb.sh b/chromium/third_party/tcmalloc/vendor/packages/deb.sh
new file mode 100644
index 00000000000..31b423c12fa
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/deb/README b/chromium/third_party/tcmalloc/vendor/packages/deb/README
new file mode 100644
index 00000000000..57becfda757
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/deb/changelog b/chromium/third_party/tcmalloc/vendor/packages/deb/changelog
new file mode 100644
index 00000000000..dad1d5f30e3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/changelog
@@ -0,0 +1,196 @@
+gperftools (2.0-1) unstable; urgency=low
+
+ * New upstream release.
+ * Package renamed from google-perftools to gperftools.
+
+ -- Google Inc. and others <google-perftools@googlegroups.com> Fri, 03 Feb 2012 15:40:45 -0800
+
+google-perftools (1.10-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 31 Jan 2012 10:43:50 -0800
+
+google-perftools (1.9-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 22 Dec 2011 16:22:45 -0800
+
+google-perftools (1.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 15 Jul 2011 16:10:51 -0700
+
+google-perftools (1.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 04 Feb 2011 15:54:31 -0800
+
+google-perftools (1.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 05 Aug 2010 12:48:03 -0700
+
+google-perftools (1.5-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 19 Jan 2010 14:46:12 -0800
+
+google-perftools (1.4-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 10 Sep 2009 13:51:15 -0700
+
+google-perftools (1.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 09 Jun 2009 18:19:06 -0700
+
+google-perftools (1.2-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 17 Apr 2009 16:40:48 -0700
+
+google-perftools (1.1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Wed, 11 Mar 2009 11:25:34 -0700
+
+google-perftools (1.0-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 06 Jan 2009 13:58:56 -0800
+
+google-perftools (1.0rc1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 11 Dec 2008 16:01:32 -0800
+
+google-perftools (0.99.1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Sat, 20 Sep 2008 09:37:18 -0700
+
+google-perftools (0.99-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 18 Sep 2008 16:00:27 -0700
+
+google-perftools (0.98-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Mon, 09 Jun 2008 16:47:03 -0700
+
+google-perftools (0.97-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Mon, 21 Apr 2008 15:20:52 -0700
+
+google-perftools (0.96-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 18 Mar 2008 14:30:44 -0700
+
+google-perftools (0.95-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 12 Feb 2008 12:28:32 -0800
+
+google-perftools (0.94-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 29 Nov 2007 07:59:43 -0800
+
+google-perftools (0.93-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 17 Aug 2007 12:32:56 -0700
+
+google-perftools (0.92-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Tue, 17 Jul 2007 22:26:27 -0700
+
+google-perftools (0.91-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Wed, 18 Apr 2007 16:43:55 -0700
+
+google-perftools (0.90-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 13 Apr 2007 14:50:51 -0700
+
+google-perftools (0.8-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Wed, 14 Jun 2006 15:11:14 -0700
+
+google-perftools (0.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 13 Apr 2006 20:59:09 -0700
+
+google-perftools (0.6-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 27 Jan 2006 14:04:27 -0800
+
+google-perftools (0.5-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Mon, Nov 14 17:28:59 2005 -0800
+
+google-perftools (0.4-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Wed, 26 Oct 2005 15:19:16 -0700
+
+google-perftools (0.3-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Fri, 24 Jun 2005 18:02:26 -0700
+
+google-perftools (0.2-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> 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. <opensource@google.com> Fri, 11 Mar 2005 08:07:33 -0800
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb/compat b/chromium/third_party/tcmalloc/vendor/packages/deb/compat
new file mode 100644
index 00000000000..b8626c4cff2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/compat
@@ -0,0 +1 @@
+4
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb/control b/chromium/third_party/tcmalloc/vendor/packages/deb/control
new file mode 100644
index 00000000000..a5535946e79
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/control
@@ -0,0 +1,25 @@
+Source: gperftools
+Priority: optional
+Maintainer: Google Inc. and others <google-perftools@googlegroups.com>
+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/chromium/third_party/tcmalloc/vendor/packages/deb/copyright b/chromium/third_party/tcmalloc/vendor/packages/deb/copyright
new file mode 100644
index 00000000000..1a11eb73ca4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/copyright
@@ -0,0 +1,35 @@
+This package was debianized by Craig Silverstein <google-perftools@googlegroups.com>
+on Fri, 03 Feb 2012 15:40:45 -0800.
+
+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.
+
+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/chromium/third_party/tcmalloc/vendor/packages/deb/docs b/chromium/third_party/tcmalloc/vendor/packages/deb/docs
new file mode 100644
index 00000000000..df891c9627b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/docs
@@ -0,0 +1,47 @@
+AUTHORS
+COPYING
+ChangeLog
+INSTALL
+NEWS
+README
+TODO
+doc/cpuprofile.html
+doc/cpuprofile-fileformat.html
+doc/designstyle.css
+doc/heap-example1.png
+doc/heap_checker.html
+doc/heapprofile.html
+doc/index.html
+doc/overview.gif
+doc/pageheap.gif
+doc/pprof-test-big.gif
+doc/pprof-test.gif
+doc/pprof-vsnprintf-big.gif
+doc/pprof-vsnprintf.gif
+doc/pprof.1
+doc/pprof_remote_servers.html
+doc/spanmap.gif
+doc/t-test1.times.txt
+doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
+doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
+doc/tcmalloc-opspersec.vs.size.1.threads.png
+doc/tcmalloc-opspersec.vs.size.12.threads.png
+doc/tcmalloc-opspersec.vs.size.16.threads.png
+doc/tcmalloc-opspersec.vs.size.2.threads.png
+doc/tcmalloc-opspersec.vs.size.20.threads.png
+doc/tcmalloc-opspersec.vs.size.3.threads.png
+doc/tcmalloc-opspersec.vs.size.4.threads.png
+doc/tcmalloc-opspersec.vs.size.5.threads.png
+doc/tcmalloc-opspersec.vs.size.8.threads.png
+doc/tcmalloc.html
+doc/threadheap.gif
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
new file mode 100644
index 00000000000..8f883479be8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
new file mode 100644
index 00000000000..e863529f3c8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
new file mode 100644
index 00000000000..14f5b95d7f4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
@@ -0,0 +1,2 @@
+usr/lib
+usr/bin
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
new file mode 100644
index 00000000000..047eed5c691
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
new file mode 100644
index 00000000000..08d1476b873
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
@@ -0,0 +1 @@
+doc/pprof.1
diff --git a/chromium/third_party/tcmalloc/vendor/packages/deb/rules b/chromium/third_party/tcmalloc/vendor/packages/deb/rules
new file mode 100644
index 00000000000..f520befd259
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/packages/rpm.sh b/chromium/third_party/tcmalloc/vendor/packages/rpm.sh
new file mode 100644
index 00000000000..448a0327f2a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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 <package name> <package version>" 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/chromium/third_party/tcmalloc/vendor/packages/rpm/rpm.spec b/chromium/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
new file mode 100644
index 00000000000..bb9a4ee8d0a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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: Google Inc. and others
+Packager: Google Inc. and others <google-perftools@googlegroups.com>
+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 <opensource@google.com>
+ - 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 <opensource@google.com>
+ - 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/chromium/third_party/tcmalloc/vendor/src/addressmap-inl.h b/chromium/third_party/tcmalloc/vendor/src/addressmap-inl.h
new file mode 100644
index 00000000000..b122f17b857
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/addressmap-inl.h
@@ -0,0 +1,421 @@
+// 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 <stddef.h>
+#include <string.h>
+#if defined HAVE_STDINT_H
+#include <stdint.h> // to get uint16_t (ISO naming madness)
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h> // another place uint16_t might be defined
+#else
+#include <sys/types.h> // 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 Value>
+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 <key,value> 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<class Type>
+ 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<uint32_t>(x) * kHashMultiplier;
+ return static_cast<int>(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<Cluster>(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 <class T> T* New(int num) {
+ void* ptr = (*alloc_)(sizeof(Object) + num*sizeof(T));
+ memset(ptr, 0, sizeof(Object) + num*sizeof(T));
+ Object* obj = reinterpret_cast<Object*>(ptr);
+ obj->next = allocated_;
+ allocated_ = obj;
+ return reinterpret_cast<T*>(reinterpret_cast<Object*>(ptr) + 1);
+ }
+};
+
+// More implementation details follow:
+
+template <class Value>
+AddressMap<Value>::AddressMap(Allocator alloc, DeAllocator dealloc)
+ : free_(NULL),
+ alloc_(alloc),
+ dealloc_(dealloc),
+ allocated_(NULL) {
+ hashtable_ = New<Cluster*>(kHashSize);
+}
+
+template <class Value>
+AddressMap<Value>::~AddressMap() {
+ // De-allocate all of the objects we allocated
+ for (Object* obj = allocated_; obj != NULL; /**/) {
+ Object* next = obj->next;
+ (*dealloc_)(obj);
+ obj = next;
+ }
+}
+
+template <class Value>
+inline const Value* AddressMap<Value>::Find(Key key) const {
+ return const_cast<AddressMap*>(this)->FindMutable(key);
+}
+
+template <class Value>
+inline Value* AddressMap<Value>::FindMutable(Key key) {
+ const Number num = reinterpret_cast<Number>(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 <class Value>
+void AddressMap<Value>::Insert(Key key, Value value) {
+ const Number num = reinterpret_cast<Number>(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<Entry>(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 <class Value>
+bool AddressMap<Value>::FindAndRemove(Key key, Value* removed_value) {
+ const Number num = reinterpret_cast<Number>(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 <class Value>
+const Value* AddressMap<Value>::FindInside(ValueSizeFunc size_func,
+ size_t max_size,
+ Key key,
+ Key* res_key) {
+ const Number key_num = reinterpret_cast<Number>(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<Number>(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 <class Value>
+template <class Type>
+inline void AddressMap<Value>::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/chromium/third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h b/chromium/third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h
new file mode 100644
index 00000000000..a47e6bbd2b1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h
@@ -0,0 +1,79 @@
+// 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_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/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h
new file mode 100644
index 00000000000..4acb76afd75
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h
@@ -0,0 +1,235 @@
+// 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 and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
+#define BASE_ATOMICOPS_INTERNALS_ARM_GENERIC_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ for (;;) {
+ // Atomic exchange the old value with an incremented one.
+ Atomic32 old_value = *ptr;
+ Atomic32 new_value = old_value + increment;
+ if (pLinuxKernelCmpxchg(old_value, new_value,
+ const_cast<Atomic32*>(ptr)) == 0) {
+ // The exchange took place as expected.
+ return new_value;
+ }
+ // Otherwise, *ptr changed mid-loop and we need to retry.
+ }
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+
+// 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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ return 0;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NotImplementedFatalError("NoBarrier_Store");
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NotImplementedFatalError("Acquire_Store64");
+}
+
+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 Release_Load(volatile const Atomic64* ptr) {
+ NotImplementedFatalError("Atomic64 Release_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/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h
new file mode 100644
index 00000000000..8d5b9b5342f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h
@@ -0,0 +1,368 @@
+// 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 <stdio.h>
+#include <stdlib.h>
+#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 Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 tmp, res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrex %1, [%2]\n"
+ "add %1, %1, %3\n"
+ "strex %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (tmp), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+inline void MemoryBarrier() {
+ __asm__ __volatile__("dmb" : : : "memory");
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 tmp, res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrex %1, [%2]\n"
+ "add %1, %1, %3\n"
+ "dmb\n"
+ "strex %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (tmp), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ int store_failed;
+ Atomic64 res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrexd %1, [%2]\n"
+ "adds %Q1, %Q1, %Q3\n"
+ "adc %R1, %R1, %R3\n"
+ "strexd %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (store_failed), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ int store_failed;
+ Atomic64 res;
+ __asm__ __volatile__(
+ "1:\n"
+ "ldrexd %1, [%2]\n"
+ "adds %Q1, %Q1, %Q3\n"
+ "adc %R1, %R1, %R3\n"
+ "dmb\n"
+ "strexd %0, %1, [%2]\n"
+ "teq %0, #0\n"
+ "bne 1b"
+ : "=&r" (store_failed), "=&r"(res)
+ : "r" (ptr), "r"(increment)
+ : "cc", "memory");
+ return res;
+}
+
+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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ 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 Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+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/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h
new file mode 100644
index 00000000000..7e49560dca1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h
@@ -0,0 +1,416 @@
+/* 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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+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<Atomic32*>(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<Atomic32*>(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\
+ cmpw 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<Atomic64*>(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<Atomic64*>(ptr)));
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
+}
+
+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<Atomic64*>(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<Atomic64*>(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 Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+ // 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();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+ // 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();
+ return *ptr;
+}
+
+#ifdef __PPC64__
+
+// 64-bit Versions.
+
+inline void NoBarrier_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+ // 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();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+ // 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();
+ return *ptr;
+}
+
+#endif
+
+} // namespace base::subtle
+} // namespace base
+
+#endif // BASE_ATOMICOPS_INTERNALS_LINUXPPC_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h
new file mode 100644
index 00000000000..430b9ee0bb4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h
@@ -0,0 +1,359 @@
+/* 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 <libkern/OSAtomic.h>
+
+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<Atomic32*>(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<Atomic32*>(ptr)));
+ return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr,
+ Atomic32 increment) {
+ return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
+}
+
+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<Atomic32*>(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 Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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<Atomic64*>(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<Atomic64*>(ptr)));
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr,
+ Atomic64 increment) {
+ return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
+}
+
+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<Atomic64*>(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 Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64 *ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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 Release_Load(volatile const Atomic64 *ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+#endif // __LP64__
+
+} // namespace base::subtle
+} // namespace base
+
+#endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h
new file mode 100644
index 00000000000..bd42c820ab0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h
@@ -0,0 +1,501 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#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, <windows.h> and <intrin.h> 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<LONG*>(ptr), newval, oldval);
+}
+inline LONG FastInterlockedExchange(volatile LONG* ptr, LONG newval) {
+ return ::InterlockedExchange(const_cast<LONG*>(ptr), newval);
+}
+inline LONG FastInterlockedExchangeAdd(volatile LONG* ptr, LONG increment) {
+ return ::InterlockedExchangeAdd(const_cast<LONG*>(ptr), increment);
+}
+
+#elif _MSC_VER >= 1400 // intrinsics didn't work so well before MSVC 8.0
+// Unfortunately, in some environments, <windows.h> and <intrin.h>
+// 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<volatile LONG*>(ptr),
+ static_cast<LONG>(new_value),
+ static_cast<LONG>(old_value));
+ return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ LONG result = FastInterlockedExchange(
+ reinterpret_cast<volatile LONG*>(ptr),
+ static_cast<LONG>(new_value));
+ return static_cast<Atomic32>(result);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return FastInterlockedExchangeAdd(
+ reinterpret_cast<volatile LONG*>(ptr),
+ static_cast<LONG>(increment)) + increment;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+} // 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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+// 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<PVOID*>(ptr),
+ newval, oldval);
+}
+inline PVOID FastInterlockedExchangePointer(volatile PVOID* ptr, PVOID newval) {
+ return ::InterlockedExchangePointer(const_cast<PVOID*>(ptr), newval);
+}
+inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr,
+ LONGLONG increment) {
+ return ::InterlockedExchangeAdd64(const_cast<LONGLONG*>(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<PVOID*>(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<PVOID*>(ptr), newval);
+}
+
+LONGLONG _InterlockedExchangeAdd64(volatile LONGLONG* ptr, LONGLONG increment);
+#pragma intrinsic(_InterlockedExchangeAdd64)
+inline LONGLONG FastInterlockedExchangeAdd64(volatile LONGLONG* ptr,
+ LONGLONG increment) {
+ return _InterlockedExchangeAdd64(const_cast<LONGLONG*>(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<volatile PVOID*>(ptr),
+ reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
+ return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ PVOID result = FastInterlockedExchangePointer(
+ reinterpret_cast<volatile PVOID*>(ptr),
+ reinterpret_cast<PVOID>(new_value));
+ return reinterpret_cast<Atomic64>(result);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return FastInterlockedExchangeAdd64(
+ reinterpret_cast<volatile LONGLONG*>(ptr),
+ static_cast<LONGLONG>(increment)) + increment;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+#if 0 // Not implemented
+ Atomic64 temp = increment;
+ __asm__ __volatile__(
+ "0:\n\t"
+ "movl (%3), %%ebx\n\t" // Move 64-bit increment into
+ "movl 4(%3), %%ecx\n\t" // ecx:ebx
+ "movl (%2), %%eax\n\t" // Read contents of ptr into
+ "movl 4(%2), %%edx\n\t" // edx:eax
+ "add %%eax, %%ebx\n\t" // sum => ecx:ebx
+ "adc %%edx, %%ecx\n\t" // edx:eax still has old *ptr
+ "lock; cmpxchg8b (%2)\n\t"// Attempt cmpxchg; if *ptr
+ "jnz 0b\n\t" // is no longer edx:eax, loop
+ : "=A"(temp), "+m"(*ptr)
+ : "D" (ptr), "S" (&increment)
+ : "memory", "%ebx", "%ecx");
+ // temp now contains the previous value of *ptr
+ return temp + increment;
+#else
+ NotImplementedFatalError("NoBarrier_AtomicIncrement");
+ return 0;
+#endif
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+#if 0 // Not implemented
+ Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return new_val;
+#else
+ NotImplementedFatalError("Barrier_AtomicIncrement");
+ return 0;
+#endif
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+#if 0 // Not implemented
+ __asm {
+ mov mm0, value; // Use mmx reg for 64-bit atomic moves
+ mov ptr, mm0;
+ emms; // Empty mmx state to enable FP registers
+ }
+#else
+ NotImplementedFatalError("NoBarrier_Store");
+#endif
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier in this implementation
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+#if 0 // Not implemented
+ Atomic64 value;
+ __asm {
+ mov mm0, ptr; // Use mmx reg for 64-bit atomic moves
+ mov value, mm0;
+ emms; // Empty mmx state to enable FP registers
+ }
+ return value;
+#else
+ NotImplementedFatalError("NoBarrier_Store");
+ return 0;
+#endif
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ Atomic64 value = NoBarrier_Load(ptr);
+ return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+#endif // defined(_WIN64) || defined(__MINGW64__)
+
+
+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/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc
new file mode 100644
index 00000000000..4f75d4724c0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc
@@ -0,0 +1,125 @@
+/* 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 <string.h>
+
+// 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, // bug can't exist before process spawns multiple threads
+ 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;
+ }
+
+ // Opteron Rev E has a bug in which on very rare occasions a locked
+ // instruction doesn't act as a read-acquire barrier if followed by a
+ // non-locked read-modify-write instruction. Rev F has this bug in
+ // pre-release versions, but not in versions released to customers,
+ // so we test only for Rev E, which is family 15, model 32..63 inclusive.
+ if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD
+ family == 15 &&
+ 32 <= model && model <= 63) {
+ AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
+ } else {
+ AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
+ }
+
+ // 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/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h
new file mode 100644
index 00000000000..c34aa5c08fc
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h
@@ -0,0 +1,428 @@
+/* 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_
+
+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_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
+ // after acquire compare-and-swap.
+ bool has_sse2; // Processor has SSE2.
+ bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
+};
+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 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 temp = increment;
+ __asm__ __volatile__("lock; xaddl %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now holds the old value of *ptr
+ return temp + increment;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ Atomic32 temp = increment;
+ __asm__ __volatile__("lock; xaddl %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now holds the old value of *ptr
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return temp + increment;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ 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");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+#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;
+ NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII
+ }
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
+ *ptr = value;
+ __asm__ __volatile__("mfence" : : : "memory");
+ } else {
+ NoBarrier_AtomicExchange(ptr, value);
+ // acts as a barrier on PIII
+ }
+}
+#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;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 temp = increment;
+ __asm__ __volatile__("lock; xaddq %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now contains the previous value of *ptr
+ return temp + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 temp = increment;
+ __asm__ __volatile__("lock; xaddq %0,%1"
+ : "+r" (temp), "+m" (*ptr)
+ : : "memory");
+ // temp now contains the previous value of *ptr
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return temp + increment;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 old_val, new_val;
+
+ do {
+ old_val = *ptr;
+ new_val = old_val + increment;
+ } while (__sync_val_compare_and_swap(ptr, old_val, new_val) != old_val);
+
+ return old_val + increment;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ Atomic64 new_val = NoBarrier_AtomicIncrement(ptr, increment);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ return 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 Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ NoBarrier_Store(ptr, value);
+ MemoryBarrier();
+}
+
+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;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return NoBarrier_Load(ptr);
+}
+
+#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);
+ if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
+ __asm__ __volatile__("lfence" : : : "memory");
+ }
+ 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/chromium/third_party/tcmalloc/vendor/src/base/atomicops.h b/chromium/third_party/tcmalloc/vendor/src/base/atomicops.h
new file mode 100644
index 00000000000..17e8a27f0ca
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/atomicops.h
@@ -0,0 +1,391 @@
+/* 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.
+//
+// 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 <config.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#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"
+
+// TODO(csilvers): match piii, not just __i386. Also, match k8
+#if 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(_WIN32)
+#include "base/atomicops-internals-windows.h"
+#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
+#include "base/atomicops-internals-x86.h"
+#elif defined(__linux__) && defined(__PPC__)
+#include "base/atomicops-internals-linuxppc.h"
+#else
+// Assume x86 for now. If you need to support a new architecture and
+// don't know how to implement atomic ops, you can probably get away
+// with using pthreads, since atomicops is only used by spinlock.h/cc
+//#error You need to implement atomic operations for this architecture
+#include "base/atomicops-internals-x86.h"
+#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<volatile AtomicWordCastType*>(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<volatile AtomicWordCastType*>(ptr), new_value);
+}
+
+// Atomically increment *ptr by "increment". Returns the new value of
+// *ptr with the increment applied. This routine implies no memory
+// barriers.
+inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
+ AtomicWord increment) {
+ return NoBarrier_AtomicIncrement(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
+}
+
+inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
+ AtomicWord increment) {
+ return Barrier_AtomicIncrement(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
+}
+
+// ------------------------------------------------------------------------
+// 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.
+// ------------------------------------------------------------------------
+inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
+ AtomicWord old_value,
+ AtomicWord new_value) {
+ return base::subtle::Acquire_CompareAndSwap(
+ reinterpret_cast<volatile AtomicWordCastType*>(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<volatile AtomicWordCastType*>(ptr),
+ old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
+ NoBarrier_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Acquire_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Release_Store(
+ reinterpret_cast<volatile AtomicWordCastType*>(ptr), value);
+}
+
+inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
+ return NoBarrier_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
+}
+
+inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Acquire_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(ptr));
+}
+
+inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Release_Load(
+ reinterpret_cast<volatile const AtomicWordCastType*>(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 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment);
+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 Acquire_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);
+Atomic32 Release_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 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
+
+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 Acquire_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);
+Atomic64 Release_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 Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
+ return base::subtle::Acquire_Store(ptr, 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);
+}
+
+inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
+ return base::subtle::Release_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 Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ base::subtle::Acquire_Store(ptr, 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);
+}
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ return base::subtle::Release_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 Acquire_Store(
+ volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 value) {
+ base::subtle::Acquire_Store(ptr, 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);
+}
+inline base::subtle::Atomic64 Release_Load(
+ volatile const base::subtle::Atomic64* ptr) {
+ return base::subtle::Release_Load(ptr);
+}
+
+#endif // BASE_HAS_ATOMIC64
+
+#endif // THREAD_ATOMICOPS_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/basictypes.h b/chromium/third_party/tcmalloc/vendor/src/base/basictypes.h
new file mode 100644
index 00000000000..75b7b5ae777
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/basictypes.h
@@ -0,0 +1,357 @@
+// 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 <config.h>
+#include <string.h> // for memcpy()
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // 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 <inttypes.h> // uint16_t might be here; PRId64 too.
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // to get uint16_t (ISO naming madness)
+#endif
+#include <sys/types.h> // 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 = ( ((( int64) 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<uintptr_t>(pthreadt)
+#else
+#define PRINTABLE_PTHREAD(pthreadt) pthreadt
+#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<bool(expr)>
+//
+// 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 <bool>
+struct CompileAssert {
+};
+
+#define COMPILE_ASSERT(expr, msg) \
+ typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+
+#define arraysize(a) (sizeof(a) / sizeof(*(a)))
+
+#define OFFSETOF_MEMBER(strct, field) \
+ (reinterpret_cast<char*>(&reinterpret_cast<strct*>(16)->field) - \
+ reinterpret_cast<char*>(16))
+
+// bit_cast<Dest,Source> implements the equivalent of
+// "*reinterpret_cast<Dest*>(&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 <class Dest, class Source>
+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;
+}
+
+#ifdef HAVE___ATTRIBUTE__
+# define ATTRIBUTE_WEAK __attribute__((weak))
+# define ATTRIBUTE_NOINLINE __attribute__((noinline))
+#else
+# define ATTRIBUTE_WEAK
+# define ATTRIBUTE_NOINLINE
+#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)))
+
+ // Weak section declaration to be used as a global declaration
+ // for ATTRIBUTE_SECTION_START|STOP(name) to compile and link
+ // even without functions with ATTRIBUTE_SECTION(name).
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name) \
+ extern char __start_##name[] ATTRIBUTE_WEAK; \
+ extern char __stop_##name[] ATTRIBUTE_WEAK
+# define INIT_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name) // no-op for ELF
+
+ // Return void* pointers to start/end of a section of code with functions
+ // having ATTRIBUTE_SECTION(name), or 0 if no such function exists.
+ // One must DECLARE_ATTRIBUTE_SECTION(name) for this to compile and link.
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#elif defined(HAVE___ATTRIBUTE__) && defined(__MACH__)
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section ("__TEXT, " #name)))
+
+#include <mach-o/getsect.h>
+#include <mach-o/dyld.h>
+class AssignAttributeStartEnd {
+ public:
+ AssignAttributeStartEnd(const char* name, char** pstart, char** pend) {
+ // Find out what dynamic library name is defined in
+ if (_dyld_present()) {
+ for (int i = _dyld_image_count() - 1; i >= 0; --i) {
+ const mach_header* hdr = _dyld_get_image_header(i);
+#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<void*>(__start_##name))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name))
+# define HAVE_ATTRIBUTE_SECTION_START 1
+
+#else // not HAVE___ATTRIBUTE__ && __ELF__, nor HAVE___ATTRIBUTE__ && __MACH__
+# define ATTRIBUTE_SECTION(name)
+# define DECLARE_ATTRIBUTE_SECTION_VARS(name)
+# define INIT_ATTRIBUTE_SECTION_VARS(name)
+# define DEFINE_ATTRIBUTE_SECTION_VARS(name)
+# define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0))
+# define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0))
+
+#endif // HAVE___ATTRIBUTE__ and __ELF__ or __MACH__
+
+#if defined(HAVE___ATTRIBUTE__) && (defined(__i386__) || defined(__x86_64__))
+# define CACHELINE_ALIGNED __attribute__((aligned(64)))
+#else
+# define CACHELINE_ALIGNED
+#endif // defined(HAVE___ATTRIBUTE__) && (__i386__ || __x86_64__)
+
+
+// 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/chromium/third_party/tcmalloc/vendor/src/base/commandlineflags.h b/chromium/third_party/tcmalloc/vendor/src/base/commandlineflags.h
new file mode 100644
index 00000000000..54bf94faf94
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/commandlineflags.h
@@ -0,0 +1,131 @@
+// 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 <config.h>
+#include <string>
+#include <string.h> // for memchr
+#include <stdlib.h> // 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
+
+// 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) \
+ (!getenv(envname) ? (dflt) : memchr("tTyY1\0", getenv(envname)[0], 6) != NULL)
+
+#define EnvToInt(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtol(getenv(envname), NULL, 10))
+
+#define EnvToInt64(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtoll(getenv(envname), NULL, 10))
+
+#define EnvToDouble(envname, dflt) \
+ (!getenv(envname) ? (dflt) : strtod(getenv(envname), NULL))
+
+#endif // BASE_COMMANDLINEFLAGS_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/cycleclock.h b/chromium/third_party/tcmalloc/vendor/src/base/cycleclock.h
new file mode 100644
index 00000000000..c704e1dae64
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/cycleclock.h
@@ -0,0 +1,163 @@
+// 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.
+
+// ----------------------------------------------------------------------
+// CycleClock
+// A CycleClock tells you the current time in Cycles. The "time"
+// is actually time since power-on. This is like time() but doesn't
+// involve a system call and is much more precise.
+//
+// NOTE: Not all cpu/platform/kernel combinations guarantee that this
+// clock increments at a constant rate or is synchronized across all logical
+// cpus in a system.
+//
+// Also, in some out of order CPU implementations, the CycleClock is not
+// serializing. So if you're trying to count at cycles granularity, your
+// data might be inaccurate due to out of order instruction execution.
+// ----------------------------------------------------------------------
+
+#ifndef GOOGLE_BASE_CYCLECLOCK_H_
+#define GOOGLE_BASE_CYCLECLOCK_H_
+
+#include "base/basictypes.h" // make sure we get the def for int64
+#include "base/arm_instruction_set_select.h"
+// base/sysinfo.h is really big and we don't want to include it unless
+// it is necessary.
+#if defined(__arm__) || defined(__mips__)
+# include "base/sysinfo.h"
+#endif
+#if defined(__MACH__) && defined(__APPLE__)
+# include <mach/mach_time.h>
+#endif
+// For MSVC, we want to use '_asm rdtsc' when possible (since it works
+// with even ancient MSVC compilers), and when not possible the
+// __rdtsc intrinsic, declared in <intrin.h>. Unfortunately, in some
+// environments, <windows.h> and <intrin.h> have conflicting
+// declarations of some other intrinsics, breaking compilation.
+// Therefore, we simply declare __rdtsc ourselves. See also
+// http://connect.microsoft.com/VisualStudio/feedback/details/262047
+#if defined(_MSC_VER) && !defined(_M_IX86)
+extern "C" uint64 __rdtsc();
+#pragma intrinsic(__rdtsc)
+#endif
+#if defined(ARMV3) || defined(__mips__)
+#include <sys/time.h>
+#endif
+
+// NOTE: only i386 and x86_64 have been well tested.
+// PPC, sparc, alpha, and ia64 are based on
+// http://peter.kuscsik.com/wordpress/?p=14
+// with modifications by m3b. See also
+// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
+struct CycleClock {
+ // This should return the number of cycles since power-on. Thread-safe.
+ static inline int64 Now() {
+#if defined(__MACH__) && defined(__APPLE__)
+ // this goes at the top because we need ALL Macs, regardless of
+ // architecture, to return the number of "mach time units" that
+ // have passed since startup. See sysinfo.cc where
+ // InitializeSystemInfo() sets the supposed cpu clock frequency of
+ // macs to the number of mach time units per second, not actual
+ // CPU clock frequency (which can change in the face of CPU
+ // frequency scaling). Also note that when the Mac sleeps, this
+ // counter pauses; it does not continue counting, nor does it
+ // reset to zero.
+ return mach_absolute_time();
+#elif defined(__i386__)
+ int64 ret;
+ __asm__ volatile ("rdtsc" : "=A" (ret) );
+ return ret;
+#elif defined(__x86_64__) || defined(__amd64__)
+ uint64 low, high;
+ __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
+ return (high << 32) | low;
+#elif defined(__powerpc__) || defined(__ppc__)
+ // This returns a time-base, which is not always precisely a cycle-count.
+ int64 tbl, tbu0, tbu1;
+ asm("mftbu %0" : "=r" (tbu0));
+ asm("mftb %0" : "=r" (tbl));
+ asm("mftbu %0" : "=r" (tbu1));
+ tbl &= -static_cast<int64>(tbu0 == tbu1);
+ // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage)
+ return (tbu1 << 32) | tbl;
+#elif defined(__sparc__)
+ int64 tick;
+ asm(".byte 0x83, 0x41, 0x00, 0x00");
+ asm("mov %%g1, %0" : "=r" (tick));
+ return tick;
+#elif defined(__ia64__)
+ int64 itc;
+ asm("mov %0 = ar.itc" : "=r" (itc));
+ return itc;
+#elif defined(_MSC_VER) && defined(_M_IX86)
+ // Older MSVC compilers (like 7.x) don't seem to support the
+ // __rdtsc intrinsic properly, so I prefer to use _asm instead
+ // when I know it will work. Otherwise, I'll use __rdtsc and hope
+ // the code is being compiled with a non-ancient compiler.
+ _asm rdtsc
+#elif defined(_MSC_VER)
+ return __rdtsc();
+#elif defined(ARMV3)
+#if defined(ARMV6) // V6 is the earliest arch that has a standard cyclecount
+ uint32 pmccntr;
+ uint32 pmuseren;
+ uint32 pmcntenset;
+ // Read the user mode perf monitor counter access permissions.
+ asm volatile ("mrc p15, 0, %0, c9, c14, 0" : "=r" (pmuseren));
+ if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
+ asm volatile ("mrc p15, 0, %0, c9, c12, 1" : "=r" (pmcntenset));
+ if (pmcntenset & 0x80000000ul) { // Is it counting?
+ asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (pmccntr));
+ // The counter is set up to count every 64th cycle
+ return static_cast<int64>(pmccntr) * 64; // Should optimize to << 6
+ }
+ }
+#endif
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
+ * CyclesPerSecond());
+#elif defined(__mips__)
+ // mips apparently only allows rdtsc for superusers, so we fall
+ // back to gettimeofday. It's possible clock_gettime would be better.
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return static_cast<int64>((tv.tv_sec + tv.tv_usec * 0.000001)
+ * CyclesPerSecond());
+#else
+// The soft failover to a generic implementation is automatic only for ARM.
+// For other platforms the developer is expected to make an attempt to create
+// a fast implementation and use generic version if nothing better is available.
+#error You need to define CycleTimer for your O/S and CPU
+#endif
+ }
+};
+
+
+#endif // GOOGLE_BASE_CYCLECLOCK_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.c b/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.c
new file mode 100644
index 00000000000..c8b61bed2d8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.c
@@ -0,0 +1,190 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "base/dynamic_annotations.h"
+
+#ifdef __GNUC__
+/* valgrind.h uses gcc extensions so it won't build with other compilers */
+# ifdef HAVE_VALGRIND_H /* prefer the user's copy if they have it */
+# include <valgrind.h>
+# else /* otherwise just use the copy that we have */
+# include "third_party/valgrind.h"
+# endif
+#endif
+
+/* Compiler-based ThreadSanitizer defines
+ DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
+ and provides its own definitions of the functions. */
+
+#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
+# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
+#endif
+
+/* Each function is empty and called (via a macro) only in debug mode.
+ The arguments are captured by dynamic tools at runtime. */
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1 \
+ && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
+
+void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock){}
+void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock){}
+void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w){}
+void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w){}
+void AnnotateBarrierInit(const char *file, int line,
+ const volatile void *barrier, long count,
+ long reinitialization_allowed) {}
+void AnnotateBarrierWaitBefore(const char *file, int line,
+ const volatile void *barrier) {}
+void AnnotateBarrierWaitAfter(const char *file, int line,
+ const volatile void *barrier) {}
+void AnnotateBarrierDestroy(const char *file, int line,
+ const volatile void *barrier) {}
+
+void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock){}
+void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv){}
+void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv){}
+void AnnotatePublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size){}
+void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size){}
+void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq){}
+void AnnotateNewMemory(const char *file, int line,
+ const volatile void *mem,
+ long size){}
+void AnnotateExpectRace(const char *file, int line,
+ const volatile void *mem,
+ const char *description){}
+void AnnotateBenignRace(const char *file, int line,
+ const volatile void *mem,
+ const char *description){}
+void AnnotateBenignRaceSized(const char *file, int line,
+ const volatile void *mem,
+ long size,
+ const char *description) {}
+void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu){}
+void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg){}
+void AnnotateThreadName(const char *file, int line,
+ const char *name){}
+void AnnotateIgnoreReadsBegin(const char *file, int line){}
+void AnnotateIgnoreReadsEnd(const char *file, int line){}
+void AnnotateIgnoreWritesBegin(const char *file, int line){}
+void AnnotateIgnoreWritesEnd(const char *file, int line){}
+void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
+void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg){}
+void AnnotateFlushState(const char *file, int line){}
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1
+ && DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
+
+#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
+
+static int GetRunningOnValgrind(void) {
+#ifdef RUNNING_ON_VALGRIND
+ if (RUNNING_ON_VALGRIND) return 1;
+#endif
+#ifdef _MSC_VER
+ /* Visual Studio can complain about getenv, so use a windows equivalent. */
+ char value[100] = "1"; /* something that is not "0" */
+ int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND",
+ value, sizeof(value));
+ /* value will remain "1" if the called failed for some reason. */
+ return (res > 0 && strcmp(value, "0") != 0);
+#else
+ /* TODO(csilvers): use GetenvBeforeMain() instead? Will need to
+ * change it to be extern "C".
+ */
+ char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
+ if (running_on_valgrind_str) {
+ return strcmp(running_on_valgrind_str, "0") != 0;
+ }
+ return 0;
+#endif
+}
+
+/* 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;
+ /* C doesn't have thread-safe initialization of statics, and we
+ don't want to depend on pthread_once here, so hack it. */
+ ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
+ if (local_running_on_valgrind == -1)
+ running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
+ return local_running_on_valgrind;
+}
+
+#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
+
+/* See the comments in dynamic_annotations.h */
+double ValgrindSlowdown(void) {
+ /* Same initialization hack as in RunningOnValgrind(). */
+ static volatile double slowdown = 0.0;
+ double local_slowdown = slowdown;
+ ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
+ if (RunningOnValgrind() == 0) {
+ return 1.0;
+ }
+ if (local_slowdown == 0.0) {
+ char *env = getenv("VALGRIND_SLOWDOWN");
+ slowdown = local_slowdown = env ? atof(env) : 50.0;
+ }
+ return local_slowdown;
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.h b/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.h
new file mode 100644
index 00000000000..4669315ced3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/dynamic_annotations.h
@@ -0,0 +1,627 @@
+/* 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_
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+# define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing condition variables such as CondVar,
+ using conditional critical sections (Await/LockWhen) and when constructing
+ user-defined synchronization mechanisms.
+
+ The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
+ be used to define happens-before arcs in user-defined synchronization
+ mechanisms: the race detector will infer an arc from the former to the
+ latter when they share the same argument pointer.
+
+ Example 1 (reference counting):
+
+ void Unref() {
+ ANNOTATE_HAPPENS_BEFORE(&refcount_);
+ if (AtomicDecrementByOne(&refcount_) == 0) {
+ ANNOTATE_HAPPENS_AFTER(&refcount_);
+ delete this;
+ }
+ }
+
+ Example 2 (message queue):
+
+ void MyQueue::Put(Type *e) {
+ MutexLock lock(&mu_);
+ ANNOTATE_HAPPENS_BEFORE(e);
+ PutElementIntoMyQueue(e);
+ }
+
+ Type *MyQueue::Get() {
+ MutexLock lock(&mu_);
+ Type *e = GetElementFromMyQueue();
+ ANNOTATE_HAPPENS_AFTER(e);
+ return e;
+ }
+
+ Note: when possible, please use the existing reference counting and message
+ queue implementations instead of inventing new ones. */
+
+ /* Report that wait on the condition variable at address "cv" has succeeded
+ and the lock at address "lock" is held. */
+ #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
+ AnnotateCondVarWait(__FILE__, __LINE__, cv, lock)
+
+ /* Report that wait on the condition variable at "cv" has succeeded. Variant
+ w/o lock. */
+ #define ANNOTATE_CONDVAR_WAIT(cv) \
+ AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL)
+
+ /* Report that we are about to signal on the condition variable at address
+ "cv". */
+ #define ANNOTATE_CONDVAR_SIGNAL(cv) \
+ AnnotateCondVarSignal(__FILE__, __LINE__, cv)
+
+ /* Report that we are about to signal_all on the condition variable at "cv". */
+ #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
+ AnnotateCondVarSignalAll(__FILE__, __LINE__, cv)
+
+ /* Annotations for user-defined synchronization mechanisms. */
+ #define ANNOTATE_HAPPENS_BEFORE(obj) ANNOTATE_CONDVAR_SIGNAL(obj)
+ #define ANNOTATE_HAPPENS_AFTER(obj) ANNOTATE_CONDVAR_WAIT(obj)
+
+ /* Report that the bytes in the range [pointer, pointer+size) are about
+ to be published safely. The race checker will create a happens-before
+ arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
+ subsequent accesses to this memory.
+ Note: this annotation may not work properly if the race detector uses
+ sampling, i.e. does not observe all memory accesses.
+ */
+ #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
+ AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
+
+ /* DEPRECATED. Don't use it. */
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
+ AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
+
+ /* DEPRECATED. Don't use it. */
+ #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
+ do { \
+ ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
+ ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
+ } while (0)
+
+ /* Instruct the tool to create a happens-before arc between mu->Unlock() and
+ mu->Lock(). This annotation may slow down the race detector and hide real
+ races. Normally it is used only when it would be difficult to annotate each
+ of the mutex's critical sections individually using the annotations above.
+ This annotation makes sense only for hybrid race detectors. For pure
+ happens-before detectors this is a no-op. For more details see
+ http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
+ #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
+ AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+
+ /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
+ #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
+ AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu)
+
+ /* -------------------------------------------------------------
+ Annotations useful when defining memory allocators, or when memory that
+ was protected in one way starts to be protected in another. */
+
+ /* Report that a new memory at "address" of size "size" has been allocated.
+ This might be used when the memory has been retrieved from a free list and
+ is about to be reused, or when a the locking discipline for a variable
+ changes. */
+ #define ANNOTATE_NEW_MEMORY(address, size) \
+ AnnotateNewMemory(__FILE__, __LINE__, address, size)
+
+ /* -------------------------------------------------------------
+ Annotations useful when defining FIFO queues that transfer data between
+ threads. */
+
+ /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
+ address "pcq" has been created. The ANNOTATE_PCQ_* annotations
+ should be used only for FIFO queues. For non-FIFO queues use
+ ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
+ #define ANNOTATE_PCQ_CREATE(pcq) \
+ AnnotatePCQCreate(__FILE__, __LINE__, pcq)
+
+ /* Report that the queue at address "pcq" is about to be destroyed. */
+ #define ANNOTATE_PCQ_DESTROY(pcq) \
+ AnnotatePCQDestroy(__FILE__, __LINE__, pcq)
+
+ /* Report that we are about to put an element into a FIFO queue at address
+ "pcq". */
+ #define ANNOTATE_PCQ_PUT(pcq) \
+ AnnotatePCQPut(__FILE__, __LINE__, pcq)
+
+ /* Report that we've just got an element from a FIFO queue at address "pcq". */
+ #define ANNOTATE_PCQ_GET(pcq) \
+ AnnotatePCQGet(__FILE__, __LINE__, pcq)
+
+ /* -------------------------------------------------------------
+ Annotations that suppress errors. It is usually better to express the
+ program's synchronization using the other annotations, but these can
+ be used when all else fails. */
+
+ /* Report that we may have a benign race at "pointer", with size
+ "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
+ point where "pointer" has been allocated, preferably close to the point
+ where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
+ #define ANNOTATE_BENIGN_RACE(pointer, description) \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
+ sizeof(*(pointer)), description)
+
+ /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
+ the memory range [address, address+size). */
+ #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
+
+ /* Request the analysis tool to ignore all reads in the current thread
+ until ANNOTATE_IGNORE_READS_END is called.
+ Useful to ignore intentional racey reads, while still checking
+ other reads and all writes.
+ See also ANNOTATE_UNPROTECTED_READ. */
+ #define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+ /* Stop ignoring reads. */
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
+ /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+ /* Stop ignoring writes. */
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+
+ /* Start ignoring all memory accesses (reads and writes). */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do {\
+ ANNOTATE_IGNORE_READS_BEGIN();\
+ ANNOTATE_IGNORE_WRITES_BEGIN();\
+ }while(0)\
+
+ /* Stop ignoring all memory accesses. */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do {\
+ ANNOTATE_IGNORE_WRITES_END();\
+ ANNOTATE_IGNORE_READS_END();\
+ }while(0)\
+
+ /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
+ This annotation could be useful if you want to skip expensive race analysis
+ during some period of program execution, e.g. during initialization. */
+ #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
+
+ /* -------------------------------------------------------------
+ Annotations useful for debugging. */
+
+ /* Request to trace every access to "address". */
+ #define ANNOTATE_TRACE_MEMORY(address) \
+ AnnotateTraceMemory(__FILE__, __LINE__, address)
+
+ /* Report the current thread name to a race detector. */
+ #define ANNOTATE_THREAD_NAME(name) \
+ AnnotateThreadName(__FILE__, __LINE__, name)
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing locks. They are not
+ normally needed by modules that merely use locks.
+ The "lock" argument is a pointer to the lock object. */
+
+ /* Report that a lock has been created at address "lock". */
+ #define ANNOTATE_RWLOCK_CREATE(lock) \
+ AnnotateRWLockCreate(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" is about to be destroyed. */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) \
+ AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" has been acquired.
+ is_w=1 for writer lock, is_w=0 for reader lock. */
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+
+ /* Report that the lock at address "lock" is about to be released. */
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+
+ /* -------------------------------------------------------------
+ Annotations useful when implementing barriers. They are not
+ normally needed by modules that merely use barriers.
+ The "barrier" argument is a pointer to the barrier object. */
+
+ /* Report that the "barrier" has been initialized with initial "count".
+ If 'reinitialization_allowed' is true, initialization is allowed to happen
+ multiple times w/o calling barrier_destroy() */
+ #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
+ AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \
+ reinitialization_allowed)
+
+ /* Report that we are about to enter barrier_wait("barrier"). */
+ #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
+ AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier)
+
+ /* Report that we just exited barrier_wait("barrier"). */
+ #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
+ AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier)
+
+ /* Report that the "barrier" has been destroyed. */
+ #define ANNOTATE_BARRIER_DESTROY(barrier) \
+ AnnotateBarrierDestroy(__FILE__, __LINE__, barrier)
+
+ /* -------------------------------------------------------------
+ Annotations useful for testing race detectors. */
+
+ /* Report that we expect a race on the variable at "address".
+ Use only in unit tests for a race detector. */
+ #define ANNOTATE_EXPECT_RACE(address, description) \
+ AnnotateExpectRace(__FILE__, __LINE__, address, description)
+
+ /* A no-op. Insert where you like to test the interceptors. */
+ #define ANNOTATE_NO_OP(arg) \
+ AnnotateNoOp(__FILE__, __LINE__, arg)
+
+ /* Force the race detector to flush its state. The actual effect depends on
+ * the implementation of the detector. */
+ #define ANNOTATE_FLUSH_STATE() \
+ AnnotateFlushState(__FILE__, __LINE__)
+
+
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+ #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
+ #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
+ #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
+ #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
+ #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
+ #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
+ #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
+ #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
+ #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
+ #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
+ #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
+ #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */
+ #define ANNOTATE_PCQ_CREATE(pcq) /* empty */
+ #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
+ #define ANNOTATE_PCQ_PUT(pcq) /* empty */
+ #define ANNOTATE_PCQ_GET(pcq) /* empty */
+ #define ANNOTATE_NEW_MEMORY(address, size) /* empty */
+ #define ANNOTATE_EXPECT_RACE(address, description) /* empty */
+ #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
+ #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
+ #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
+ #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
+ #define ANNOTATE_TRACE_MEMORY(arg) /* empty */
+ #define ANNOTATE_THREAD_NAME(name) /* empty */
+ #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_END() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_END() /* empty */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
+ #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
+ #define ANNOTATE_NO_OP(arg) /* empty */
+ #define ANNOTATE_FLUSH_STATE() /* empty */
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+/* Macro definitions for GCC attributes that allow static thread safety
+ analysis to recognize and use some of the dynamic annotations as
+ escape hatches.
+ TODO(lcwu): remove the check for __SUPPORT_DYN_ANNOTATION__ once the
+ default crosstool/GCC supports these GCC attributes. */
+
+#define ANNOTALYSIS_STATIC_INLINE
+#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY ;
+#define ANNOTALYSIS_IGNORE_READS_BEGIN
+#define ANNOTALYSIS_IGNORE_READS_END
+#define ANNOTALYSIS_IGNORE_WRITES_BEGIN
+#define ANNOTALYSIS_IGNORE_WRITES_END
+#define ANNOTALYSIS_UNPROTECTED_READ
+
+#if defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__)) && \
+ defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 0
+#define ANNOTALYSIS_ONLY 1
+#undef ANNOTALYSIS_STATIC_INLINE
+#define ANNOTALYSIS_STATIC_INLINE static inline
+#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+#define ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY { (void)file; (void)line; }
+#endif
+
+/* Only emit attributes when annotalysis is enabled. */
+#if defined(__SUPPORT_TS_ANNOTATION__) && defined(__SUPPORT_DYN_ANNOTATION__)
+#undef ANNOTALYSIS_IGNORE_READS_BEGIN
+#define ANNOTALYSIS_IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
+#undef ANNOTALYSIS_IGNORE_READS_END
+#define ANNOTALYSIS_IGNORE_READS_END __attribute__ ((ignore_reads_end))
+#undef ANNOTALYSIS_IGNORE_WRITES_BEGIN
+#define ANNOTALYSIS_IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
+#undef ANNOTALYSIS_IGNORE_WRITES_END
+#define ANNOTALYSIS_IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
+#undef ANNOTALYSIS_UNPROTECTED_READ
+#define ANNOTALYSIS_UNPROTECTED_READ __attribute__ ((unprotected_read))
+#endif
+
+#endif // defined(__GNUC__) && (!defined(SWIG)) && (!defined(__clang__))
+
+/* Use the macros above rather than using these functions directly. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+void AnnotateRWLockCreate(const char *file, int line,
+ const volatile void *lock);
+void AnnotateRWLockDestroy(const char *file, int line,
+ const volatile void *lock);
+void AnnotateRWLockAcquired(const char *file, int line,
+ const volatile void *lock, long is_w);
+void AnnotateRWLockReleased(const char *file, int line,
+ const volatile void *lock, long is_w);
+void AnnotateBarrierInit(const char *file, int line,
+ const volatile void *barrier, long count,
+ long reinitialization_allowed);
+void AnnotateBarrierWaitBefore(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateBarrierWaitAfter(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateBarrierDestroy(const char *file, int line,
+ const volatile void *barrier);
+void AnnotateCondVarWait(const char *file, int line,
+ const volatile void *cv,
+ const volatile void *lock);
+void AnnotateCondVarSignal(const char *file, int line,
+ const volatile void *cv);
+void AnnotateCondVarSignalAll(const char *file, int line,
+ const volatile void *cv);
+void AnnotatePublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotatePCQCreate(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQDestroy(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQPut(const char *file, int line,
+ const volatile void *pcq);
+void AnnotatePCQGet(const char *file, int line,
+ const volatile void *pcq);
+void AnnotateNewMemory(const char *file, int line,
+ const volatile void *address,
+ long size);
+void AnnotateExpectRace(const char *file, int line,
+ const volatile void *address,
+ const char *description);
+void AnnotateBenignRace(const char *file, int line,
+ const volatile void *address,
+ const char *description);
+void AnnotateBenignRaceSized(const char *file, int line,
+ const volatile void *address,
+ long size,
+ const char *description);
+void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
+ const volatile void *mu);
+void AnnotateTraceMemory(const char *file, int line,
+ const volatile void *arg);
+void AnnotateThreadName(const char *file, int line,
+ const char *name);
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreReadsBegin(const char *file, int line)
+ ANNOTALYSIS_IGNORE_READS_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreReadsEnd(const char *file, int line)
+ ANNOTALYSIS_IGNORE_READS_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreWritesBegin(const char *file, int line)
+ ANNOTALYSIS_IGNORE_WRITES_BEGIN ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+ANNOTALYSIS_STATIC_INLINE
+void AnnotateIgnoreWritesEnd(const char *file, int line)
+ ANNOTALYSIS_IGNORE_WRITES_END ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+void AnnotateEnableRaceDetection(const char *file, int line, int enable);
+void AnnotateNoOp(const char *file, int line,
+ const volatile void *arg);
+void AnnotateFlushState(const char *file, int line);
+
+/* 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);
+
+/* ValgrindSlowdown returns:
+ * 1.0, if (RunningOnValgrind() == 0)
+ * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
+ * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
+ This function can be used to scale timeout values:
+ EXAMPLE:
+ for (;;) {
+ DoExpensiveBackgroundTask();
+ SleepForSeconds(5 * ValgrindSlowdown());
+ }
+ */
+double ValgrindSlowdown(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
+
+ /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+
+ Instead of doing
+ ANNOTATE_IGNORE_READS_BEGIN();
+ ... = x;
+ ANNOTATE_IGNORE_READS_END();
+ one can use
+ ... = ANNOTATE_UNPROTECTED_READ(x); */
+ template <class T>
+ inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
+ ANNOTALYSIS_UNPROTECTED_READ {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+ }
+ /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
+ #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var ## _annotator { \
+ public: \
+ static_var ## _annotator() { \
+ ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
+ sizeof(static_var), \
+ # static_var ": " description); \
+ } \
+ }; \
+ static static_var ## _annotator the ## static_var ## _annotator;\
+ }
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+
+ #define ANNOTATE_UNPROTECTED_READ(x) (x)
+ #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
+
+#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+
+/* Annotalysis, a GCC based static analyzer, is able to understand and use
+ some of the dynamic annotations defined in this file. However, dynamic
+ annotations are usually disabled in the opt mode (to avoid additional
+ runtime overheads) while Annotalysis only works in the opt mode.
+ In order for Annotalysis to use these dynamic annotations when they
+ are disabled, we re-define these annotations here. Note that unlike the
+ original macro definitions above, these macros are expanded to calls to
+ static inline functions so that the compiler will be able to remove the
+ calls after the analysis. */
+
+#ifdef ANNOTALYSIS_ONLY
+
+ #undef ANNOTALYSIS_ONLY
+
+ /* Undefine and re-define the macros that the static analyzer understands. */
+ #undef ANNOTATE_IGNORE_READS_BEGIN
+ #define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_READS_END
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_WRITES_BEGIN
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_WRITES_END
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+
+ #undef ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ANNOTATE_IGNORE_READS_BEGIN(); \
+ ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ }while(0) \
+
+ #undef ANNOTATE_IGNORE_READS_AND_WRITES_END
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ }while(0) \
+
+ #if defined(__cplusplus)
+ #undef ANNOTATE_UNPROTECTED_READ
+ template <class T>
+ inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x)
+ ANNOTALYSIS_UNPROTECTED_READ {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+ }
+ #endif /* __cplusplus */
+
+#endif /* ANNOTALYSIS_ONLY */
+
+/* Undefine the macros intended only in this file. */
+#undef ANNOTALYSIS_STATIC_INLINE
+#undef ANNOTALYSIS_SEMICOLON_OR_EMPTY_BODY
+
+#endif /* BASE_DYNAMIC_ANNOTATIONS_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc b/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc
new file mode 100644
index 00000000000..2949343700d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc
@@ -0,0 +1,433 @@
+// 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 <stddef.h> // 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 <int N> 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 <class T>
+const T* GetTableElement(const ElfW(Ehdr) *ehdr,
+ ElfW(Off) table_offset,
+ ElfW(Word) element_size,
+ size_t index) {
+ return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr)
+ + table_offset
+ + index * element_size);
+}
+} // namespace
+
+const void *const ElfMemImage::kInvalidBase =
+ reinterpret_cast<const void *>(~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<ElfW(Phdr)>(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<const void *>(sym->st_value);
+ }
+ CHECK_LT(link_base_, sym->st_value);
+ return GetTableElement<char>(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<const char *>(version_definition);
+ version_definition =
+ reinterpret_cast<const ElfW(Verdef) *>(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<const ElfW(Verdaux) *>(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<uintptr_t>(base);
+ // Fake VDSO has low bit set.
+ const bool fake_vdso = ((base_as_uintptr_t & 1) != 0);
+ base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1);
+ const char *const base_as_char = reinterpret_cast<const char *>(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<const ElfW(Ehdr) *>(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<const char *>(link_base_);
+ ElfW(Dyn) *dynamic_entry =
+ reinterpret_cast<ElfW(Dyn) *>(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<ElfW(Word) *>(value);
+ break;
+ case DT_SYMTAB:
+ dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);
+ break;
+ case DT_STRTAB:
+ dynstr_ = reinterpret_cast<const char *>(value);
+ break;
+ case DT_VERSYM:
+ versym_ = reinterpret_cast<ElfW(Versym) *>(value);
+ break;
+ case DT_VERDEF:
+ verdef_ = reinterpret_cast<ElfW(Verdef) *>(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<const char *>(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<const ElfMemImage *>(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/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.h b/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.h
new file mode 100644
index 00000000000..6f1f09773a8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/elf_mem_image.h
@@ -0,0 +1,134 @@
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h> // 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 <stdlib.h>
+#include <link.h> // 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/chromium/third_party/tcmalloc/vendor/src/base/elfcore.h b/chromium/third_party/tcmalloc/vendor/src/base/elfcore.h
new file mode 100644
index 00000000000..34a96dec3d0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/elfcore.h
@@ -0,0 +1,385 @@
+/* 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, and MIPS on Linux.
+ * Porting to other related platforms should not be difficult.
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+ defined(__mips__)) && defined(__linux)
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <config.h>
+
+
+/* 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_ARCH_3__)
+ 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;
+#endif
+
+#if defined(__i386__) && defined(__GNUC__)
+ /* On x86 we provide an optimized version of the FRAME() macro, if the
+ * compiler supports a GCC-style asm() directive. This results in somewhat
+ * more accurate values for CPU registers.
+ */
+ typedef struct Frame {
+ struct i386_regs uregs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile ( \
+ "push %%ebp\n" \
+ "push %%ebx\n" \
+ "mov %%ebx,0(%%eax)\n" \
+ "mov %%ecx,4(%%eax)\n" \
+ "mov %%edx,8(%%eax)\n" \
+ "mov %%esi,12(%%eax)\n" \
+ "mov %%edi,16(%%eax)\n" \
+ "mov %%ebp,20(%%eax)\n" \
+ "mov %%eax,24(%%eax)\n" \
+ "mov %%ds,%%ebx\n" \
+ "mov %%ebx,28(%%eax)\n" \
+ "mov %%es,%%ebx\n" \
+ "mov %%ebx,32(%%eax)\n" \
+ "mov %%fs,%%ebx\n" \
+ "mov %%ebx,36(%%eax)\n" \
+ "mov %%gs,%%ebx\n" \
+ "mov %%ebx, 40(%%eax)\n" \
+ "call 0f\n" \
+ "0:pop %%ebx\n" \
+ "add $1f-0b,%%ebx\n" \
+ "mov %%ebx,48(%%eax)\n" \
+ "mov %%cs,%%ebx\n" \
+ "mov %%ebx,52(%%eax)\n" \
+ "pushf\n" \
+ "pop %%ebx\n" \
+ "mov %%ebx,56(%%eax)\n" \
+ "mov %%esp,%%ebx\n" \
+ "add $8,%%ebx\n" \
+ "mov %%ebx,60(%%eax)\n" \
+ "mov %%ss,%%ebx\n" \
+ "mov %%ebx,64(%%eax)\n" \
+ "pop %%ebx\n" \
+ "pop %%ebp\n" \
+ "1:" \
+ : : "a" (&f) : "memory"); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ (r) = (f).uregs; \
+ } while (0)
+#elif defined(__x86_64__) && defined(__GNUC__)
+ /* The FRAME and SET_FRAME macros for x86_64. */
+ typedef struct Frame {
+ struct i386_regs uregs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile ( \
+ "push %%rbp\n" \
+ "push %%rbx\n" \
+ "mov %%r15,0(%%rax)\n" \
+ "mov %%r14,8(%%rax)\n" \
+ "mov %%r13,16(%%rax)\n" \
+ "mov %%r12,24(%%rax)\n" \
+ "mov %%rbp,32(%%rax)\n" \
+ "mov %%rbx,40(%%rax)\n" \
+ "mov %%r11,48(%%rax)\n" \
+ "mov %%r10,56(%%rax)\n" \
+ "mov %%r9,64(%%rax)\n" \
+ "mov %%r8,72(%%rax)\n" \
+ "mov %%rax,80(%%rax)\n" \
+ "mov %%rcx,88(%%rax)\n" \
+ "mov %%rdx,96(%%rax)\n" \
+ "mov %%rsi,104(%%rax)\n" \
+ "mov %%rdi,112(%%rax)\n" \
+ "mov %%ds,%%rbx\n" \
+ "mov %%rbx,184(%%rax)\n" \
+ "mov %%es,%%rbx\n" \
+ "mov %%rbx,192(%%rax)\n" \
+ "mov %%fs,%%rbx\n" \
+ "mov %%rbx,200(%%rax)\n" \
+ "mov %%gs,%%rbx\n" \
+ "mov %%rbx,208(%%rax)\n" \
+ "call 0f\n" \
+ "0:pop %%rbx\n" \
+ "add $1f-0b,%%rbx\n" \
+ "mov %%rbx,128(%%rax)\n" \
+ "mov %%cs,%%rbx\n" \
+ "mov %%rbx,136(%%rax)\n" \
+ "pushf\n" \
+ "pop %%rbx\n" \
+ "mov %%rbx,144(%%rax)\n" \
+ "mov %%rsp,%%rbx\n" \
+ "add $16,%%ebx\n" \
+ "mov %%rbx,152(%%rax)\n" \
+ "mov %%ss,%%rbx\n" \
+ "mov %%rbx,160(%%rax)\n" \
+ "pop %%rbx\n" \
+ "pop %%rbp\n" \
+ "1:" \
+ : : "a" (&f) : "memory"); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ (f).uregs.fs_base = (r).fs_base; \
+ (f).uregs.gs_base = (r).gs_base; \
+ (r) = (f).uregs; \
+ } while (0)
+#elif defined(__ARM_ARCH_3__) && defined(__GNUC__)
+ /* ARM calling conventions are a little more tricky. A little assembly
+ * helps in obtaining an accurate snapshot of all registers.
+ */
+ typedef struct Frame {
+ struct arm_regs arm;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; \
+ do { \
+ long cpsr; \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ __asm__ volatile( \
+ "stmia %0, {r0-r15}\n" /* All integer regs */\
+ : : "r"(&f.arm) : "memory"); \
+ f.arm.uregs[16] = 0; \
+ __asm__ volatile( \
+ "mrs %0, cpsr\n" /* Condition code reg */\
+ : "=r"(cpsr)); \
+ f.arm.uregs[17] = cpsr; \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ /* Don't override the FPU status register. */\
+ /* Use the value obtained from ptrace(). This*/\
+ /* works, because our code does not perform */\
+ /* any FPU operations, itself. */\
+ long fps = (f).arm.uregs[16]; \
+ errno = (f).errno_; \
+ (r) = (f).arm; \
+ (r).uregs[16] = fps; \
+ } while (0)
+#elif defined(__mips__) && defined(__GNUC__)
+ typedef struct Frame {
+ struct mips_regs mips_regs;
+ int errno_;
+ pid_t tid;
+ } Frame;
+ #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; })
+ #define FRAME(f) Frame f = { 0 }; \
+ do { \
+ unsigned long hi, lo; \
+ register unsigned long pc __asm__("$31"); \
+ f.mips_regs.uregs[ 0] = MIPSREG( 0); \
+ f.mips_regs.uregs[ 1] = MIPSREG( 1); \
+ f.mips_regs.uregs[ 2] = MIPSREG( 2); \
+ f.mips_regs.uregs[ 3] = MIPSREG( 3); \
+ f.mips_regs.uregs[ 4] = MIPSREG( 4); \
+ f.mips_regs.uregs[ 5] = MIPSREG( 5); \
+ f.mips_regs.uregs[ 6] = MIPSREG( 6); \
+ f.mips_regs.uregs[ 7] = MIPSREG( 7); \
+ f.mips_regs.uregs[ 8] = MIPSREG( 8); \
+ f.mips_regs.uregs[ 9] = MIPSREG( 9); \
+ f.mips_regs.uregs[10] = MIPSREG(10); \
+ f.mips_regs.uregs[11] = MIPSREG(11); \
+ f.mips_regs.uregs[12] = MIPSREG(12); \
+ f.mips_regs.uregs[13] = MIPSREG(13); \
+ f.mips_regs.uregs[14] = MIPSREG(14); \
+ f.mips_regs.uregs[15] = MIPSREG(15); \
+ f.mips_regs.uregs[16] = MIPSREG(16); \
+ f.mips_regs.uregs[17] = MIPSREG(17); \
+ f.mips_regs.uregs[18] = MIPSREG(18); \
+ f.mips_regs.uregs[19] = MIPSREG(19); \
+ f.mips_regs.uregs[20] = MIPSREG(20); \
+ f.mips_regs.uregs[21] = MIPSREG(21); \
+ f.mips_regs.uregs[22] = MIPSREG(22); \
+ f.mips_regs.uregs[23] = MIPSREG(23); \
+ f.mips_regs.uregs[24] = MIPSREG(24); \
+ f.mips_regs.uregs[25] = MIPSREG(25); \
+ f.mips_regs.uregs[26] = MIPSREG(26); \
+ f.mips_regs.uregs[27] = MIPSREG(27); \
+ f.mips_regs.uregs[28] = MIPSREG(28); \
+ f.mips_regs.uregs[29] = MIPSREG(29); \
+ f.mips_regs.uregs[30] = MIPSREG(30); \
+ f.mips_regs.uregs[31] = MIPSREG(31); \
+ __asm__ volatile ("mfhi %0" : "=r"(hi)); \
+ __asm__ volatile ("mflo %0" : "=r"(lo)); \
+ __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \
+ f.mips_regs.hi = hi; \
+ f.mips_regs.lo = lo; \
+ f.mips_regs.cp0_epc = pc; \
+ f.errno_ = errno; \
+ f.tid = sys_gettid(); \
+ } while (0)
+ #define SET_FRAME(f,r) \
+ do { \
+ errno = (f).errno_; \
+ memcpy((r).uregs, (f).mips_regs.uregs, \
+ 32*sizeof(unsigned long)); \
+ (r).hi = (f).mips_regs.hi; \
+ (r).lo = (f).mips_regs.lo; \
+ (r).cp0_epc = (f).mips_regs.cp0_epc; \
+ } while (0)
+#else
+ /* If we do not have a hand-optimized assembly version of the FRAME()
+ * macro, we cannot reliably unroll the stack. So, we show a few additional
+ * stack frames for the coredumper.
+ */
+ typedef struct Frame {
+ pid_t tid;
+ } Frame;
+ #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0)
+ #define SET_FRAME(f,r) do { } while (0)
+#endif
+
+
+/* Internal function for generating a core file. This API can change without
+ * notice and is only supposed to be used internally by the core dumper.
+ *
+ * This function works for both single- and multi-threaded core
+ * dumps. If called as
+ *
+ * FRAME(frame);
+ * InternalGetCoreDump(&frame, 0, NULL, ap);
+ *
+ * it creates a core file that only contains information about the
+ * calling thread.
+ *
+ * Optionally, the caller can provide information about other threads
+ * by passing their process ids in "thread_pids". The process id of
+ * the caller should not be included in this array. All of the threads
+ * must have been attached to with ptrace(), prior to calling this
+ * function. They will be detached when "InternalGetCoreDump()" returns.
+ *
+ * This function either returns a file handle that can be read for obtaining
+ * a core dump, or "-1" in case of an error. In the latter case, "errno"
+ * will be set appropriately.
+ *
+ * While "InternalGetCoreDump()" is not technically async signal safe, you
+ * might be tempted to invoke it from a signal handler. The code goes to
+ * great lengths to make a best effort that this will actually work. But in
+ * any case, you must make sure that you preserve the value of "errno"
+ * yourself. It is guaranteed to be clobbered otherwise.
+ *
+ * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again,
+ * it makes a best effort to behave reasonably when called in a multi-
+ * threaded environment, but it is ultimately the caller's responsibility
+ * to provide locking.
+ */
+int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids,
+ va_list ap
+ /* const struct CoreDumpParameters *params,
+ const char *file_name,
+ const char *PATH
+ */);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ELFCORE_H */
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/googleinit.h b/chromium/third_party/tcmalloc/vendor/src/base/googleinit.h
new file mode 100644
index 00000000000..dbf610cb0dd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/googleinit.h
@@ -0,0 +1,73 @@
+// 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, "<GoogleModuleObject> constructing: %s\n", name_);
+ if (ctor)
+ ctor();
+ }
+ ~GoogleInitializer() {
+ RAW_VLOG(10, "<GoogleModuleObject> 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/chromium/third_party/tcmalloc/vendor/src/base/linux_syscall_support.h b/chromium/third_party/tcmalloc/vendor/src/base/linux_syscall_support.h
new file mode 100644
index 00000000000..d550776efd3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/linux_syscall_support.h
@@ -0,0 +1,2182 @@
+/* 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_futex1(
+ * sys_getcpu(
+ * sys_getdents(
+ * 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_getdents64
+ * sys_llseek
+ * sys_mmap2
+ * sys_openat
+ * 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, and 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)
+
+#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 <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <endian.h>
+
+#ifdef __mips__
+/* Include definitions of the ABI currently in use. */
+#include <sgidefs.h>
+#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__)
+
+/* 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
+#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,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}/stat.h */
+#ifdef __mips__
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+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_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned long long st_rdev;
+ unsigned short int __pad2;
+ long long st_size;
+ long st_blksize;
+ long 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 long __unused4;
+ unsigned long __unused5;
+};
+#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,i386,mips,x86_64,ppc}/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 {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+ unsigned st_mode;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned __pad0;
+ unsigned long st_rdev;
+ long st_size;
+ long st_blksize;
+ 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_;
+ long __unused[3];
+};
+#elif defined(__PPC__)
+struct kernel_stat {
+ unsigned st_dev;
+ unsigned long st_ino; // ino_t
+ unsigned long st_mode; // mode_t
+ unsigned short st_nlink; // nlink_t
+ unsigned st_uid; // uid_t
+ unsigned st_gid; // gid_t
+ unsigned st_rdev;
+ long st_size; // off_t
+ 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;
+};
+#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64)
+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];
+};
+#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
+#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_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 defininitions */
+#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__))
+ /* 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 \
+ : "esp", "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)) \
+ : "esp", "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)) \
+ : "esp", "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)
+ : "esp", "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_BODY
+ #define LSS_BODY(type,name, ...) \
+ long __res; \
+ __asm__ __volatile__("syscall" : "=a" (__res) : "0" (__NR_##name), \
+ ##__VA_ARGS__ : "r11", "rcx", "memory"); \
+ 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) { \
+ LSS_BODY(type, name, "D" ((long)(arg1))); \
+ }
+ #undef _syscall2
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((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, name, "D" ((long)(arg1)), "S" ((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) { \
+ long __res; \
+ __asm__ __volatile__("movq %5,%%r10; syscall" : \
+ "=a" (__res) : "0" (__NR_##name), \
+ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \
+ "r" ((long)(arg4)) : "r10", "r11", "rcx", "memory"); \
+ LSS_RETURN(type, __res); \
+ }
+ #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__("movq %5,%%r10; movq %6,%%r8; syscall" : \
+ "=a" (__res) : "0" (__NR_##name), \
+ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \
+ "r" ((long)(arg4)), "r" ((long)(arg5)) : \
+ "r8", "r10", "r11", "rcx", "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; \
+ __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; movq %7,%%r9;" \
+ "syscall" : \
+ "=a" (__res) : "0" (__NR_##name), \
+ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \
+ "r" ((long)(arg4)), "r" ((long)(arg5)), "r" ((long)(arg6)) : \
+ "r8", "r9", "r10", "r11", "rcx", "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;
+ */
+ "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"(fn), "S"(child_stack), "D"(flags), "r"(arg),
+ "d"(parent_tidptr), "g"(newtls), "g"(child_tidptr)
+ : "rsp", "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.
+ */
+ void (*res)(void);
+ __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 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), "r" ((unsigned long)arg5), \
+ "r" ((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.3.6 clone.S */
+ /* TODO(csilvers): consider wrapping some args up in a struct, like we
+ * do for i386's _syscall6, so we can compile successfully on gcc 2.95
+ */
+ 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;
+ {
+ 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");
+ }
+ LSS_RETURN(int, __ret, __err);
+ }
+ #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)
+ LSS_INLINE _syscall3(int, fcntl, int, f,
+ int, c, long, a)
+ LSS_INLINE _syscall2(int, fstat, int, f,
+ struct kernel_stat*, b)
+ LSS_INLINE _syscall4(int, futex, int*, a,
+ int, o, int, v,
+ struct kernel_timespec*, t)
+ LSS_INLINE _syscall3(int, getdents, int, f,
+ struct kernel_dirent*, d, int, c)
+#ifdef __NR_getdents64
+ LSS_INLINE _syscall3(int, getdents64, int, f,
+ struct kernel_dirent64*, d, int, c)
+#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)
+ LSS_INLINE _syscall3(off_t, lseek, int, f,
+ off_t, o, int, w)
+ 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 _syscall3(int, open, const char*, p,
+ int, f, int, m)
+ 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)
+ LSS_INLINE _syscall2(int, stat, const char*, f,
+ struct kernel_stat*, b)
+ 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(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
+ LSS_INLINE _syscall3(int, socket, int, d,
+ int, t, int, p)
+ #endif
+ #if defined(__x86_64__)
+ LSS_INLINE _syscall6(void*, mmap, void*, s,
+ size_t, l, int, p,
+ int, f, int, d,
+ __off64_t, o)
+
+ LSS_INLINE int LSS_NAME(sigaction)(int signum,
+ const struct kernel_sigaction *act,
+ struct kernel_sigaction *oldact) {
+ /* 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 {
+ 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(__x86_64__) || \
+ defined(__arm__) || \
+ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
+ 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);
+ }
+ #endif
+ #if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ LSS_INLINE _syscall4(int, openat, int, d, 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__)
+ #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)
+#ifdef __PPC64__
+ LSS_INLINE _syscall6(void*, mmap, void*, s,
+ size_t, l, int, p,
+ int, f, int, d,
+ off_t, o)
+#else
+ #ifndef __ARM_EABI__
+ /* Not available on ARM EABI Linux. */
+ LSS_INLINE _syscall1(void*, mmap, void*, a)
+ #endif
+ 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(__PPC__)
+ #undef LSS_SC_LOADARGS_0
+ #define LSS_SC_LOADARGS_0(dummy...)
+ #undef LSS_SC_LOADARGS_1
+ #define LSS_SC_LOADARGS_1(arg1) \
+ __sc_4 = (unsigned long) (arg1)
+ #undef LSS_SC_LOADARGS_2
+ #define LSS_SC_LOADARGS_2(arg1, arg2) \
+ LSS_SC_LOADARGS_1(arg1); \
+ __sc_5 = (unsigned long) (arg2)
+ #undef LSS_SC_LOADARGS_3
+ #define LSS_SC_LOADARGS_3(arg1, arg2, arg3) \
+ LSS_SC_LOADARGS_2(arg1, arg2); \
+ __sc_6 = (unsigned long) (arg3)
+ #undef LSS_SC_LOADARGS_4
+ #define LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4) \
+ LSS_SC_LOADARGS_3(arg1, arg2, arg3); \
+ __sc_7 = (unsigned long) (arg4)
+ #undef LSS_SC_LOADARGS_5
+ #define LSS_SC_LOADARGS_5(arg1, arg2, arg3, arg4, arg5) \
+ LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4); \
+ __sc_8 = (unsigned long) (arg5)
+ #undef LSS_SC_BODY
+ #define LSS_SC_BODY(nr, type, opt, args...) \
+ long __sc_ret, __sc_err; \
+ { \
+ register unsigned long __sc_0 __asm__ ("r0") = __NR_socketcall; \
+ register unsigned long __sc_3 __asm__ ("r3") = opt; \
+ 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_SC_LOADARGS_##nr(args); \
+ __asm__ __volatile__ \
+ ("stwu 1, -48(1)\n\t" \
+ "stw 4, 20(1)\n\t" \
+ "stw 5, 24(1)\n\t" \
+ "stw 6, 28(1)\n\t" \
+ "stw 7, 32(1)\n\t" \
+ "stw 8, 36(1)\n\t" \
+ "addi 4, 1, 20\n\t" \
+ "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"); \
+ __sc_ret = __sc_3; \
+ __sc_err = __sc_0; \
+ } \
+ LSS_RETURN(type, __sc_ret, __sc_err)
+
+ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
+ LSS_SC_BODY(3, int, 1, domain, type, protocol);
+ }
+ #endif
+ #if defined(__i386__) || \
+ (defined(__arm__) && !defined(__ARM_EABI__)) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+
+ /* 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(long, 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(__i386__) || defined(__PPC__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+ LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p,
+ int*, s, int, o)
+ #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;
+ }
+ }
+ #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/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.cc b/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.cc
new file mode 100644
index 00000000000..19da4004b17
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.cc
@@ -0,0 +1,665 @@
+/* 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 <sched.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#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
+
+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 - 4096,
+ 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 ResumeAllProcessThreads(), then
+ * we are running a higher risk, though. So, try to avoid calling
+ * abort() after calling 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) {
+ 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;
+};
+
+
+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;
+
+ /* 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 = sys_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) {
+ 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 (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 */
+ 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 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
+ * 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 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;
+
+ 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;
+
+ /* 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
+
+ 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) {
+ 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;
+ }
+ } else {
+ args.result = -1;
+ args.err = clone_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
+ * 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 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/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.h b/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.h
new file mode 100644
index 00000000000..5c318fed7ec
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/linuxthreads.h
@@ -0,0 +1,53 @@
+/* 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 x86-32 and x86-64 on Linux. Porting to other
+ * related platforms should not be difficult.
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+ defined(__mips__) || defined(__PPC__)) && 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/chromium/third_party/tcmalloc/vendor/src/base/logging.cc b/chromium/third_party/tcmalloc/vendor/src/base/logging.cc
new file mode 100644
index 00000000000..4b97858a371
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/logging.cc
@@ -0,0 +1,107 @@
+// 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 <config.h>
+#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 <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#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/chromium/third_party/tcmalloc/vendor/src/base/logging.h b/chromium/third_party/tcmalloc/vendor/src/base/logging.h
new file mode 100644
index 00000000000..d6a6ab58abf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/logging.h
@@ -0,0 +1,258 @@
+// 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 <config.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#include <string.h> // for strlen(), strcmp()
+#include <assert.h>
+#include <errno.h> // for errno
+#include "base/commandlineflags.h"
+
+// On some systems (like freebsd), we can't call write() at all in a
+// global constructor, perhaps because errno hasn't been set up.
+// (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 <sys/syscall.h>
+#define WRITE_TO_STDERR(buf, len) syscall(SYS_write, STDERR_FILENO, buf, len)
+#else
+#define WRITE_TO_STDERR(buf, len) write(STDERR_FILENO, buf, len)
+#endif
+
+// 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 <windows.h>
+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/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc b/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc
new file mode 100644
index 00000000000..c043cb68b6e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc
@@ -0,0 +1,522 @@
+/* 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 <gperftools/malloc_hook.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <new> // 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.
+
+// ---------------------------------------------------------------------------
+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 int32 r = 1; // no locking---it's not critical
+ ANNOTATE_BENIGN_RACE(&r, "benign race, 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<kMaxLevel and next[level-1] will fit in the node.
+// 0 < LLA_SkiplistLevels(x,y,false) <= LLA_SkiplistLevels(x,y,true) < kMaxLevel
+static int LLA_SkiplistLevels(size_t size, size_t base, bool random) {
+ // max_fit is the maximum number of levels that will fit in a node for the
+ // given size. We can't return more than max_fit, no matter what the
+ // random number generator says.
+ int max_fit = (size-OFFSETOF_MEMBER(AllocList, next)) / sizeof (AllocList *);
+ int level = IntLog2(size, base) + (random? Random() : 1);
+ if (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)
+};
+
+// 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;
+
+// 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<intptr_t>(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'.
+ }
+ }
+}
+
+// L < meta_data_arena->mu
+LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32 flags,
+ Arena *meta_data_arena) {
+ 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;
+ 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, &region->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<intptr_t>(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<char *>(prev) + prev->header.size <
+ reinterpret_cast<char *>(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<char *>(a) + a->header.size ==
+ reinterpret_cast<char *>(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<AllocList *>(
+ reinterpret_cast<char *>(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<AllocList *>(
+ reinterpret_cast<char *>(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;
+ if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
+ new_pages = MallocHook::UnhookedMMap(0, new_pages_size,
+ PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ } else {
+ new_pages = mmap(0, new_pages_size,
+ PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ }
+ RAW_CHECK(new_pages != MAP_FAILED, "mmap error");
+ arena->mu.Lock();
+ s = reinterpret_cast<AllocList *>(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<AllocList *>
+ (req_rnd + reinterpret_cast<char *>(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;
+ }
+ ANNOTATE_NEW_MEMORY(result, request);
+ 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;
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.h b/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.h
new file mode 100644
index 00000000000..393b3d25b8a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/low_level_alloc.h
@@ -0,0 +1,106 @@
+/* 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 <config.h>
+#include <stddef.h> // for size_t
+#include "base/basictypes.h"
+
+class LowLevelAlloc {
+ public:
+ 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);
+
+ // 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/chromium/third_party/tcmalloc/vendor/src/base/simple_mutex.h b/chromium/third_party/tcmalloc/vendor/src/base/simple_mutex.h
new file mode 100644
index 00000000000..a97172ac5ea
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/simple_mutex.h
@@ -0,0 +1,331 @@
+// 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 <config.h>
+
+#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 <windows.h>
+ 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 <pthread.h>
+ typedef pthread_rwlock_t MutexType;
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+ typedef pthread_mutex_t MutexType;
+#else
+# error Need to implement mutex.h for your architecture, or #define NO_THREADS
+#endif
+
+#include <assert.h>
+#include <stdlib.h> // 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/chromium/third_party/tcmalloc/vendor/src/base/spinlock.cc b/chromium/third_party/tcmalloc/vendor/src/base/spinlock.cc
new file mode 100644
index 00000000000..1413923fef1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock.cc
@@ -0,0 +1,182 @@
+/* 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 <config.h>
+#include "base/spinlock.h"
+#include "base/synchronization_profiling.h"
+#include "base/spinlock_internal.h"
+#include "base/cycleclock.h"
+#include "base/sysinfo.h" /* for NumCPUs() */
+
+// NOTE on the Lock-state values:
+//
+// kSpinLockFree represents the unlocked state
+// kSpinLockHeld represents the locked state with no waiters
+//
+// Values greater than kSpinLockHeld represent the locked state with waiters,
+// where the value is the time the current lock holder had to
+// wait before obtaining the lock. The kSpinLockSleeper state is a special
+// "locked with waiters" state that indicates that a sleeper needs to
+// be woken, but the thread that just released the lock didn't wait.
+
+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 (NumCPUs() > 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;
+
+} // unnamed namespace
+
+// Monitor the lock to see if its value changes within some time period
+// (adaptive_spin_count loop iterations). A timestamp indicating
+// when the thread initially started waiting for the lock is passed in via
+// the initial_wait_timestamp value. The total wait time in cycles for the
+// lock is returned in the wait_cycles parameter. The last value read
+// from the lock is returned from the method.
+Atomic32 SpinLock::SpinLoop(int64 initial_wait_timestamp,
+ Atomic32* wait_cycles) {
+ int c = adaptive_spin_count;
+ while (base::subtle::NoBarrier_Load(&lockword_) != kSpinLockFree && --c > 0) {
+ }
+ Atomic32 spin_loop_wait_cycles = CalculateWaitCycles(initial_wait_timestamp);
+ Atomic32 lock_value =
+ base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
+ spin_loop_wait_cycles);
+ *wait_cycles = spin_loop_wait_cycles;
+ return lock_value;
+}
+
+void SpinLock::SlowLock() {
+ // The lock was not obtained initially, so this thread needs to wait for
+ // it. Record the current timestamp in the local variable wait_start_time
+ // so the total wait time can be stored in the lockword once this thread
+ // obtains the lock.
+ int64 wait_start_time = CycleClock::Now();
+ Atomic32 wait_cycles;
+ Atomic32 lock_value = SpinLoop(wait_start_time, &wait_cycles);
+
+ 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 SpinLockWait routine to properly indicate
+ // the last lock_value observed.
+ lock_value = kSpinLockSleeper;
+ } else if (lock_value == kSpinLockFree) {
+ // Lock is free again, so try and aquire 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,
+ wait_cycles);
+ 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(wait_start_time, &wait_cycles);
+ }
+}
+
+// The wait time for contentionz lock profiling must fit into 32 bits.
+// However, the lower 32-bits of the cycle counter wrap around too quickly
+// with high frequency processors, so a right-shift by 7 is performed to
+// quickly divide the cycles by 128. Using these 32 bits, reduces the
+// granularity of time measurement to 128 cycles, and loses track
+// of wait time for waits greater than 109 seconds on a 5 GHz machine
+// [(2^32 cycles/5 Ghz)*128 = 109.95 seconds]. Waits this long should be
+// very rare and the reduced granularity should not be an issue given
+// processors in the Google fleet operate at a minimum of one billion
+// cycles/sec.
+enum { PROFILE_TIMESTAMP_SHIFT = 7 };
+
+void SpinLock::SlowUnlock(uint64 wait_cycles) {
+ base::internal::SpinLockWake(&lockword_, false); // wake waiter if necessary
+
+ // Collect contentionz profile info, expanding the wait_cycles back out to
+ // the full value. If wait_cycles is <= kSpinLockSleeper, then no wait
+ // was actually performed, so don't record the wait time. Note, that the
+ // CalculateWaitCycles method adds in kSpinLockSleeper cycles
+ // unconditionally to guarantee the wait time is not kSpinLockFree or
+ // kSpinLockHeld. The adding in of these small number of cycles may
+ // overestimate the contention by a slight amount 50% of the time. However,
+ // if this code tried to correct for that addition by subtracting out the
+ // kSpinLockSleeper amount that would underestimate the contention slightly
+ // 50% of the time. Both ways get the wrong answer, so the code
+ // overestimates to be more conservative. Overestimating also makes the code
+ // a little simpler.
+ //
+ if (wait_cycles > kSpinLockSleeper) {
+ base::SubmitSpinLockProfileData(this,
+ wait_cycles << PROFILE_TIMESTAMP_SHIFT);
+ }
+}
+
+inline int32 SpinLock::CalculateWaitCycles(int64 wait_start_time) {
+ int32 wait_cycles = ((CycleClock::Now() - wait_start_time) >>
+ PROFILE_TIMESTAMP_SHIFT);
+ // The number of cycles waiting for the lock is used as both the
+ // wait_cycles and lock value, so it can't be kSpinLockFree or
+ // kSpinLockHeld. Make sure the value returned is at least
+ // kSpinLockSleeper.
+ wait_cycles |= kSpinLockSleeper;
+ return wait_cycles;
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/spinlock.h b/chromium/third_party/tcmalloc/vendor/src/base/spinlock.h
new file mode 100644
index 00000000000..c2be4fd7264
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock.h
@@ -0,0 +1,151 @@
+/* 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
+ */
+
+//
+// Fast spinlocks (at least on x86, a lock/unlock pair is approximately
+// half the cost of a Mutex because the unlock just does a store instead
+// of a compare-and-swap which is expensive).
+
+// 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 <config.h>
+#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.
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
+ if (base::subtle::Acquire_CompareAndSwap(&lockword_, kSpinLockFree,
+ kSpinLockHeld) != kSpinLockFree) {
+ SlowLock();
+ }
+ ANNOTATE_RWLOCK_ACQUIRED(this, 1);
+ }
+
+ // 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);
+ if (res) {
+ ANNOTATE_RWLOCK_ACQUIRED(this, 1);
+ }
+ return res;
+ }
+
+ // Release this SpinLock, which must be held by the calling thread.
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ inline void Unlock() /*UNLOCK_FUNCTION()*/ {
+ uint64 wait_cycles =
+ static_cast<uint64>(base::subtle::NoBarrier_Load(&lockword_));
+ ANNOTATE_RWLOCK_RELEASED(this, 1);
+ base::subtle::Release_Store(&lockword_, kSpinLockFree);
+ if (wait_cycles != kSpinLockHeld) {
+ // Collect contentionz profile info, and speed the wakeup of any waiter.
+ // The wait_cycles value indicates how long this thread spent waiting
+ // for the lock.
+ SlowUnlock(wait_cycles);
+ }
+ }
+
+ // 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(uint64 wait_cycles);
+ Atomic32 SpinLoop(int64 initial_wait_timestamp, Atomic32* wait_cycles);
+ inline int32 CalculateWaitCycles(int64 wait_start_time);
+
+ 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();
+ }
+ // TODO(csilvers): uncomment the annotation when we figure out how to
+ // support this macro with 0 args (see thread_annotations.h)
+ 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/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc
new file mode 100644
index 00000000000..b9faddef2c6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc
@@ -0,0 +1,102 @@
+/* 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 {
+
+// See spinlock_internal.h for spec.
+int32 SpinLockWait(volatile Atomic32 *w, int n,
+ const SpinLockWaitTransition trans[]) {
+ int32 v;
+ bool done = false;
+ for (int loop = 0; !done; loop++) {
+ v = base::subtle::Acquire_Load(w);
+ int i;
+ for (i = 0; i != n && v != trans[i].from; i++) {
+ }
+ if (i == n) {
+ SpinLockDelay(w, v, loop); // no matching transition
+ } else if (trans[i].to == v || // null transition
+ base::subtle::Acquire_CompareAndSwap(w, v, trans[i].to) == v) {
+ done = trans[i].done;
+ }
+ }
+ return v;
+}
+
+// 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.
+ 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));
+}
+
+} // namespace internal
+} // namespace base
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.h b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.h
new file mode 100644
index 00000000000..44942609f40
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_internal.h
@@ -0,0 +1,64 @@
+/* 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 <config.h>
+#include "base/basictypes.h"
+#include "base/atomicops.h"
+
+namespace base {
+namespace internal {
+
+// SpinLockWait() waits until it can perform one of several transitions from
+// "from" to "to". It returns when it performs a transition where done==true.
+struct SpinLockWaitTransition {
+ int32 from;
+ int32 to;
+ bool done;
+};
+
+// Wait until *w can transition from trans[i].from to trans[i].to for some i
+// satisfying 0<=i<n && trans[i].done, atomically make the transition,
+// then return the old value of *w. Make any other atomic tranistions
+// where !trans[i].done, but continue waiting.
+int32 SpinLockWait(volatile Atomic32 *w, int n,
+ const SpinLockWaitTransition trans[]);
+void SpinLockWake(volatile Atomic32 *w, bool all);
+void SpinLockDelay(volatile Atomic32 *w, int32 value, int loop);
+
+} // namespace internal
+} // namespace base
+#endif
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h
new file mode 100644
index 00000000000..bee2d4cedb1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h
@@ -0,0 +1,103 @@
+/* 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 <errno.h>
+#include <sched.h>
+#include <time.h>
+#include <limits.h>
+#include "base/linux_syscall_support.h"
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_PRIVATE_FLAG 128
+
+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.
+#ifdef __arm__
+ // ARM linux doesn't support sys_futex1(void*, int, int, struct timespec*);
+ have_futex = 0;
+#else
+ have_futex = (sizeof (Atomic32) == sizeof (int) &&
+ sys_futex(&x, FUTEX_WAKE, 1, 0) >= 0);
+#endif
+ if (have_futex &&
+ sys_futex(&x, FUTEX_WAKE | futex_private_flag, 1, 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
+ sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAIT | futex_private_flag,
+ value, reinterpret_cast<struct kernel_timespec *>(&tm));
+ } else {
+ nanosleep(&tm, NULL);
+ }
+ errno = save_errno;
+ }
+}
+
+void SpinLockWake(volatile Atomic32 *w, bool all) {
+ if (have_futex) {
+ sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAKE | futex_private_flag, all? INT_MAX : 1, 0);
+ }
+}
+
+} // namespace internal
+} // namespace base
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h
new file mode 100644
index 00000000000..e1d43b7db29
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h
@@ -0,0 +1,62 @@
+/* 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 <config.h>
+#include <errno.h>
+#ifdef HAVE_SCHED_H
+#include <sched.h> /* For sched_yield() */
+#endif
+#include <time.h> /* 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/chromium/third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h
new file mode 100644
index 00000000000..64decd26724
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h
@@ -0,0 +1,53 @@
+/* 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 <windows.h>
+
+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/chromium/third_party/tcmalloc/vendor/src/base/stl_allocator.h b/chromium/third_party/tcmalloc/vendor/src/base/stl_allocator.h
new file mode 100644
index 00000000000..8276a83d77f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/stl_allocator.h
@@ -0,0 +1,97 @@
+/* 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 <config.h>
+
+#include <stddef.h> // for ptrdiff_t
+#include <limits>
+
+#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<T, MyAlloc> provides the same thread-safety
+// guarantees as MyAlloc.
+//
+// Usage example:
+// set<T, less<T>, STL_Allocator<T, MyAlloc> > 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 <typename T, class Alloc>
+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 <class T1> struct rebind {
+ typedef STL_Allocator<T1, Alloc> other;
+ };
+
+ STL_Allocator() { }
+ STL_Allocator(const STL_Allocator&) { }
+ template <class T1> STL_Allocator(const STL_Allocator<T1, Alloc>&) { }
+ ~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<T*>(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/chromium/third_party/tcmalloc/vendor/src/base/synchronization_profiling.h b/chromium/third_party/tcmalloc/vendor/src/base/synchronization_profiling.h
new file mode 100644
index 00000000000..cf02c218a11
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/synchronization_profiling.h
@@ -0,0 +1,50 @@
+/* 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.
+ *
+ * ---
+ * Author: Chris Ruemmler
+ */
+
+#ifndef BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
+#define BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
+
+#include "base/basictypes.h"
+
+namespace base {
+
+// We can do contention-profiling of SpinLocks, but the code is in
+// mutex.cc, which is not always linked in with spinlock. Hence we
+// provide a weak definition, which are used if mutex.cc isn't linked in.
+
+// Submit the number of cycles the spinlock spent contending.
+ATTRIBUTE_WEAK extern void SubmitSpinLockProfileData(const void *, int64);
+extern void SubmitSpinLockProfileData(const void *contendedlock,
+ int64 wait_cycles) {}
+}
+#endif // BASE_AUXILIARY_SYNCHRONIZATION_PROFILING_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.cc b/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.cc
new file mode 100644
index 00000000000..2559158b9db
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.cc
@@ -0,0 +1,985 @@
+// 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 <config.h>
+#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(__CYGWIN__) && !defined(__CYGWIN32)
+# define PLATFORM_WINDOWS 1
+#endif
+
+#include <stdlib.h> // for getenv()
+#include <stdio.h> // for snprintf(), sscanf()
+#include <string.h> // for memmove(), memchr(), etc.
+#include <fcntl.h> // for open()
+#include <errno.h> // for errno
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for read()
+#endif
+#if defined __MACH__ // Mac OS X, almost certainly
+#include <mach-o/dyld.h> // for iterating over dll's in ProcMapsIter
+#include <mach-o/loader.h> // for iterating over dll's in ProcMapsIter
+#include <sys/types.h>
+#include <sys/sysctl.h> // how we figure out numcpu's on OS X
+#elif defined __FreeBSD__
+#include <sys/sysctl.h>
+#elif defined __sun__ // Solaris
+#include <procfs.h> // for, e.g., prmap_t
+#elif defined(PLATFORM_WINDOWS)
+#include <process.h> // for getpid() (actually, _getpid())
+#include <shlwapi.h> // for SHGetValueA()
+#include <tlhelp32.h> // for Module32First()
+#endif
+#include "base/sysinfo.h"
+#include "base/commandlineflags.h"
+#include "base/dynamic_annotations.h" // for RunningOnValgrind
+#include "base/logging.h"
+#include "base/cycleclock.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 <sys/syscall.h>
+#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.
+// ----------------------------------------------------------------------
+
+// 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) {
+#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
+ if (__environ) { // can exist but be NULL, if statically linked
+ const int namelen = strlen(name);
+ for (char** p = __environ; *p; p++) {
+ if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
+ return *p + namelen+1; // point after =
+ }
+ 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 int namelen = strlen(name);
+ 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*)memchr(p, '\0', sizeof(envbuf) - (p - envbuf));
+ if (endp == NULL) // this entry isn't NUL terminated
+ return NULL;
+ else if (!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
+}
+
+// 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;
+}
+
+// ----------------------------------------------------------------------
+// CyclesPerSecond()
+// NumCPUs()
+// It's important this not call malloc! -- they may be called at
+// global-construct time, before we've set up all our proper malloc
+// hooks and such.
+// ----------------------------------------------------------------------
+
+static double cpuinfo_cycles_per_second = 1.0; // 0.0 might be dangerous
+static int cpuinfo_num_cpus = 1; // Conservative guess
+
+void SleepForMilliseconds(int milliseconds) {
+#ifdef PLATFORM_WINDOWS
+ _sleep(milliseconds); // Windows's _sleep takes milliseconds argument
+#else
+ // Sleep for a few milliseconds
+ struct timespec sleep_time;
+ sleep_time.tv_sec = milliseconds / 1000;
+ sleep_time.tv_nsec = (milliseconds % 1000) * 1000000;
+ while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR)
+ ; // Ignore signals and wait for the full interval to elapse.
+#endif
+}
+
+// Helper function estimates cycles/sec by observing cycles elapsed during
+// sleep(). Using small sleep time decreases accuracy significantly.
+static int64 EstimateCyclesPerSecond(const int estimate_time_ms) {
+ assert(estimate_time_ms > 0);
+ if (estimate_time_ms <= 0)
+ return 1;
+ double multiplier = 1000.0 / (double)estimate_time_ms; // scale by this much
+
+ const int64 start_ticks = CycleClock::Now();
+ SleepForMilliseconds(estimate_time_ms);
+ const int64 guess = int64(multiplier * (CycleClock::Now() - start_ticks));
+ return guess;
+}
+
+// ReadIntFromFile is only called on linux and cygwin platforms.
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+// Helper function for reading an int from a file. Returns true if successful
+// and the memory location pointed to by value is set to the value read.
+static bool ReadIntFromFile(const char *file, int *value) {
+ bool ret = false;
+ int fd = open(file, O_RDONLY);
+ if (fd != -1) {
+ char line[1024];
+ char* err;
+ memset(line, '\0', sizeof(line));
+ read(fd, line, sizeof(line) - 1);
+ const int temp_value = strtol(line, &err, 10);
+ if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
+ *value = temp_value;
+ ret = true;
+ }
+ close(fd);
+ }
+ return ret;
+}
+#endif
+
+// WARNING: logging calls back to InitializeSystemInfo() so it must
+// not invoke any logging code. Also, InitializeSystemInfo() can be
+// called before main() -- in fact it *must* be since already_called
+// isn't protected -- before malloc hooks are properly set up, so
+// we make an effort not to call any routines which might allocate
+// memory.
+
+static void InitializeSystemInfo() {
+ static bool already_called = false; // safe if we run before threads
+ if (already_called) return;
+ already_called = true;
+
+ bool saw_mhz = false;
+
+ if (RunningOnValgrind()) {
+ // Valgrind may slow the progress of time artificially (--scale-time=N
+ // option). We thus can't rely on CPU Mhz info stored in /sys or /proc
+ // files. Thus, actually measure the cps.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(100);
+ saw_mhz = true;
+ }
+
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+ char line[1024];
+ char* err;
+ int freq;
+
+ // If the kernel is exporting the tsc frequency use that. There are issues
+ // where cpuinfo_max_freq cannot be relied on because the BIOS may be
+ // exporintg an invalid p-state (on x86) or p-states may be used to put the
+ // processor in a new mode (turbo mode). Essentially, those frequencies
+ // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
+ // well.
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
+ // The value is in kHz (as the file name suggests). For example, on a
+ // 2GHz warpstation, the file contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
+ }
+
+ // If CPU scaling is in effect, we want to use the *maximum* frequency,
+ // not whatever CPU speed some random processor happens to be using now.
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
+ &freq)) {
+ // The value is in kHz. For example, on a 2GHz machine, the file
+ // contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
+ }
+
+ // Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq.
+ const char* pname = "/proc/cpuinfo";
+ int fd = open(pname, O_RDONLY);
+ if (fd == -1) {
+ perror(pname);
+ if (!saw_mhz) {
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
+ return; // TODO: use generic tester instead?
+ }
+
+ double bogo_clock = 1.0;
+ bool saw_bogo = false;
+ int num_cpus = 0;
+ line[0] = line[1] = '\0';
+ int chars_read = 0;
+ do { // we'll exit when the last read didn't read anything
+ // Move the next line to the beginning of the buffer
+ const int oldlinelen = strlen(line);
+ if (sizeof(line) == oldlinelen + 1) // oldlinelen took up entire line
+ line[0] = '\0';
+ else // still other lines left to save
+ memmove(line, line + oldlinelen+1, sizeof(line) - (oldlinelen+1));
+ // Terminate the new line, reading more if we can't find the newline
+ char* newline = strchr(line, '\n');
+ if (newline == NULL) {
+ const int linelen = strlen(line);
+ const int bytes_to_read = sizeof(line)-1 - linelen;
+ assert(bytes_to_read > 0); // because the memmove recovered >=1 bytes
+ chars_read = read(fd, line + linelen, bytes_to_read);
+ line[linelen + chars_read] = '\0';
+ newline = strchr(line, '\n');
+ }
+ if (newline != NULL)
+ *newline = '\0';
+
+ // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
+ // accept postive values. Some environments (virtual machines) report zero,
+ // which would cause infinite looping in WallTime_Init.
+ if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
+ const char* freqstr = strchr(line, ':');
+ if (freqstr) {
+ cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
+ if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0)
+ saw_mhz = true;
+ }
+ } else if (strncasecmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
+ const char* freqstr = strchr(line, ':');
+ if (freqstr) {
+ bogo_clock = strtod(freqstr+1, &err) * 1000000.0;
+ if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0)
+ saw_bogo = true;
+ }
+ } else if (strncasecmp(line, "processor", sizeof("processor")-1) == 0) {
+ num_cpus++; // count up every time we see an "processor :" entry
+ }
+ } while (chars_read > 0);
+ close(fd);
+
+ if (!saw_mhz) {
+ if (saw_bogo) {
+ // If we didn't find anything better, we'll use bogomips, but
+ // we're not happy about it.
+ cpuinfo_cycles_per_second = bogo_clock;
+ } else {
+ // If we don't even have bogomips, we'll use the slow estimation.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
+ }
+ if (cpuinfo_cycles_per_second == 0.0) {
+ cpuinfo_cycles_per_second = 1.0; // maybe unnecessary, but safe
+ }
+ if (num_cpus > 0) {
+ cpuinfo_num_cpus = num_cpus;
+ }
+
+#elif defined __FreeBSD__
+ // For this sysctl to work, the machine must be configured without
+ // SMP, APIC, or APM support. hz should be 64-bit in freebsd 7.0
+ // and later. Before that, it's a 32-bit quantity (and gives the
+ // wrong answer on machines faster than 2^32 Hz). See
+ // http://lists.freebsd.org/pipermail/freebsd-i386/2004-November/001846.html
+ // But also compare FreeBSD 7.0:
+ // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG70#L223
+ // 231 error = sysctl_handle_quad(oidp, &freq, 0, req);
+ // To FreeBSD 6.3 (it's the same in 6-STABLE):
+ // http://fxr.watson.org/fxr/source/i386/i386/tsc.c?v=RELENG6#L131
+ // 139 error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
+#if __FreeBSD__ >= 7
+ uint64_t hz = 0;
+#else
+ unsigned int hz = 0;
+#endif
+ size_t sz = sizeof(hz);
+ const char *sysctl_path = "machdep.tsc_freq";
+ if ( sysctlbyname(sysctl_path, &hz, &sz, NULL, 0) != 0 ) {
+ fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
+ sysctl_path, strerror(errno));
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ } else {
+ cpuinfo_cycles_per_second = hz;
+ }
+ // TODO(csilvers): also figure out cpuinfo_num_cpus
+
+#elif defined(PLATFORM_WINDOWS)
+# pragma comment(lib, "shlwapi.lib") // for SHGetValue()
+ // In NT, read MHz from the registry. If we fail to do so or we're in win9x
+ // then make a crude estimate.
+ OSVERSIONINFO os;
+ os.dwOSVersionInfoSize = sizeof(os);
+ DWORD data, data_size = sizeof(data);
+ if (GetVersionEx(&os) &&
+ os.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ SUCCEEDED(SHGetValueA(HKEY_LOCAL_MACHINE,
+ "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
+ "~MHz", NULL, &data, &data_size)))
+ cpuinfo_cycles_per_second = (int64)data * (int64)(1000 * 1000); // was mhz
+ else
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(500); // TODO <500?
+
+ // Get the number of processors.
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ cpuinfo_num_cpus = info.dwNumberOfProcessors;
+
+#elif defined(__MACH__) && defined(__APPLE__)
+ // returning "mach time units" per second. the current number of elapsed
+ // mach time units can be found by calling uint64 mach_absolute_time();
+ // while not as precise as actual CPU cycles, it is accurate in the face
+ // of CPU frequency scaling and multi-cpu/core machines.
+ // Our mac users have these types of machines, and accuracy
+ // (i.e. correctness) trumps precision.
+ // See cycleclock.h: CycleClock::Now(), which returns number of mach time
+ // units on Mac OS X.
+ mach_timebase_info_data_t timebase_info;
+ mach_timebase_info(&timebase_info);
+ double mach_time_units_per_nanosecond =
+ static_cast<double>(timebase_info.denom) /
+ static_cast<double>(timebase_info.numer);
+ cpuinfo_cycles_per_second = mach_time_units_per_nanosecond * 1e9;
+
+ int num_cpus = 0;
+ size_t size = sizeof(num_cpus);
+ int numcpus_name[] = { CTL_HW, HW_NCPU };
+ if (::sysctl(numcpus_name, arraysize(numcpus_name), &num_cpus, &size, 0, 0)
+ == 0
+ && (size == sizeof(num_cpus)))
+ cpuinfo_num_cpus = num_cpus;
+
+#else
+ // Generic cycles per second counter
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+#endif
+}
+
+double CyclesPerSecond(void) {
+ InitializeSystemInfo();
+ return cpuinfo_cycles_per_second;
+}
+
+int NumCPUs(void) {
+ InitializeSystemInfo();
+ return cpuinfo_num_cpus;
+}
+
+// ----------------------------------------------------------------------
+// HasPosixThreads()
+// Return true if we're running POSIX (e.g., NPTL on Linux)
+// threads, as opposed to a non-POSIX thread libary. 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.
+// ----------------------------------------------------------------------
+bool HasPosixThreads() {
+#if defined(__linux__)
+#ifndef _CS_GNU_LIBPTHREAD_VERSION
+#define _CS_GNU_LIBPTHREAD_VERSION 3
+#endif
+ char buf[32];
+ // We assume that, if confstr() doesn't know about this name, then
+ // the same glibc is providing LinuxThreads.
+ if (confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)) == 0)
+ return false;
+ return strncmp(buf, "NPTL", 4) == 0;
+#elif defined(PLATFORM_WINDOWS) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+ return false;
+#else // other OS
+ return true; // Assume that everything else has Posix
+#endif // else OS_LINUX
+}
+
+// ----------------------------------------------------------------------
+
+#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<int>(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<uint32_t kMagic, uint32_t kLCSegment,
+ typename MachHeader, typename SegmentCommand>
+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<char*>(_dyld_get_image_name(current_image));
+ if (file_mapping) *file_mapping = 0;
+ if (file_pages) *file_pages = 0; // could we use sc->filesize?
+ if (anon_mapping) *anon_mapping = 0;
+ if (anon_pages) *anon_pages = 0;
+ if (dev) *dev = 0;
+ return true;
+ }
+
+ 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<char *>(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<char *>(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 (sscanf(stext_, "%"SCNx64"-%"SCNx64" %4s %"SCNx64" %x:%x %"SCNd64" %n",
+ start ? start : &tmpstart,
+ end ? end : &tmpend,
+ flags_,
+ offset ? offset : &tmpoffset,
+ &major, &minor,
+ inode ? inode : &tmpinode, &filename_offset) != 7) continue;
+#elif defined(__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<prmap_t*>(ibuf_);
+ // Best-effort attempt to get the inode from the filename. I think the
+ // two middle ints are major and minor device numbers, but I'm not sure.
+ sscanf(mapinfo->pr_mapname, "ufs.%*d.%*d.%ld", &inode_from_mapname);
+
+ if (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<int>(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<MH_MAGIC_64, LC_SEGMENT_64,
+ struct mach_header_64, struct segment_command_64>(
+ 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<MH_MAGIC, LC_SEGMENT,
+ struct mach_header, struct segment_command>(
+ 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<DWORD_PTR>(module_.modBaseAddr);
+ if (start) *start = base_addr;
+ if (end) *end = base_addr + module_.modBaseSize;
+ if (flags) *flags = kDefaultPerms;
+ if (offset) *offset = 0;
+ if (inode) *inode = 0;
+ if (filename) *filename = module_.szExePath;
+ if (file_mapping) *file_mapping = 0;
+ if (file_pages) *file_pages = 0;
+ if (anon_mapping) *anon_mapping = 0;
+ if (anon_pages) *anon_pages = 0;
+ if (dev) *dev = 0;
+ return true;
+ }
+#endif
+
+ // We didn't find anything
+ return false;
+}
+
+int ProcMapsIterator::FormatLine(char* buffer, int bufsize,
+ uint64 start, uint64 end, const char *flags,
+ uint64 offset, int64 inode,
+ const char *filename, dev_t dev) {
+ // We assume 'flags' looks like 'rwxp' or 'rwx'.
+ char r = (flags && flags[0] == 'r') ? 'r' : '-';
+ char w = (flags && flags[0] && flags[1] == 'w') ? 'w' : '-';
+ char x = (flags && flags[0] && flags[1] && flags[2] == 'x') ? 'x' : '-';
+ // p always seems set on linux, so we set the default to 'p', not '-'
+ char p = (flags && flags[0] && flags[1] && flags[2] && flags[3] != 'p')
+ ? '-' : 'p';
+
+ const int rc = snprintf(buffer, bufsize,
+ "%08"PRIx64"-%08"PRIx64" %c%c%c%c %08"PRIx64" %02x:%02x %-11"PRId64" %s\n",
+ start, end, r,w,x,p, offset,
+ static_cast<int>(dev/256), static_cast<int>(dev%256),
+ inode, filename);
+ return (rc < 0 || rc >= bufsize) ? 0 : rc;
+}
+
+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/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.h b/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.h
new file mode 100644
index 00000000000..7935855d67f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/sysinfo.h
@@ -0,0 +1,235 @@
+// 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 <config.h>
+
+#include <time.h>
+#if (defined(_WIN32) || defined(__MINGW32__)) && (!defined(__CYGWIN__) && !defined(__CYGWIN32__))
+#include <windows.h> // for DWORD
+#include <TlHelp32.h> // for CreateToolhelp32Snapshot
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for pid_t
+#endif
+#include <stddef.h> // for size_t
+#include <limits.h> // 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 NumCPUs();
+
+void SleepForMilliseconds(int milliseconds);
+
+// processor cycles per second of each processor. Thread-safe.
+extern double CyclesPerSecond(void);
+
+
+// Return true if we're running POSIX (e.g., NPTL on Linux) threads,
+// as opposed to a non-POSIX thread libary. 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):
+ // <start_addr(hex)>-<end_addr(hex)> <perms(rwxp)> <offset(hex)> +
+ // <major_dev(hex)>:<minor_dev(hex)> <inode> <filename> Note: the
+ // eg
+ // 08048000-0804c000 r-xp 00000000 03:01 3793678 /bin/cat
+ // If you don't have the dev_t (dev), feel free to pass in 0.
+ // (Next() doesn't return a dev_t, though NextExt does.)
+ //
+ // Note: if filename and flags were obtained via a call to Next(),
+ // then the output of this function is only valid if Next() returned
+ // true, and only until the iterator is destroyed or Next() is
+ // called again. (Since filename, at least, points into CurrentLine.)
+ static int FormatLine(char* buffer, int bufsize,
+ uint64 start, uint64 end, const char *flags,
+ uint64 offset, int64 inode, const char *filename,
+ dev_t dev);
+
+ // Find the next entry in /proc/maps; return true if found or false
+ // if at the end of the file.
+ //
+ // 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/chromium/third_party/tcmalloc/vendor/src/base/thread_annotations.h b/chromium/third_party/tcmalloc/vendor/src/base/thread_annotations.h
new file mode 100644
index 00000000000..f57b2999ee7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/thread_annotations.h
@@ -0,0 +1,134 @@
+// 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 GCC's "attributes" extension.
+// Using the macros defined here instead of the raw GCC 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(__GNUC__) \
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \
+ && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG))
+#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(x))
+
+#define SHARED_LOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x))
+
+#define EXCLUSIVE_TRYLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x))
+
+#define SHARED_TRYLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x))
+
+#define UNLOCK_FUNCTION(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock(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/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.c b/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.c
new file mode 100644
index 00000000000..bc180dba7a9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.c
@@ -0,0 +1,77 @@
+/* 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 <stdio.h> /* needed for NULL on some powerpc platforms (?!) */
+#ifdef HAVE_SYS_PRCTL
+# include <sys/prctl.h>
+#endif
+#include "base/thread_lister.h"
+#include "base/linuxthreads.h"
+/* Include other thread listers here that define THREADS macro
+ * 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 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 ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) {
+ return 1;
+}
+
+#endif /* ifndef THREADS */
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.h b/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.h
new file mode 100644
index 00000000000..6afe4dd1c72
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/thread_lister.h
@@ -0,0 +1,82 @@
+/* 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 <stdarg.h>
+#include <sys/types.h>
+
+#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 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
+ * 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 ListAllProcessThreads(void *parameter,
+ ListAllProcessThreadsCallBack callback, ...);
+
+/* This function resumes the list of all linux threads that
+ * 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 ResumeAllProcessThreads(int num_threads, pid_t *thread_pids);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _THREAD_LISTER_H */
diff --git a/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.cc b/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.cc
new file mode 100644
index 00000000000..767ee5f58f0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.cc
@@ -0,0 +1,189 @@
+// 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 <fcntl.h>
+#include <stddef.h> // for ptrdiff_t
+
+#include "base/atomicops.h" // for MemoryBarrier
+#include "base/linux_syscall_support.h"
+#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::GetCpuFn VDSOSupport::getcpu_fn_ = &InitAndGetCPU;
+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;
+ getcpu_fn_ = &GetCPUViaSyscall;
+ return NULL;
+ }
+ int fd = open("/proc/self/auxv", O_RDONLY);
+ if (fd == -1) {
+ // Kernel too old to have a VDSO.
+ vdso_base_ = NULL;
+ getcpu_fn_ = &GetCPUViaSyscall;
+ 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<void *>(aux.a_un.a_val);
+ break;
+ }
+ }
+ close(fd);
+ if (vdso_base_ == ElfMemImage::kInvalidBase) {
+ // Didn't find AT_SYSINFO_EHDR in auxv[].
+ vdso_base_ = NULL;
+ }
+ }
+ GetCpuFn fn = &GetCPUViaSyscall; // default if VDSO not present.
+ if (vdso_base_) {
+ VDSOSupport vdso;
+ SymbolInfo info;
+ if (vdso.LookupSymbol("__vdso_getcpu", "LINUX_2.6", STT_FUNC, &info)) {
+ // Casting from an int to a pointer is not legal C++. To emphasize
+ // this, we use a C-style cast rather than a C++-style cast.
+ fn = (GetCpuFn)(info.address);
+ }
+ }
+ // Subtle: this code runs outside of any locks; prevent compiler
+ // from assigning to getcpu_fn_ more than once.
+ base::subtle::MemoryBarrier();
+ getcpu_fn_ = fn;
+ 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);
+ // Also reset getcpu_fn_, so GetCPU could be tested with simulated VDSO.
+ getcpu_fn_ = &InitAndGetCPU;
+ 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);
+}
+
+// NOLINT on 'long' because this routine mimics kernel api.
+long VDSOSupport::GetCPUViaSyscall(unsigned *cpu, void *, void *) { // NOLINT
+#if defined(__NR_getcpu)
+ return sys_getcpu(cpu, NULL, NULL);
+#else
+ // x86_64 never implemented sys_getcpu(), except as a VDSO call.
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+// Use fast __vdso_getcpu if available.
+long VDSOSupport::InitAndGetCPU(unsigned *cpu, void *x, void *y) { // NOLINT
+ Init();
+ CHECK_NE(getcpu_fn_, &InitAndGetCPU); // << "Init() did not set getcpu_fn_";
+ return (*getcpu_fn_)(cpu, x, y);
+}
+
+// This function must be very fast, and may be called from very
+// low level (e.g. tcmalloc). Hence I avoid things like
+// GoogleOnceInit() and ::operator new.
+int GetCPU(void) {
+ unsigned cpu;
+ int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, NULL, NULL);
+ return ret_code == 0 ? cpu : ret_code;
+}
+
+// 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/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.h b/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.h
new file mode 100644
index 00000000000..b97ab254d38
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/base/vdso_support.h
@@ -0,0 +1,155 @@
+// 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<FN>(info.address);
+// }
+
+#ifndef BASE_VDSO_SUPPORT_H_
+#define BASE_VDSO_SUPPORT_H_
+
+#include <config.h>
+#include "base/basictypes.h"
+#include "base/elf_mem_image.h"
+
+#ifdef HAVE_ELF_MEM_IMAGE
+
+#define HAVE_VDSO_SUPPORT 1
+
+#include <stdlib.h> // 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_;
+
+ // NOLINT on 'long' because these routines mimic kernel api.
+ // The 'cache' parameter may be used by some versions of the kernel,
+ // and should be NULL or point to a static buffer containing at
+ // least two 'long's.
+ static long InitAndGetCPU(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+ static long GetCPUViaSyscall(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+ typedef long (*GetCpuFn)(unsigned *cpu, void *cache, // NOLINT 'long'.
+ void *unused);
+
+ // This function pointer may point to InitAndGetCPU,
+ // GetCPUViaSyscall, or __vdso_getcpu at different stages of initialization.
+ static GetCpuFn getcpu_fn_;
+
+ friend int GetCPU(void); // Needs access to getcpu_fn_.
+
+ DISALLOW_COPY_AND_ASSIGN(VDSOSupport);
+};
+
+// Same as sched_getcpu() on later glibc versions.
+// Return current CPU, using (fast) __vdso_getcpu@LINUX_2.6 if present,
+// otherwise use syscall(SYS_getcpu,...).
+// May return -1 with errno == ENOSYS if the kernel doesn't
+// support SYS_getcpu.
+int GetCPU();
+} // namespace base
+
+#endif // HAVE_ELF_MEM_IMAGE
+
+#endif // BASE_VDSO_SUPPORT_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/central_freelist.cc b/chromium/third_party/tcmalloc/vendor/src/central_freelist.cc
new file mode 100644
index 00000000000..87a1825c02b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/central_freelist.cc
@@ -0,0 +1,376 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include <algorithm>
+#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<uintptr_t>(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);
+ Event(span, 'N', 0);
+ }
+
+ // 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<<kPageShift) /
+ Static::sizemap()->ByteSizeForClass(span->sizeclass));
+ }
+
+ counter_++;
+ span->refcount--;
+ if (span->refcount == 0) {
+ Event(span, '#', 0);
+ counter_ -= ((span->length<<kPageShift) /
+ Static::sizemap()->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<void**>(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 >= kNumClasses) {
+ while (t >= kNumClasses) {
+ t -= kNumClasses;
+ }
+ race_counter = t;
+ }
+ ASSERT(t >= 0);
+ ASSERT(t < kNumClasses);
+ 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;
+ void* head = NULL;
+ void* tail = NULL;
+ // TODO: Prefetch multiple TCEntries?
+ tail = FetchFromSpansSafe();
+ if (tail != NULL) {
+ SLL_SetNext(tail, NULL);
+ head = tail;
+ result = 1;
+ while (result < N) {
+ void *t = FetchFromSpans();
+ if (!t) break;
+ SLL_Push(&head, t);
+ result++;
+ }
+ }
+ lock_.Unlock();
+ *start = head;
+ *end = tail;
+ return result;
+}
+
+
+void* CentralFreeList::FetchFromSpansSafe() {
+ void *t = FetchFromSpans();
+ if (!t) {
+ Populate();
+ t = FetchFromSpans();
+ }
+ return t;
+}
+
+void* CentralFreeList::FetchFromSpans() {
+ if (tcmalloc::DLL_IsEmpty(&nonempty_)) return NULL;
+ Span* span = nonempty_.next;
+
+ ASSERT(span->objects != NULL);
+ span->refcount++;
+ void* result = span->objects;
+ span->objects = *(reinterpret_cast<void**>(result));
+ if (span->objects == NULL) {
+ // Move to empty list
+ tcmalloc::DLL_Remove(span);
+ tcmalloc::DLL_Prepend(&empty_, span);
+ Event(span, 'E', 0);
+ }
+ counter_--;
+ 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()->CacheSizeClass(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<char*>(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<void**>(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/chromium/third_party/tcmalloc/vendor/src/central_freelist.h b/chromium/third_party/tcmalloc/vendor/src/central_freelist.h
new file mode 100644
index 00000000000..4fd5799de9a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/central_freelist.h
@@ -0,0 +1,200 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_CENTRAL_FREELIST_H_
+#define TCMALLOC_CENTRAL_FREELIST_H_
+
+#include "config.h"
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // 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();
+
+ 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.
+ void* FetchFromSpans() 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.
+ void* FetchFromSpansSafe() 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<int kFreeListSizeMod64>
+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/chromium/third_party/tcmalloc/vendor/src/common.cc b/chromium/third_party/tcmalloc/vendor/src/common.cc
new file mode 100644
index 00000000000..dad7372ffef
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/common.cc
@@ -0,0 +1,202 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include "common.h"
+#include "system-alloc.h"
+
+namespace tcmalloc {
+
+// 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 >= 16) {
+ // We need an alignment of at least 16 bytes to satisfy
+ // requirements for some SSE types.
+ alignment = 16;
+ }
+ // Maximum alignment allowed is page size alignment.
+ if (alignment > kPageSize) {
+ alignment = kPageSize;
+ }
+ CHECK_CONDITION(size < 16 || alignment >= 16);
+ 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<int>(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 > 32) num = 32;
+
+ return num;
+}
+
+// Initialize the mapping arrays
+void SizeMap::Init() {
+ // 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 <= 16);
+ 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++;
+ }
+ if (sc != kNumClasses) {
+ Log(kCrash, __FILE__, __LINE__,
+ "wrong number of size classes: (found vs. expected )", sc, kNumClasses);
+ }
+
+ // Initialize the mapping arrays
+ int next_size = 0;
+ for (int c = 1; c < kNumClasses; 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; size++) {
+ const int sc = SizeClass(size);
+ if (sc <= 0 || sc >= kNumClasses) {
+ 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);
+ }
+ }
+
+ // Initialize the num_objects_to_move array.
+ for (size_t cl = 1; cl < kNumClasses; ++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;
+void* MetaDataAlloc(size_t bytes) {
+ void* result = TCMalloc_SystemAlloc(bytes, NULL);
+ if (result != NULL) {
+ metadata_system_bytes_ += bytes;
+ }
+ return result;
+}
+
+uint64_t metadata_system_bytes() { return metadata_system_bytes_; }
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/vendor/src/common.h b/chromium/third_party/tcmalloc/vendor/src/common.h
new file mode 100644
index 00000000000..49458f24a14
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/common.h
@@ -0,0 +1,246 @@
+// 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 <opensource@google.com>
+//
+// Common definitions for tcmalloc code.
+
+#ifndef TCMALLOC_COMMON_H_
+#define TCMALLOC_COMMON_H_
+
+#include "config.h"
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t, uint64_t
+#endif
+#include "internal_logging.h" // for ASSERT, 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
+//-------------------------------------------------------------------
+
+// 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_LARGE_PAGES)
+static const size_t kPageShift = 15;
+static const size_t kNumClasses = 78;
+#else
+static const size_t kPageShift = 13;
+static const size_t kNumClasses = 86;
+#endif
+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;
+static const size_t kLargeSizeClass = 0;
+// For all span-lengths < kMaxPages we keep an exact-size list.
+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<Length>(0)) >> kPageShift;
+
+#if defined __x86_64__
+// All current and planned x86_64 processors only look at the lower 48 bits
+// in virtual to physical address translation. The top 16 are thus unused.
+// TODO(rus): Under what operating systems can we increase it safely to 17?
+// This lets us use smaller page maps. On first allocation, a 36-bit page map
+// uses only 96 KB instead of the 4.5 MB used by a 52-bit page map.
+static const int kAddressBits = (sizeof(void*) < 8 ? (8 * sizeof(void*)) : 48);
+#else
+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:
+ // 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_[kNumClasses];
+
+ //-------------------------------------------------------------------
+ // 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];
+
+ // Compute index of the class_array[] entry for a given size
+ static inline int ClassIndex(int s) {
+ ASSERT(0 <= s);
+ ASSERT(s <= kMaxSize);
+ const bool big = (s > kMaxSmallSize);
+ const int add_amount = big ? (127 + (120<<7)) : 7;
+ const int shift_amount = big ? 7 : 3;
+ return (s + add_amount) >> shift_amount;
+ }
+
+ int NumMoveSize(size_t size);
+
+ // Mapping from size class to max size storable in that class
+ size_t class_to_size_[kNumClasses];
+
+ // Mapping from size class to number of pages to allocate at a time
+ size_t class_to_pages_[kNumClasses];
+
+ public:
+ // 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(int size) {
+ return class_array_[ClassIndex(size)];
+ }
+
+ // Get the byte-size for a specified class
+ inline size_t ByteSizeForClass(size_t cl) {
+ return class_to_size_[cl];
+ }
+
+ // Mapping from size class to max size storable in that class
+ inline size_t class_to_size(size_t 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(size_t 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(size_t 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/chromium/third_party/tcmalloc/vendor/src/config.h.in b/chromium/third_party/tcmalloc/vendor/src/config.h.in
new file mode 100644
index 00000000000..4eed17ab83b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/config.h.in
@@ -0,0 +1,274 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+
+#ifndef GPERFTOOLS_CONFIG_H_
+#define GPERFTOOLS_CONFIG_H_
+
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+#undef HAVE_BUILTIN_STACK_POINTER
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+#undef HAVE_CONFLICT_SIGNAL_H
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_UNAME
+
+/* 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 <dlfcn.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+#undef HAVE_LIBUNWIND_H
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#undef HAVE_LINUX_PTRACE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if the compiler implements namespaces */
+#undef HAVE_NAMESPACES
+
+/* Define to 1 if you have the <poll.h> 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
+
+/* Define to 1 if you have the <pwd.h> 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 <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if compiler supports __thread */
+#undef HAVE_TLS
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#undef HAVE_UNWIND_H
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+#undef HAVE___INT64
+
+/* 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 in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 'volatile' if __malloc_hook is declared volatile */
+#undef MALLOC_HOOK_MAYBE_VOLATILE
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* 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
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIdS
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIuS
+
+/* printf format code for printing a size_t and ssize_t */
+#undef PRIxS
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#undef STL_NAMESPACE
+
+/* Version number of package */
+#undef VERSION
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+
+#ifdef __MINGW32__
+#include "windows/mingw.h"
+#endif
+
+#endif /* #ifndef GPERFTOOLS_CONFIG_H_ */
+
diff --git a/chromium/third_party/tcmalloc/vendor/src/config_for_unittests.h b/chromium/third_party/tcmalloc/vendor/src/config_for_unittests.h
new file mode 100644
index 00000000000..b418dbf2708
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/config_for_unittests.h
@@ -0,0 +1,64 @@
+// 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/chromium/third_party/tcmalloc/vendor/src/debugallocation.cc b/chromium/third_party/tcmalloc/vendor/src/debugallocation.cc
new file mode 100644
index 00000000000..70ec162bc72
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/debugallocation.cc
@@ -0,0 +1,1420 @@
+// 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 <opensource@google.com>
+
+#include "config.h"
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#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 <malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# endif
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gperftools/malloc_extension.h>
+#include <gperftools/malloc_hook.h>
+#include <gperftools/stacktrace.h>
+#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"
+
+#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_FRANCE_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)));
+
+// The do_* functions are defined in tcmalloc/tcmalloc.cc,
+// which is included before this file
+// when TCMALLOC_FOR_DEBUGALLOCATION is defined
+// TODO(csilvers): get rid of these now that we are tied to tcmalloc.
+#define BASE_MALLOC_NEW do_malloc
+#define BASE_MALLOC do_malloc
+#define BASE_FREE do_free
+#define BASE_MALLOC_STATS do_malloc_stats
+#define BASE_MALLOPT do_mallopt
+#define BASE_MALLINFO do_mallinfo
+
+// ========================================================================= //
+
+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 <typename QueueEntry>
+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 =
+ GetStackTrace(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 BASE_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 int kMagicMalloc = 0xDEADBEEF;
+ static const int 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 BASE_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_;
+ int 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<int> 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<MallocBlockQueueEntry>* 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(int value) const {
+ return kMagicMMap == value || kMagicMalloc == value;
+ }
+
+ static size_t real_malloced_size(size_t size) {
+ return size + sizeof(MallocBlock);
+ }
+ static size_t real_mmapped_size(size_t size) {
+ return size + MallocBlock::data_offset();
+ }
+
+ 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_);
+ }
+
+ int* magic2_addr() { return (int*)(size2_addr() + 1); }
+ const int* magic2_addr() const { return (const int*)(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 = BASE_MALLOC(sizeof(AllocMap));
+ alloc_map_ = new(p) AllocMap(BASE_MALLOC, BASE_FREE);
+ }
+ alloc_map_->Insert(data_addr(), type);
+ // initialize us
+ size1_ = size;
+ offset_ = 0;
+ alloc_type_ = type;
+ if (!IsMMapped()) {
+ *magic2_addr() = magic1_;
+ *size2_addr() = size;
+ }
+ alloc_map_lock_.Unlock();
+ memset(data_addr(), kMagicUninitializedByte, size);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "should hold");
+ RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
+ }
+ }
+
+ size_t CheckAndClear(int type) {
+ alloc_map_lock_.Lock();
+ CheckLocked(type);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "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();
+ 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 (size1_ != *size2_addr()) {
+ RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
+ "has been corrupted", data_addr());
+ }
+ if (!IsValidMagicValue(*magic2_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: %"PRIuS"", 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*) (type == kMallocType ?
+ BASE_MALLOC(real_malloced_size(size)) :
+ BASE_MALLOC_NEW(real_malloced_size(size)));
+ }
+#else
+ b = (MallocBlock*) (type == kMallocType ?
+ BASE_MALLOC(real_malloced_size(size)) :
+ BASE_MALLOC_NEW(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) {
+ if (IsMMapped()) { // have to do this before CheckAndClear
+#ifdef HAVE_MMAP
+ int size = CheckAndClear(type);
+ 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);
+ 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<MallocBlockQueueEntry>;
+ 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]);
+ BASE_FREE(entries[i].block);
+ }
+ num_entries = 0;
+ free_queue_lock_.Lock();
+ }
+ }
+ RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
+ free_queue_lock_.Unlock();
+ for (int i = 0; i < num_entries; i++) {
+ CheckForDanglingWrites(entries[i]);
+ BASE_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<unsigned char*>(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<void*>(
+ 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<char*>(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<char*>(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<MallocBlock *>(
+ reinterpret_cast<char *>(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 memalign, and
+ // mb->offset_ is the distance backwards to the real header from mb,
+ // which is a fake header. The following subtraction works for both zero
+ // and non-zero values.
+ return reinterpret_cast<MallocBlock *>(
+ reinterpret_cast<char *>(mb) - mb->offset_);
+ }
+ static const MallocBlock* FromRawPointer(const void* p) {
+ // const-safe version: we just cast about
+ return FromRawPointer(const_cast<void*>(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 int MallocBlock::kMagicMalloc;
+const int MallocBlock::kMagicMMap;
+
+MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
+SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
+
+FreeQueue<MallocBlockQueueEntry>* 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];
+ 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
+ trace_fd = open("/tmp/google.alloc", O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (trace_fd == -1) {
+ trace_fd = 2;
+ TracePrintf(trace_fd,
+ "Can't open /tmp/google.alloc. Logging to stderr.\n");
+ }
+ // Add a header to the log.
+ TracePrintf(trace_fd, "Trace started: %lu\n",
+ static_cast<unsigned long>(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%"PRIuS"\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) {
+ MALLOC_TRACE("free",
+ (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
+ ptr);
+ if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type);
+}
+
+// ========================================================================= //
+
+// 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) {
+ const MallocBlock* mb = MallocBlock::FromRawPointer(p);
+ return TCMallocImplementation::GetOwnership(mb);
+ }
+ return MallocExtension::kNotOwned; // nobody owns NULL
+ }
+
+ virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* 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<size_t>::max();
+ i.total_bytes_free = MallocBlock::FreeQueueSize();
+ v->push_back(i);
+ }
+
+ };
+
+static DebugMallocImplementation debug_malloc_implementation;
+
+REGISTER_MODULE_INITIALIZER(debugallocation, {
+ // 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()) {
+ MallocExtension::Register(&debug_malloc_implementation);
+ }
+});
+
+REGISTER_MODULE_DESTRUCTOR(debugallocation, {
+ if (!RunningOnValgrind()) {
+ // When the program exits, check all blocks still in the free
+ // queue for corruption.
+ DanglingWriteChecker();
+ }
+});
+
+// ========================================================================= //
+
+// 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) {
+ for (;;) {
+ void* p = DebugAllocate(size, new_type);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ 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 p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
+ return tc_new_mode ? debug_cpp_alloc(size, MallocBlock::kMallocType, true)
+ : DebugAllocate(size, MallocBlock::kMallocType);
+}
+
+// Exported routines
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) __THROW {
+ // 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW {
+ 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);
+ 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;
+
+ memcpy(p->data_addr(), old->data_addr(),
+ (old->data_size() < size) ? old->data_size() : size);
+ MallocHook::InvokeDeleteHook(ptr);
+ MallocHook::InvokeNewHook(p->data_addr(), size);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+ 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 %"PRIuS" bytes: new failed.", size);
+ }
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kNewType);
+}
+
+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 %"PRIuS" bytes: new[] failed.", size);
+ }
+ return ptr;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
+ __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ DebugDeallocate(p, MallocBlock::kArrayNewType);
+}
+
+// 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);
+}
+
+// This is mostly the same as do_memalign in tcmalloc.cc.
+static void *do_debug_memalign(size_t alignment, size_t size) {
+ // 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, MallocBlock::kMallocType);
+ if (p != 0) {
+ intptr_t orig_p = reinterpret_cast<intptr_t>(p);
+ // Leave data_offset bytes for fake header, and round up to meet
+ // alignment.
+ p = reinterpret_cast<void *>(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<MallocBlock *>(
+ reinterpret_cast<char *>(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.
+ fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
+ }
+ return p;
+}
+
+// This is mostly the same as cpp_memalign in tcmalloc.cc.
+static void* debug_cpp_memalign(size_t align, size_t size) {
+ for (;;) {
+ void* p = do_debug_memalign(align, size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh)
+ return 0;
+
+ // 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&) {
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
+ size_t size) {
+ return tc_new_mode ? debug_cpp_memalign(align, size)
+ : do_debug_memalign(align, size);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) __THROW {
+ void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ 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)
+ __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
+
+ void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
+ 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) __THROW {
+ // Allocate >= size bytes starting on a page boundary
+ void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
+ // 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);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+// malloc_stats just falls through to the base implementation.
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
+ BASE_MALLOC_STATS();
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
+ return BASE_MALLOPT(cmd, value);
+}
+
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
+ return BASE_MALLINFO();
+}
+#endif
+
+extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
+ return MallocExtension::instance()->GetAllocatedSize(ptr);
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/getpc.h b/chromium/third_party/tcmalloc/vendor/src/getpc.h
new file mode 100644
index 00000000000..9fb2e162beb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/getpc.h
@@ -0,0 +1,186 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This is an internal header file used by profiler.cc. It defines
+// the single (inline) function GetPC. GetPC is used in a signal
+// handler to figure out the instruction that was being executed when
+// the signal-handler was triggered.
+//
+// To get this, we use the ucontext_t argument to the signal-handler
+// callback, which holds the full context of what was going on when
+// the signal triggered. How to get from a ucontext_t to a Program
+// Counter is OS-dependent.
+
+#ifndef BASE_GETPC_H_
+#define BASE_GETPC_H_
+
+#include "config.h"
+
+// On many linux systems, we may need _GNU_SOURCE to get access to
+// the defined constants that define the register we want to see (eg
+// REG_EIP). Note this #define must come first!
+#define _GNU_SOURCE 1
+// If #define _GNU_SOURCE causes problems, this might work instead.
+// It will cause problems for FreeBSD though!, because it turns off
+// the needed __BSD_VISIBLE.
+//#define _XOPEN_SOURCE 500
+
+#include <string.h> // for memcmp
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h> // for ucontext_t (and also mcontext_t)
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+#include <cygwin/signal.h>
+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.
+ char ins[16];
+ // How many bytes to match from ins array?
+ int ins_size;
+ // The offset from the stack pointer (e)sp where to look for the
+ // call return address. Interpreted as bytes.
+ int return_sp_offset;
+};
+
+
+// The dereferences needed to get the PC from a struct ucontext were
+// determined at configure time, and stored in the macro
+// PC_FROM_UCONTEXT in config.h. The only thing we need to do here,
+// then, is to do the magic call-unrolling for systems that support it.
+
+// -- Special case 1: linux x86, for which we have CallUnrollInfo
+#if defined(__linux) && defined(__i386) && defined(__GNUC__)
+static const CallUnrollInfo callunrollinfo[] = {
+ // Entry to a function: push %ebp; mov %esp,%ebp
+ // Top-of-stack contains the caller IP.
+ { 0,
+ {0x55, 0x89, 0xe5}, 3,
+ 0
+ },
+ // Entry to a function, second instruction: push %ebp; mov %esp,%ebp
+ // Top-of-stack contains the old frame, caller IP is +4.
+ { -1,
+ {0x55, 0x89, 0xe5}, 3,
+ 4
+ },
+ // Return from a function: RET.
+ // Top-of-stack contains the caller IP.
+ { 0,
+ {0xc3}, 1,
+ 0
+ }
+};
+
+inline void* GetPC(const ucontext_t& signal_ucontext) {
+ // See comment above struct CallUnrollInfo. Only try instruction
+ // flow matching if both eip and esp looks reasonable.
+ const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP];
+ const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP];
+ if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 &&
+ (esp & 0xffff0000) != 0) {
+ char* eip_char = reinterpret_cast<char*>(eip);
+ for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) {
+ if (!memcmp(eip_char + callunrollinfo[i].pc_offset,
+ callunrollinfo[i].ins, callunrollinfo[i].ins_size)) {
+ // We have a match.
+ void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset);
+ return *retaddr;
+ }
+ }
+ }
+ return (void*)eip;
+}
+
+// Special case #2: Windows, which has to do something totally different.
+#elif defined(_WIN32) || 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) {
+ return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h
+}
+
+#endif
+
+#endif // BASE_GETPC_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/heap-checker.h b/chromium/third_party/tcmalloc/vendor/src/google/heap-checker.h
new file mode 100644
index 00000000000..8aa5ea49ca9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/heap-checker.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/heap-checker.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/heap-profiler.h b/chromium/third_party/tcmalloc/vendor/src/google/heap-profiler.h
new file mode 100644
index 00000000000..be4395964f4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/heap-profiler.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/heap-profiler.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension.h b/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension.h
new file mode 100644
index 00000000000..55150e5a49a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/malloc_extension.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h b/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h
new file mode 100644
index 00000000000..87d727b3943
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/malloc_extension_c.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook.h b/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook.h
new file mode 100644
index 00000000000..e5b8e7cb001
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/malloc_hook.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook_c.h b/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook_c.h
new file mode 100644
index 00000000000..e3ac0a49997
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/malloc_hook_c.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/malloc_hook_c.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/profiler.h b/chromium/third_party/tcmalloc/vendor/src/google/profiler.h
new file mode 100644
index 00000000000..67a89c198b1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/profiler.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/profiler.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/stacktrace.h b/chromium/third_party/tcmalloc/vendor/src/google/stacktrace.h
new file mode 100644
index 00000000000..eb761cab4e0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/stacktrace.h
@@ -0,0 +1,33 @@
+// 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.
+ */
+#include <gperftools/stacktrace.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/google/tcmalloc.h b/chromium/third_party/tcmalloc/vendor/src/google/tcmalloc.h
new file mode 100644
index 00000000000..c7db6319426
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/google/tcmalloc.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/tcmalloc.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-checker.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-checker.h
new file mode 100644
index 00000000000..32ed10a8232
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-checker.h
@@ -0,0 +1,424 @@
+// 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 doc/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 <sys/types.h> // 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 <stdint.h> // for uintptr_t
+#endif
+#include <stdarg.h> // for va_list
+#include <vector>
+
+// 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 <typename T>
+ static T* IgnoreObject(T* ptr) {
+ DoIgnoreObject(static_cast<const void*>(const_cast<const T*>(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();
+ // TODO(csilvers): remove this one, at least
+ friend int main(int, char**);
+
+
+ // 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 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 ListAllProcessThreads.
+ // Here we only use num_threads and thread_pids, that 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 T>
+class HiddenPointer {
+ public:
+ explicit HiddenPointer(T* t)
+ : masked_t_(reinterpret_cast<uintptr_t>(t) ^ kHideMask) {
+ }
+ // Returns unhidden pointer. Be careful where you save the result.
+ T* get() const { return reinterpret_cast<T*>(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<uintptr_t>(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<void_function>* 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/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h
new file mode 100644
index 00000000000..57cb97a1c9c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h
@@ -0,0 +1,104 @@
+/* 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 doc/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 <stddef.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
+
+/* 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/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h
new file mode 100644
index 00000000000..b180115ff34
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h
@@ -0,0 +1,420 @@
+// 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 <opensource@google.com>
+//
+// 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 <stddef.h>
+// 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 <stdint.h>
+#endif
+#include <string>
+#include <vector>
+
+// 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 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 current state of the malloc
+ // data structures. 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.
+ // 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.
+ //
+ // 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<FreeListInfo>* 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();
+};
+
+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/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h
new file mode 100644
index 00000000000..72a0a7c1733
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h
@@ -0,0 +1,99 @@
+/* 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 <stddef.h>
+#include <sys/types.h>
+
+/* 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);
+
+/*
+ * 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/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h
new file mode 100644
index 00000000000..b99c047cd5d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h
@@ -0,0 +1,358 @@
+// 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 <stddef.h>
+#include <sys/types.h>
+extern "C" {
+#include <gperftools/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/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook_c.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/malloc_hook_c.h
new file mode 100644
index 00000000000..56337e15e83
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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 <stddef.h>
+#include <sys/types.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
+
+#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/chromium/third_party/tcmalloc/vendor/src/gperftools/profiler.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/profiler.h
new file mode 100644
index 00000000000..7971e04442f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/profiler.h
@@ -0,0 +1,168 @@
+/* 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 doc/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
+ * "PROFILE" 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 <path_to_executable> <profile_file_name>
+ * % pprof --gv <path_to_executable> <profile_file_name>
+ *
+ * These functions are thread-safe.
+ */
+
+#ifndef BASE_PROFILER_H_
+#define BASE_PROFILER_H_
+
+#include <time.h> /* 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 sucessfully, 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();
+
+/* 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();
+
+
+/* DEPRECATED: these functions were used to enable/disable profiling
+ * in the current thread, but no longer do anything.
+ */
+PERFTOOLS_DLL_DECL void ProfilerEnable();
+PERFTOOLS_DLL_DECL void ProfilerDisable();
+
+/* Returns nonzero if profile is currently enabled, zero if it's not. */
+PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads();
+
+/* Routine for registering new threads with the profiler.
+ */
+PERFTOOLS_DLL_DECL void ProfilerRegisterThread();
+
+/* 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);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* BASE_PROFILER_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/gperftools/stacktrace.h b/chromium/third_party/tcmalloc/vendor/src/gperftools/stacktrace.h
new file mode 100644
index 00000000000..fd186d63a1b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/stacktrace.h
@@ -0,0 +1,116 @@
+// 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/chromium/third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in b/chromium/third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in
new file mode 100644
index 00000000000..dbca6ec07fe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// 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@"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if @ac_cv_have_struct_mallinfo@
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/heap-checker-bcad.cc b/chromium/third_party/tcmalloc/vendor/src/heap-checker-bcad.cc
new file mode 100644
index 00000000000..7ed6942c07f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/heap-checker-bcad.cc
@@ -0,0 +1,92 @@
+// 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 <stdlib.h> // for abort()
+#include <gperftools/malloc_extension.h>
+
+// 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/chromium/third_party/tcmalloc/vendor/src/heap-checker.cc b/chromium/third_party/tcmalloc/vendor/src/heap-checker.cc
new file mode 100644
index 00000000000..5967b02a47e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/heap-checker.cc
@@ -0,0 +1,2377 @@
+// 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 <fcntl.h> // for O_RDONLY (we use syscall to do actual reads)
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <assert.h>
+
+#if defined(HAVE_LINUX_PTRACE_H)
+#include <linux/ptrace.h>
+#endif
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
+#include <wtypes.h>
+#include <winbase.h>
+#undef ERROR // windows defines these as macros, which can cause trouble
+#undef max
+#undef min
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <algorithm>
+#include <functional>
+
+#include <gperftools/heap-checker.h>
+
+#include "base/basictypes.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include <gperftools/stacktrace.h>
+#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 <gperftools/malloc_hook.h>
+#include <gperftools/malloc_extension.h>
+#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 bool ProfilingIsEnabledForAllThreads();
+bool 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_int32(heap_check_error_exit_code,
+ EnvToInt("HEAP_CHECK_ERROR_EXIT_CODE", 1),
+ "Exit code to return if any leaks were detected.");
+
+//----------------------------------------------------------------------
+
+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 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<typename T> static void DeleteAndNull(T** p) {
+ (*p)->~T();
+ Free(*p);
+ *p = NULL;
+ }
+ template<typename T> 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<uintptr_t, size_t, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, size_t>,
+ 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<AllocObject,
+ STL_Allocator<AllocObject, HeapLeakChecker::Allocator>
+ > LiveObjectsStack;
+static LiveObjectsStack* live_objects = NULL;
+
+// A special string type that uses my allocator
+typedef basic_string<char, char_traits<char>,
+ STL_Allocator<char, HeapLeakChecker::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<HCL_string, LiveObjectsStack, less<HCL_string>,
+ STL_Allocator<pair<const HCL_string, LiveObjectsStack>,
+ 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<uintptr_t, HeapLeakChecker::RangeValue, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, HeapLeakChecker::RangeValue>,
+ 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<uintptr_t, less<uintptr_t>,
+ STL_Allocator<uintptr_t, HeapLeakChecker::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<uintptr_t, uintptr_t, less<uintptr_t>,
+ STL_Allocator<pair<const uintptr_t, uintptr_t>,
+ 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*)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<typename T>
+inline static const void* AsPtr(T addr) {
+ return reinterpret_cast<void*>(addr);
+}
+inline static uintptr_t AsInt(const void* ptr) {
+ return reinterpret_cast<uintptr_t>(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 %"PRIuS "; %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 %"PRIuS"", 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, &region)) {
+ // 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 %"PRIuS" bytes at %p"
+ ": have stack inside: %p",
+ (stack_disable ? "stack" : "range"),
+ info.object_size, ptr, AsPtr(*iter));
+ return;
+ }
+ }
+ RAW_VLOG(11, "%s-disabling %"PRIuS" 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).
+//
+/*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<void*, STL_Allocator<void*, Allocator> > 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]);
+#if (defined(__i386__) || defined(__x86_64)) && \
+ defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER)
+ i386_regs thread_regs;
+#define sys_ptrace(r, p, a, d) syscall(SYS_ptrace, (r), (p), (a), (d))
+ // We use sys_ptrace to avoid thread locking
+ // because this is called from 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<void*>(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<void**>(&thread_regs);
+ p < reinterpret_cast<void**>(&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 %"PRIuS" 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:
+ 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 %"PRIuS" 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 %"PRIuS" 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<uintptr_t>(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 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!");
+ }
+ 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
+ // ListAllProcessThreads, so that CPU profiler can collect all its samples.
+ // The machinery of 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() &&
+ ListAllProcessThreads(NULL, IsOneThread) == 1;
+ // When the normal path of 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)
+ : 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<const char*>(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 %"PRIuS" 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<uintptr_t>(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<char*>(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<const uintptr_t*>(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<const void*>(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 %"PRIuS" bytes at %p "
+ "inside %p of size %"PRIuS"",
+ 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 %"PRIuS" 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 %"PRIuS" 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<char*>(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: %"PRIuS" bytes "
+ "in %"PRIuS" 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
+extern char* program_invocation_name;
+extern char* program_invocation_short_name;
+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 "<your binary>"; }
+static string invocation_path() { return "<your binary>"; }
+#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<HeapProfileTable::Snapshot*>(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<ssize_t>(leaks->total().alloc_size);
+ inuse_allocs_increase_ = static_cast<ssize_t>(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<HeapProfileTable::Snapshot*>(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::void_function>* 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<HeapCleaner::void_function>;
+ 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=<mode>.");
+ }
+ }
+
+ // 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.
+#ifdef __FreeBSD__
+ FLAGS_heap_check_after_destructors = true;
+#endif
+
+ { 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 <this_binary> | 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");
+ // We don't want to call atexit() routines!
+ _exit(FLAGS_heap_check_error_exit_code);
+ }
+ 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);
+ // 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);
+ 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/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.cc b/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.cc
new file mode 100644
index 00000000000..8b2ed337b20
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.cc
@@ -0,0 +1,696 @@
+// 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 <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#include <fcntl.h> // for open()
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#ifndef GLOB_NOMATCH // true on some old cygwins
+# define GLOB_NOMATCH 0
+#endif
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // for PRIxPTR
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#include <errno.h>
+#include <stdarg.h>
+#include <string>
+#include <map>
+#include <algorithm> // for sort(), equal(), and copy()
+
+#include "heap-profile-table.h"
+
+#include "base/logging.h"
+#include "raw_printer.h"
+#include "symbolize.h"
+#include <gperftools/stacktrace.h>
+#include <gperftools/malloc_hook.h>
+#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";
+
+//----------------------------------------------------------------------
+
+// Size for alloc_table_ and mmap_table_.
+static const int kHashTableSize = 179999;
+/*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)
+ : alloc_(alloc), dealloc_(dealloc) {
+ // Initialize the overall profile stats.
+ memset(&total_, 0, sizeof(total_));
+
+ // Make the malloc table.
+ const int alloc_table_bytes = kHashTableSize * sizeof(*alloc_table_);
+ alloc_table_ = reinterpret_cast<Bucket**>(alloc_(alloc_table_bytes));
+ memset(alloc_table_, 0, alloc_table_bytes);
+ num_alloc_buckets_ = 0;
+
+ // Initialize the mmap table.
+ mmap_table_ = NULL;
+ num_available_mmap_buckets_ = 0;
+
+ // Make malloc and mmap allocation maps.
+ alloc_address_map_ =
+ new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
+ mmap_address_map_ = NULL;
+}
+
+HeapProfileTable::~HeapProfileTable() {
+ DeallocateBucketTable(alloc_table_);
+ alloc_table_ = NULL;
+ DeallocateBucketTable(mmap_table_);
+ mmap_table_ = NULL;
+ DeallocateAllocationMap(alloc_address_map_);
+ alloc_address_map_ = NULL;
+ DeallocateAllocationMap(mmap_address_map_);
+ mmap_address_map_ = NULL;
+}
+
+void HeapProfileTable::DeallocateAllocationMap(AllocationMap* allocation) {
+ if (allocation != NULL) {
+ alloc_address_map_->~AllocationMap();
+ dealloc_(allocation);
+ }
+}
+
+void HeapProfileTable::DeallocateBucketTable(Bucket** table) {
+ if (table != NULL) {
+ for (int b = 0; b < kHashTableSize; b++) {
+ for (Bucket* x = table[b]; x != 0; /**/) {
+ Bucket* b = x;
+ x = x->next;
+ dealloc_(b->stack);
+ dealloc_(b);
+ }
+ }
+ dealloc_(table);
+ }
+}
+
+HeapProfileTable::Bucket* HeapProfileTable::GetBucket(
+ int depth, const void* const key[], Bucket** table,
+ int* bucket_count) {
+ // Make hash-value
+ uintptr_t h = 0;
+ for (int i = 0; i < depth; i++) {
+ h += reinterpret_cast<uintptr_t>(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 = 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<const void**>(alloc_(key_size));
+ copy(key, key + depth, kcopy);
+ Bucket* b = reinterpret_cast<Bucket*>(alloc_(sizeof(Bucket)));
+ memset(b, 0, sizeof(*b));
+ b->hash = h;
+ b->depth = depth;
+ b->stack = kcopy;
+ b->next = table[buck];
+ table[buck] = b;
+ if (bucket_count != NULL) {
+ ++(*bucket_count);
+ }
+ 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, alloc_table_,
+ &num_alloc_buckets_);
+ 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;
+ alloc_address_map_->Insert(ptr, v);
+}
+
+void HeapProfileTable::RecordFree(const void* ptr) {
+ AllocValue v;
+ if (alloc_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 = alloc_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 = alloc_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 =
+ alloc_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 = 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 = 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<uintptr_t>(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 = reinterpret_cast<Bucket**>(alloc_(sizeof(Bucket) *
+ (num_alloc_buckets_ + num_available_mmap_buckets_)));
+
+ RAW_DCHECK(mmap_table_ != NULL || num_available_mmap_buckets_ == 0, "");
+
+ int n = 0;
+
+ for (int b = 0; b < kHashTableSize; b++) {
+ for (Bucket* x = alloc_table_[b]; x != 0; x = x->next) {
+ list[n++] = x;
+ }
+ }
+ RAW_DCHECK(n == num_alloc_buckets_, "");
+
+ if (mmap_table_ != NULL) {
+ for (int b = 0; b < kHashTableSize; b++) {
+ for (Bucket* x = mmap_table_[b]; x != 0; x = x->next) {
+ list[n++] = x;
+ }
+ }
+ }
+ RAW_DCHECK(n == num_alloc_buckets_ + num_available_mmap_buckets_, "");
+
+ sort(list, list + num_alloc_buckets_ + num_available_mmap_buckets_,
+ ByAllocatedSpace);
+
+ return list;
+}
+
+void HeapProfileTable::RefreshMMapData() {
+ // Make the table
+ static const int mmap_table_bytes = kHashTableSize * sizeof(*mmap_table_);
+ if (mmap_table_ == NULL) {
+ mmap_table_ = reinterpret_cast<Bucket**>(alloc_(mmap_table_bytes));
+ memset(mmap_table_, 0, mmap_table_bytes);
+ }
+ num_available_mmap_buckets_ = 0;
+
+ ClearMMapData();
+ mmap_address_map_ =
+ new(alloc_(sizeof(AllocationMap))) AllocationMap(alloc_, dealloc_);
+
+ MemoryRegionMap::LockHolder l;
+ for (MemoryRegionMap::RegionIterator r =
+ MemoryRegionMap::BeginRegionLocked();
+ r != MemoryRegionMap::EndRegionLocked(); ++r) {
+ Bucket* b =
+ GetBucket(r->call_stack_depth, r->call_stack, mmap_table_, NULL);
+ if (b->alloc_size == 0) {
+ num_available_mmap_buckets_ += 1;
+ }
+ b->allocs += 1;
+ b->alloc_size += r->end_addr - r->start_addr;
+
+ AllocValue v;
+ v.set_bucket(b);
+ v.bytes = r->end_addr - r->start_addr;
+ mmap_address_map_->Insert(reinterpret_cast<const void*>(r->start_addr), v);
+ }
+}
+
+void HeapProfileTable::ClearMMapData() {
+ if (mmap_address_map_ != NULL) {
+ mmap_address_map_->Iterate(ZeroBucketCountsIterator, this);
+ mmap_address_map_->~AllocationMap();
+ dealloc_(mmap_address_map_);
+ mmap_address_map_ = NULL;
+ }
+}
+
+void HeapProfileTable::IterateOrderedAllocContexts(
+ AllocContextIterator callback) const {
+ Bucket** list = MakeSortedBucketList();
+ AllocContextInfo info;
+ for (int i = 0; i < num_alloc_buckets_; ++i) {
+ *static_cast<Stats*>(&info) = *static_cast<Stats*>(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) 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) return 0;
+ Bucket total_with_mmap(total_);
+ if (mmap_table_ != NULL) {
+ total_with_mmap.alloc_size += MemoryRegionMap::MapSize();
+ total_with_mmap.free_size += MemoryRegionMap::UnmapSize();
+ }
+ bucket_length = UnparseBucket(total_with_mmap, buf, bucket_length, size,
+ " heapprofile", &stats);
+ for (int i = 0; i < num_alloc_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;
+}
+
+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);
+}
+
+inline void HeapProfileTable::ZeroBucketCountsIterator(
+ const void* ptr, AllocValue* v, HeapProfileTable* heap_profile) {
+ Bucket* b = v->bucket();
+ if (b != NULL) {
+ b->allocs = 0;
+ b->alloc_size = 0;
+ b->free_size = 0;
+ b->frees = 0;
+ }
+}
+
+// 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) {
+ 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<const DumpArgs&>(DumpNonLiveIterator, args);
+ RawWrite(fd, kProcSelfMapsHeader, strlen(kProcSelfMapsHeader));
+ DumpProcSelfMaps(fd);
+ RawClose(fd);
+ return true;
+ } else {
+ RAW_LOG(ERROR, "Failed dumping filtered heap profile to %s", file_name);
+ return false;
+ }
+}
+
+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_);
+ alloc_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;
+ alloc_address_map_->Iterate<AddNonLiveArgs*>(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<Bucket*, Entry> 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 %"PRIuS" bytes "
+ "in %"PRIuS" 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<Bucket*,Entry>::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<uintptr_t>(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 %"PRIuS" byte object %p", v->bytes, ptr);
+}
+
+void HeapProfileTable::Snapshot::ReportIndividualObjects() {
+ char unused;
+ map_.Iterate(ReportObject, &unused);
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.h b/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.h
new file mode 100644
index 00000000000..abd3184e60f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/heap-profile-table.h
@@ -0,0 +1,422 @@
+// 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
+
+// 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.
+ struct Stats {
+ 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
+
+ // semantic equality
+ bool Equivalent(const Stats& x) const {
+ return allocs - frees == x.allocs - x.frees &&
+ alloc_size - free_size == x.alloc_size - x.free_size;
+ }
+ };
+
+ // 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);
+ ~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 {
+ alloc_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);
+
+ // Refresh the internal mmap information from MemoryRegionMap. Results of
+ // FillOrderedProfile and IterateOrderedAllocContexts will contain mmap'ed
+ // memory regions as at calling RefreshMMapData.
+ void RefreshMMapData();
+
+ // Clear the internal mmap information. Results of FillOrderedProfile and
+ // IterateOrderedAllocContexts won't contain mmap'ed memory regions after
+ // calling ClearMMapData.
+ void ClearMMapData();
+
+ private:
+
+ // data types ----------------------------
+
+ // Hash table bucket to hold (de)allocation stats
+ // for a given allocation call stack trace.
+ struct Bucket : public Stats {
+ uintptr_t hash; // Hash value of the stack trace
+ int depth; // Depth of stack trace
+ const void** stack; // Stack trace
+ Bucket* next; // Next entry in hash-table
+ };
+
+ // Info stored in the address map
+ struct AllocValue {
+ // Access to the stack-trace bucket
+ Bucket* bucket() const {
+ return reinterpret_cast<Bucket*>(bucket_rep & ~uintptr_t(kMask));
+ }
+ // This also does set_live(false).
+ void set_bucket(Bucket* b) { bucket_rep = reinterpret_cast<uintptr_t>(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<AllocValue> AllocationMap;
+
+ // Arguments that need to be passed DumpNonLiveIterator callback below.
+ struct DumpArgs {
+ RawFD fd; // file to write to
+ Stats* profile_stats; // stats to update (may be NULL)
+
+ DumpArgs(RawFD a, Stats* d)
+ : fd(a), profile_stats(d) { }
+ };
+
+ // 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);
+
+ // Deallocate a given allocation map.
+ void DeallocateAllocationMap(AllocationMap* allocation);
+
+ // Deallocate a given bucket table.
+ void DeallocateBucketTable(Bucket** table);
+
+ // Get the bucket for the caller stack trace 'key' of depth 'depth' from a
+ // bucket hash map 'table' creating the bucket if needed. '*bucket_count'
+ // is incremented both when 'bucket_count' is not NULL and when a new
+ // bucket object is created.
+ Bucket* GetBucket(int depth, const void* const key[], Bucket** table,
+ int* bucket_count);
+
+ // 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 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 filling size variables in buckets by zero.
+ inline static void ZeroBucketCountsIterator(
+ const void* ptr, AllocValue* v, HeapProfileTable* heap_profile);
+
+ // Helper for IterateOrderedAllocContexts and FillOrderedProfile.
+ // Creates a sorted list of Buckets whose length is num_alloc_buckets_ +
+ // num_avaliable_mmap_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.
+ // It doesn't contain mmap'ed regions.
+ Bucket total_;
+
+ // 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** alloc_table_;
+ int num_alloc_buckets_;
+
+ // Bucket hash table for mmap.
+ // This table is filled with the information from MemoryRegionMap by calling
+ // RefreshMMapData.
+ Bucket** mmap_table_;
+ int num_available_mmap_buckets_;
+
+ // Map of all currently allocated objects and mapped regions we know about.
+ AllocationMap* alloc_address_map_;
+ AllocationMap* mmap_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/chromium/third_party/tcmalloc/vendor/src/heap-profiler.cc b/chromium/third_party/tcmalloc/vendor/src/heap-profiler.cc
new file mode 100644
index 00000000000..09a3911a4f8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/heap-profiler.cc
@@ -0,0 +1,555 @@
+// 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 <config.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h> // for open()
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+
+#include <algorithm>
+#include <string>
+
+#include <gperftools/heap-profiler.h>
+
+#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 <gperftools/malloc_hook.h>
+#include <gperftools/malloc_extension.h>
+#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 STL_NAMESPACE::string;
+using STL_NAMESPACE::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_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 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) {
+ if (FLAGS_mmap_profile) {
+ heap_profile->RefreshMMapData();
+ }
+ bytes_written = heap_profile->FillOrderedProfile(buf, buflen - 1);
+ if (FLAGS_mmap_profile) {
+ heap_profile->ClearMMapData();
+ }
+ }
+ 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<char*>(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<char*>(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;
+ }
+ 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<int>(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 PRIxS 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=%"PRIuS", 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 PRIxS 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=%"PRIuS", "
+ "new_size=%"PRIuS", 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 PRIxS 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=%"PRIuS")",
+ (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=%"PRIdS") = 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);
+ }
+
+ 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<char*>(ProfilerMalloc(kProfileBufferSize));
+
+ heap_profile = new(ProfilerMalloc(sizeof(HeapProfileTable)))
+ HeapProfileTable(ProfilerMalloc, ProfilerFree);
+
+ last_dump_alloc = 0;
+ last_dump_free = 0;
+ high_water_mark = 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<char*>(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);
+ }
+}
+
+//----------------------------------------------------------------------
+// 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
+
+ HeapProfileTable::CleanupOldProfiles(fname);
+
+ HeapProfilerStart(fname);
+}
+
+// class used for finalization -- dumps the heap-profile at program exit
+struct HeapProfileEndWriter {
+ ~HeapProfileEndWriter() { HeapProfilerDump("Exiting"); }
+};
+
+// 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/chromium/third_party/tcmalloc/vendor/src/internal_logging.cc b/chromium/third_party/tcmalloc/vendor/src/internal_logging.cc
new file mode 100644
index 00000000000..2189d84662e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/internal_logging.cc
@@ -0,0 +1,193 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#include "internal_logging.h"
+#include <stdarg.h> // for va_end, va_start
+#include <stdio.h> // for vsnprintf, va_list, etc
+#include <stdlib.h> // for abort
+#include <string.h> // for strlen, memcpy
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+
+#include <gperftools/malloc_extension.h>
+#include "base/logging.h" // for perftools_vsnprintf
+#include "base/spinlock.h" // for SpinLockHolder, SpinLock
+
+static const int kLogBufSize = 800;
+
+// 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<uint64_t>(item.u_.snum), 10);
+ } else {
+ return AddNum(static_cast<uint64_t>(item.u_.snum), 10);
+ }
+ case LogItem::kPtr:
+ return AddStr("0x", 2)
+ && AddNum(reinterpret_cast<uintptr_t>(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/chromium/third_party/tcmalloc/vendor/src/internal_logging.h b/chromium/third_party/tcmalloc/vendor/src/internal_logging.h
new file mode 100644
index 00000000000..02670346cbd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/internal_logging.h
@@ -0,0 +1,143 @@
+// 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 <opensource@google.com>
+//
+// Internal logging and related utility routines.
+
+#ifndef TCMALLOC_INTERNAL_LOGGING_H_
+#define TCMALLOC_INTERNAL_LOGGING_H_
+
+#include <config.h>
+#include <stddef.h> // for size_t
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#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/chromium/third_party/tcmalloc/vendor/src/libc_override.h b/chromium/third_party/tcmalloc/vendor/src/libc_override.h
new file mode 100644
index 00000000000..666d14de760
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/libc_override.h
@@ -0,0 +1,90 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h> // for __GLIBC__
+#endif
+#include <gperftools/tcmalloc.h>
+
+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/chromium/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h b/chromium/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h
new file mode 100644
index 00000000000..070ebf72aac
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h
@@ -0,0 +1,99 @@
+// 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 <opensource@google.com>
+//
+// 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 <sys/cdefs.h> // for __THROW
+#endif
+#include <gperftools/tcmalloc.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)))
+
+void* operator new(size_t size) throw (std::bad_alloc)
+ ALIAS(tc_new);
+void operator delete(void* p) __THROW
+ ALIAS(tc_delete);
+void* operator new[](size_t size) throw (std::bad_alloc)
+ ALIAS(tc_newarray);
+void operator delete[](void* p) __THROW
+ ALIAS(tc_deletearray);
+void* operator new(size_t size, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_new_nothrow);
+void* operator new[](size_t size, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_newarray_nothrow);
+void operator delete(void* p, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_delete_nothrow);
+void operator delete[](void* p, const std::nothrow_t& nt) __THROW
+ ALIAS(tc_deletearray_nothrow);
+
+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* 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);
+ void malloc_stats(void) __THROW ALIAS(tc_malloc_stats);
+ 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);
+ size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size);
+} // 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/chromium/third_party/tcmalloc/vendor/src/libc_override_glibc.h b/chromium/third_party/tcmalloc/vendor/src/libc_override_glibc.h
new file mode 100644
index 00000000000..16badcc4275
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/libc_override_glibc.h
@@ -0,0 +1,148 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+#include <features.h> // for __GLIBC__
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+#include <gperftools/tcmalloc.h>
+
+#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__)
+
+
+// We also have to hook libc malloc. While our work with weak symbols
+// should make sure libc malloc is never called in most situations, it
+// can be worked around by shared libraries with the DEEPBIND
+// environment variable set. The below hooks libc to call our malloc
+// routines even in that situation. In other situations, this hook
+// should never be called.
+extern "C" {
+static void* glibc_override_malloc(size_t size, const void *caller) {
+ return tc_malloc(size);
+}
+static void* glibc_override_realloc(void *ptr, size_t size,
+ const void *caller) {
+ return tc_realloc(ptr, size);
+}
+static void glibc_override_free(void *ptr, const void *caller) {
+ tc_free(ptr);
+}
+static void* glibc_override_memalign(size_t align, size_t size,
+ const void *caller) {
+ return tc_memalign(align, size);
+}
+
+// We should be using __malloc_initialize_hook here, like the #if 0
+// code below. (See http://swoolley.org/man.cgi/3/malloc_hook.)
+// However, this causes weird linker errors with programs that link
+// with -static, so instead we just assign the vars directly at
+// static-constructor time. That should serve the same effect of
+// making sure the hooks are set before the first malloc call the
+// program makes.
+#if 0
+#include <malloc.h> // for __malloc_hook, etc.
+void glibc_override_malloc_init_hook(void) {
+ __malloc_hook = glibc_override_malloc;
+ __realloc_hook = glibc_override_realloc;
+ __free_hook = glibc_override_free;
+ __memalign_hook = glibc_override_memalign;
+}
+
+void (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_initialize_hook)(void)
+ = &glibc_override_malloc_init_hook;
+#endif
+
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __malloc_hook)(size_t, const void*)
+ = &glibc_override_malloc;
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __realloc_hook)(void*, size_t, const void*)
+ = &glibc_override_realloc;
+void (* MALLOC_HOOK_MAYBE_VOLATILE __free_hook)(void*, const void*)
+ = &glibc_override_free;
+void* (* MALLOC_HOOK_MAYBE_VOLATILE __memalign_hook)(size_t,size_t, const void*)
+ = &glibc_override_memalign;
+
+} // extern "C"
+
+// No need to write ReplaceSystemAlloc(); one of the #includes above
+// did it for us.
+
+#endif // TCMALLOC_LIBC_OVERRIDE_GLIBC_INL_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/libc_override_osx.h b/chromium/third_party/tcmalloc/vendor/src/libc_override_osx.h
new file mode 100644
index 00000000000..78a0ef2f959
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/libc_override_osx.h
@@ -0,0 +1,275 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+#include <gperftools/tcmalloc.h>
+
+#if !defined(__APPLE__)
+# error libc_override_glibc-osx.h is for OS X distributions only.
+#endif
+
+#include <AvailabilityMacros.h>
+#include <malloc/malloc.h>
+
+// 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
+ // <malloc/malloc.h> 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<void*>(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) {
+ // Hopefully unneeded by us!
+}
+
+void mi_force_unlock(malloc_zone_t *zone) {
+ // Hopefully unneeded by us!
+}
+
+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 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 = malloc_default_zone();
+ malloc_zone_unregister(default_zone);
+ malloc_zone_register(default_zone);
+}
+
+#endif // TCMALLOC_LIBC_OVERRIDE_OSX_INL_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/libc_override_redefine.h b/chromium/third_party/tcmalloc/vendor/src/libc_override_redefine.h
new file mode 100644
index 00000000000..d8d999ce7bb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/libc_override_redefine.h
@@ -0,0 +1,93 @@
+// 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 <opensource@google.com>
+//
+// 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_
+
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+
+#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
+
+void* operator new(size_t size) { return tc_new(size); }
+void operator delete(void* p) __THROW { tc_delete(p); }
+void* operator new[](size_t size) { return tc_newarray(size); }
+void operator delete[](void* p) __THROW { tc_deletearray(p); }
+void* operator new(size_t size, const std::nothrow_t& nt) __THROW {
+ return tc_new_nothrow(size, nt);
+}
+void* operator new[](size_t size, const std::nothrow_t& nt) __THROW {
+ return tc_newarray_nothrow(size, nt);
+}
+void operator delete(void* ptr, const std::nothrow_t& nt) __THROW {
+ return tc_delete_nothrow(ptr, nt);
+}
+void operator delete[](void* ptr, const std::nothrow_t& nt) __THROW {
+ return tc_deletearray_nothrow(ptr, nt);
+}
+extern "C" {
+ void* malloc(size_t s) __THROW { return tc_malloc(s); }
+ void free(void* p) __THROW { tc_free(p); }
+ void* realloc(void* p, size_t s) __THROW { return tc_realloc(p, s); }
+ void* calloc(size_t n, size_t s) __THROW { return tc_calloc(n, s); }
+ void cfree(void* p) __THROW { tc_cfree(p); }
+ void* memalign(size_t a, size_t s) __THROW { return tc_memalign(a, s); }
+ void* valloc(size_t s) __THROW { return tc_valloc(s); }
+ void* pvalloc(size_t s) __THROW { return tc_pvalloc(s); }
+ int posix_memalign(void** r, size_t a, size_t s) __THROW {
+ return tc_posix_memalign(r, a, s);
+ }
+ void malloc_stats(void) __THROW { tc_malloc_stats(); }
+ int mallopt(int cmd, int v) __THROW { return tc_mallopt(cmd, v); }
+#ifdef HAVE_STRUCT_MALLINFO
+ struct mallinfo mallinfo(void) __THROW { return tc_mallinfo(); }
+#endif
+ size_t malloc_size(void* p) __THROW { return tc_malloc_size(p); }
+ size_t malloc_usable_size(void* p) __THROW { 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/chromium/third_party/tcmalloc/vendor/src/linked_list.h b/chromium/third_party/tcmalloc/vendor/src/linked_list.h
new file mode 100644
index 00000000000..4b0af1b9f63
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/linked_list.h
@@ -0,0 +1,102 @@
+// 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 <opensource@google.com>
+//
+// Some very basic linked list functions for dealing with using void * as
+// storage.
+
+#ifndef TCMALLOC_LINKED_LIST_H_
+#define TCMALLOC_LINKED_LIST_H_
+
+#include <stddef.h>
+
+namespace tcmalloc {
+
+inline void *SLL_Next(void *t) {
+ return *(reinterpret_cast<void**>(t));
+}
+
+inline void SLL_SetNext(void *t, void *n) {
+ *(reinterpret_cast<void**>(t)) = n;
+}
+
+inline void SLL_Push(void **list, void *element) {
+ SLL_SetNext(element, *list);
+ *list = element;
+}
+
+inline void *SLL_Pop(void **list) {
+ void *result = *list;
+ *list = SLL_Next(*list);
+ return result;
+}
+
+// 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/chromium/third_party/tcmalloc/vendor/src/malloc_extension.cc b/chromium/third_party/tcmalloc/vendor/src/malloc_extension.cc
new file mode 100644
index 00000000000..2d6497f4e74
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/malloc_extension.cc
@@ -0,0 +1,372 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#include <string>
+#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"
+
+using STL_NAMESPACE::string;
+using STL_NAMESPACE::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<size_t>(-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<MallocExtension::FreeListInfo>* v) {
+ v->clear();
+}
+
+// The current malloc extension object.
+
+static pthread_once_t module_init = PTHREAD_ONCE_INIT;
+static MallocExtension* current_instance = NULL;
+
+static void InitModule() {
+ current_instance = new MallocExtension;
+#ifndef NO_HEAP_CHECK
+ HeapLeakChecker::IgnoreObject(current_instance);
+#endif
+}
+
+MallocExtension* MallocExtension::instance() {
+ perftools_pthread_once(&module_init, InitModule);
+ return current_instance;
+}
+
+void MallocExtension::Register(MallocExtension* implementation) {
+ perftools_pthread_once(&module_init, 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<uintptr_t>(entry[0]);
+}
+uintptr_t Size(void** entry) {
+ return reinterpret_cast<uintptr_t>(entry[1]);
+}
+uintptr_t Depth(void** entry) {
+ return reinterpret_cast<uintptr_t>(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<uint64>(count),
+ static_cast<uint64>(size),
+ static_cast<uint64>(count),
+ static_cast<uint64>(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));
+
+// 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_Ownership>(
+ MallocExtension::instance()->GetOwnership(p));
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/malloc_hook-inl.h b/chromium/third_party/tcmalloc/vendor/src/malloc_hook-inl.h
new file mode 100644
index 00000000000..27e5bdcaafe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/malloc_hook-inl.h
@@ -0,0 +1,322 @@
+// 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 <stddef.h>
+#include <sys/types.h>
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+#include <gperftools/malloc_hook.h>
+
+namespace base { namespace internal {
+
+// The following (implementation) code is DEPRECATED.
+// A simple atomic pointer class that can be initialized by the linker
+// when you define a namespace-scope variable as:
+//
+// AtomicPtr<Foo*> my_global = { &initial_value };
+//
+// This isn't suitable for a general atomic<> class because of the
+// public access to data_.
+template<typename PtrT>
+class AtomicPtr {
+ public:
+ COMPILE_ASSERT(sizeof(PtrT) <= sizeof(AtomicWord),
+ PtrT_should_fit_in_AtomicWord);
+
+ PtrT Get() const {
+ // Depending on the system, Acquire_Load(AtomicWord*) may have
+ // been defined to return an AtomicWord, Atomic32, or Atomic64.
+ // We hide that implementation detail here with an explicit cast.
+ // This prevents MSVC 2005, at least, from complaining (it has to
+ // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't).
+ return reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::Acquire_Load(&data_)));
+ }
+
+ // Sets the contained value to new_val and returns the old value,
+ // atomically, with acquire and release semantics.
+ // This is a full-barrier instruction.
+ PtrT Exchange(PtrT new_val);
+
+ // Atomically executes:
+ // result = data_
+ // if (data_ == old_val)
+ // data_ = new_val;
+ // return result;
+ // This is a full-barrier instruction.
+ PtrT CompareAndSwap(PtrT old_val, PtrT new_val);
+
+ // Not private so that the class is an aggregate and can be
+ // initialized by the linker. Don't access this directly.
+ AtomicWord data_;
+};
+
+// These are initialized in malloc_hook.cc
+extern AtomicPtr<MallocHook::NewHook> new_hook_;
+extern AtomicPtr<MallocHook::DeleteHook> delete_hook_;
+extern AtomicPtr<MallocHook::PreMmapHook> premmap_hook_;
+extern AtomicPtr<MallocHook::MmapHook> mmap_hook_;
+extern AtomicPtr<MallocHook::MunmapHook> munmap_hook_;
+extern AtomicPtr<MallocHook::MremapHook> mremap_hook_;
+extern AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_;
+extern AtomicPtr<MallocHook::SbrkHook> sbrk_hook_;
+// End DEPRECATED code.
+
+// Maximum of 7 hooks means that HookList is 8 words.
+static const int kHookListMaxValues = 7;
+
+// HookList: a class that provides synchronized insertions and removals and
+// lockless traversal. Most of the implementation is in malloc_hook.cc.
+template <typename T>
+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);
+
+ // 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::Acquire_Load(&priv_end) == 0;
+ }
+
+ // 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.
+ AtomicWord priv_end;
+ AtomicWord priv_data[kHookListMaxValues];
+};
+
+extern HookList<MallocHook::NewHook> new_hooks_;
+extern HookList<MallocHook::DeleteHook> delete_hooks_;
+extern HookList<MallocHook::PreMmapHook> premmap_hooks_;
+extern HookList<MallocHook::MmapHook> mmap_hooks_;
+extern HookList<MallocHook::MmapReplacement> mmap_replacement_;
+extern HookList<MallocHook::MunmapHook> munmap_hooks_;
+extern HookList<MallocHook::MunmapReplacement> munmap_replacement_;
+extern HookList<MallocHook::MremapHook> mremap_hooks_;
+extern HookList<MallocHook::PreSbrkHook> presbrk_hooks_;
+extern HookList<MallocHook::SbrkHook> sbrk_hooks_;
+
+} } // namespace base::internal
+
+// The following method is DEPRECATED
+inline MallocHook::NewHook MallocHook::GetNewHook() {
+ return base::internal::new_hook_.Get();
+}
+
+inline void MallocHook::InvokeNewHook(const void* p, size_t s) {
+ if (!base::internal::new_hooks_.empty()) {
+ InvokeNewHookSlow(p, s);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::NewHook hook = MallocHook::GetNewHook();
+ if (hook != NULL) (*hook)(p, s);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::DeleteHook MallocHook::GetDeleteHook() {
+ return base::internal::delete_hook_.Get();
+}
+
+inline void MallocHook::InvokeDeleteHook(const void* p) {
+ if (!base::internal::delete_hooks_.empty()) {
+ InvokeDeleteHookSlow(p);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::DeleteHook hook = MallocHook::GetDeleteHook();
+ if (hook != NULL) (*hook)(p);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() {
+ return base::internal::premmap_hook_.Get();
+}
+
+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 code is DEPRECATED.
+ MallocHook::PreMmapHook hook = MallocHook::GetPreMmapHook();
+ if (hook != NULL) (*hook)(start, size,
+ protection, flags,
+ fd, offset);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::MmapHook MallocHook::GetMmapHook() {
+ return base::internal::mmap_hook_.Get();
+}
+
+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);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::MmapHook hook = MallocHook::GetMmapHook();
+ if (hook != NULL) (*hook)(result,
+ start, size,
+ protection, flags,
+ fd, offset);
+ // End DEPRECATED code.
+}
+
+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_hook_.Get();
+}
+
+inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) {
+ if (!base::internal::munmap_hooks_.empty()) {
+ InvokeMunmapHookSlow(p, size);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::MunmapHook hook = MallocHook::GetMunmapHook();
+ if (hook != NULL) (*hook)(p, size);
+ // End DEPRECATED code.
+}
+
+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_hook_.Get();
+}
+
+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 code is DEPRECATED.
+ MallocHook::MremapHook hook = MallocHook::GetMremapHook();
+ if (hook != NULL) (*hook)(result,
+ old_addr, old_size,
+ new_size, flags, new_addr);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() {
+ return base::internal::presbrk_hook_.Get();
+}
+
+inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) {
+ if (!base::internal::presbrk_hooks_.empty() && increment != 0) {
+ InvokePreSbrkHookSlow(increment);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::PreSbrkHook hook = MallocHook::GetPreSbrkHook();
+ if (hook != NULL && increment != 0) (*hook)(increment);
+ // End DEPRECATED code.
+}
+
+// The following method is DEPRECATED
+inline MallocHook::SbrkHook MallocHook::GetSbrkHook() {
+ return base::internal::sbrk_hook_.Get();
+}
+
+inline void MallocHook::InvokeSbrkHook(const void* result,
+ ptrdiff_t increment) {
+ if (!base::internal::sbrk_hooks_.empty() && increment != 0) {
+ InvokeSbrkHookSlow(result, increment);
+ }
+ // The following code is DEPRECATED.
+ MallocHook::SbrkHook hook = MallocHook::GetSbrkHook();
+ if (hook != NULL && increment != 0) (*hook)(result, increment);
+ // End DEPRECATED code.
+}
+
+#endif /* _MALLOC_HOOK_INL_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/malloc_hook.cc b/chromium/third_party/tcmalloc/vendor/src/malloc_hook.cc
new file mode 100644
index 00000000000..2f8608e41b0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/malloc_hook.cc
@@ -0,0 +1,723 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+
+// 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 <sys/mman.h>
+# undef mremap
+#endif
+
+#include <stddef.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <algorithm>
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "maybe_threads.h"
+#include "malloc_hook-inl.h"
+#include <gperftools/malloc_hook.h>
+
+// 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 <gperftools/stacktrace.h>
+#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 {
+
+// The code below is DEPRECATED.
+template<typename PtrT>
+PtrT AtomicPtr<PtrT>::Exchange(PtrT new_val) {
+ base::subtle::MemoryBarrier(); // Release semantics.
+ // Depending on the system, NoBarrier_AtomicExchange(AtomicWord*)
+ // may have been defined to return an AtomicWord, Atomic32, or
+ // Atomic64. We hide that implementation detail here with an
+ // explicit cast. This prevents MSVC 2005, at least, from complaining.
+ PtrT old_val = reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::NoBarrier_AtomicExchange(
+ &data_,
+ reinterpret_cast<AtomicWord>(new_val))));
+ base::subtle::MemoryBarrier(); // And acquire semantics.
+ return old_val;
+}
+
+template<typename PtrT>
+PtrT AtomicPtr<PtrT>::CompareAndSwap(PtrT old_val, PtrT new_val) {
+ base::subtle::MemoryBarrier(); // Release semantics.
+ PtrT retval = reinterpret_cast<PtrT>(static_cast<AtomicWord>(
+ base::subtle::NoBarrier_CompareAndSwap(
+ &data_,
+ reinterpret_cast<AtomicWord>(old_val),
+ reinterpret_cast<AtomicWord>(new_val))));
+ base::subtle::MemoryBarrier(); // And acquire semantics.
+ return retval;
+}
+
+AtomicPtr<MallocHook::NewHook> new_hook_ = { 0 };
+AtomicPtr<MallocHook::DeleteHook> delete_hook_ = { 0 };
+AtomicPtr<MallocHook::PreMmapHook> premmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MmapHook> mmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MunmapHook> munmap_hook_ = { 0 };
+AtomicPtr<MallocHook::MremapHook> mremap_hook_ = { 0 };
+AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_ = { 0 };
+AtomicPtr<MallocHook::SbrkHook> sbrk_hook_ = { 0 };
+// End of DEPRECATED code section.
+
+// 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 <typename T>
+bool HookList<T>::Add(T value_as_t) {
+ AtomicWord value = bit_cast<AtomicWord>(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::Release_Store(&priv_data[index], value);
+ if (prev_num_hooks <= index) {
+ base::subtle::Release_Store(&priv_end, index + 1);
+ }
+ return true;
+}
+
+template <typename T>
+bool HookList<T>::Remove(T value_as_t) {
+ if (value_as_t == 0) {
+ return false;
+ }
+ SpinLockHolder l(&hooklist_spinlock);
+ AtomicWord hooks_end = base::subtle::Acquire_Load(&priv_end);
+ int index = 0;
+ while (index < hooks_end && value_as_t != bit_cast<T>(
+ base::subtle::Acquire_Load(&priv_data[index]))) {
+ ++index;
+ }
+ if (index == hooks_end) {
+ return false;
+ }
+ base::subtle::Release_Store(&priv_data[index], 0);
+ if (hooks_end == index + 1) {
+ // Adjust hooks_end down to the lowest possible value.
+ hooks_end = index;
+ while ((hooks_end > 0) &&
+ (base::subtle::Acquire_Load(&priv_data[hooks_end - 1]) == 0)) {
+ --hooks_end;
+ }
+ base::subtle::Release_Store(&priv_end, hooks_end);
+ }
+ return true;
+}
+
+template <typename T>
+int HookList<T>::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<T>(data);
+ ++actual_hooks_end;
+ --n;
+ }
+ }
+ return actual_hooks_end;
+}
+
+// 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<AtomicWord>(initial_value) } }
+
+// Explicit instantiation for malloc_hook_test.cc. This ensures all the methods
+// are instantiated.
+template struct HookList<MallocHook::NewHook>;
+
+HookList<MallocHook::NewHook> new_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(&InitialNewHook);
+HookList<MallocHook::DeleteHook> delete_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::PreMmapHook> premmap_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(&InitialPreMMapHook);
+HookList<MallocHook::MmapHook> mmap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::MunmapHook> munmap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::MremapHook> mremap_hooks_ = INIT_HOOK_LIST;
+HookList<MallocHook::PreSbrkHook> presbrk_hooks_ =
+ INIT_HOOK_LIST_WITH_VALUE(InitialPreSbrkHook);
+HookList<MallocHook::SbrkHook> sbrk_hooks_ = INIT_HOOK_LIST;
+
+// These lists contain either 0 or 1 hooks.
+HookList<MallocHook::MmapReplacement> mmap_replacement_ = { 0 };
+HookList<MallocHook::MunmapReplacement> munmap_replacement_ = { 0 };
+
+#undef INIT_HOOK_LIST_WITH_VALUE
+#undef INIT_HOOK_LIST
+
+} } // namespace base::internal
+
+// The code below is DEPRECATED.
+using base::internal::new_hook_;
+using base::internal::delete_hook_;
+using base::internal::premmap_hook_;
+using base::internal::mmap_hook_;
+using base::internal::munmap_hook_;
+using base::internal::mremap_hook_;
+using base::internal::presbrk_hook_;
+using base::internal::sbrk_hook_;
+// End of DEPRECATED code section.
+
+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_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_DeleteHook MallocHook_SetDeleteHook(MallocHook_DeleteHook hook) {
+ RAW_VLOG(10, "SetDeleteHook(%p)", hook);
+ return delete_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_PreMmapHook MallocHook_SetPreMmapHook(MallocHook_PreMmapHook hook) {
+ RAW_VLOG(10, "SetPreMmapHook(%p)", hook);
+ return premmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MmapHook MallocHook_SetMmapHook(MallocHook_MmapHook hook) {
+ RAW_VLOG(10, "SetMmapHook(%p)", hook);
+ return mmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MunmapHook MallocHook_SetMunmapHook(MallocHook_MunmapHook hook) {
+ RAW_VLOG(10, "SetMunmapHook(%p)", hook);
+ return munmap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_MremapHook MallocHook_SetMremapHook(MallocHook_MremapHook hook) {
+ RAW_VLOG(10, "SetMremapHook(%p)", hook);
+ return mremap_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_PreSbrkHook MallocHook_SetPreSbrkHook(MallocHook_PreSbrkHook hook) {
+ RAW_VLOG(10, "SetPreSbrkHook(%p)", hook);
+ return presbrk_hook_.Exchange(hook);
+}
+
+extern "C"
+MallocHook_SbrkHook MallocHook_SetSbrkHook(MallocHook_SbrkHook hook) {
+ RAW_VLOG(10, "SetSbrkHook(%p)", hook);
+ return sbrk_hook_.Exchange(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) {
+ INVOKE_HOOKS(NewHook, new_hooks_, (p, s));
+}
+
+void MallocHook::InvokeDeleteHookSlow(const void* p) {
+ 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
+
+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<uintptr_t>(ATTRIBUTE_SECTION_START(name)) <= \
+ reinterpret_cast<uintptr_t>(addr) && \
+ reinterpret_cast<uintptr_t>(addr) < \
+ reinterpret_cast<uintptr_t>(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;
+ }
+}
+
+// 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])) {
+ 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/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h b/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h
new file mode 100644
index 00000000000..dae868c3e09
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h
@@ -0,0 +1,165 @@
+// 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 <unistd.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+// Make sure mmap doesn't get #define'd away by <sys/mman.h>
+#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) {
+ void* curbrk = 0;
+
+#if defined(__x86_64__) || defined(__amd64__)
+# ifdef PIC
+ __asm__ __volatile__(
+ "movq .curbrk@GOTPCREL(%%rip), %%rdx;"
+ "movq (%%rdx), %%rax;"
+ "movq %%rax, %0;"
+ : "=r" (curbrk)
+ :: "%rdx", "%rax");
+# else
+ __asm__ __volatile__(
+ "movq .curbrk(%%rip), %%rax;"
+ "movq %%rax, %0;"
+ : "=r" (curbrk)
+ :: "%rax");
+# endif
+#else
+ __asm__ __volatile__(
+ "movl .curbrk, %%eax;"
+ "movl %%eax, %0;"
+ : "=r" (curbrk)
+ :: "%eax");
+#endif
+
+ if (increment == 0) {
+ return curbrk;
+ }
+
+ char* prevbrk = static_cast<char*>(curbrk);
+ void* newbrk = prevbrk + increment;
+
+ if (brk(newbrk) == -1) {
+ return reinterpret_cast<void*>(static_cast<intptr_t>(-1));
+ }
+
+ return prevbrk;
+}
+
+
+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<size_t>(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/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h b/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h
new file mode 100644
index 00000000000..dc79f8bb11e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h
@@ -0,0 +1,234 @@
+// 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 <opensource@google.com>
+
+// 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 <unistd.h>
+#include <syscall.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include "base/linux_syscall_support.h"
+
+// 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(_MIPS_SIM) && _MIPS_SIM == _ABI64)
+
+static inline void* do_mmap64(void *start, size_t length,
+ int prot, int flags,
+ int fd, __off64_t offset) __THROW {
+ return sys_mmap(start, length, prot, flags, fd, offset);
+}
+
+#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,
+ (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 mmap doesn't get #define'd away by <sys/mman.h>
+# 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(ptrdiff_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<size_t>(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 = 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 = 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;
+}
+
+// libc's version:
+extern "C" void* __sbrk(ptrdiff_t increment);
+
+extern "C" void* sbrk(ptrdiff_t increment) __THROW {
+ MallocHook::InvokePreSbrkHook(increment);
+ void *result = __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_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/chromium/third_party/tcmalloc/vendor/src/maybe_threads.cc b/chromium/third_party/tcmalloc/vendor/src/maybe_threads.cc
new file mode 100644
index 00000000000..15c8a23dcb3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/maybe_threads.cc
@@ -0,0 +1,133 @@
+// 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 <opensource@google.com>
+//
+// 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 <assert.h>
+#include <string.h> // for memcmp
+#include <stdio.h> // 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 <string>
+#include "maybe_threads.h"
+#include "base/basictypes.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;
+ 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;
+}
+
+#define MAX_PERTHREAD_VALS 16
+static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
+static int next_key;
+
+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 = (pthread_key_t)(next_key++);
+ return 0;
+ }
+}
+
+void *perftools_pthread_getspecific(pthread_key_t key) {
+ if (pthread_getspecific) {
+ return pthread_getspecific(key);
+ } else {
+ return perftools_pthread_specific_vals[(int)key];
+ }
+}
+
+int perftools_pthread_setspecific(pthread_key_t key, void *val) {
+ if (pthread_setspecific) {
+ return pthread_setspecific(key, val);
+ } else {
+ perftools_pthread_specific_vals[(int)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 <stdio.h>, 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;
+ }
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/maybe_threads.h b/chromium/third_party/tcmalloc/vendor/src/maybe_threads.h
new file mode 100644
index 00000000000..5f35e00cdf5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/maybe_threads.h
@@ -0,0 +1,52 @@
+// 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 <opensource@google.com>
+
+//-------------------------------------------------------------------
+// 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 <pthread.h>
+#endif
+
+int perftools_pthread_key_create(pthread_key_t *key,
+ void (*destr_function) (void *));
+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));
+
+#endif /* GOOGLE_MAYBE_THREADS_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/memfs_malloc.cc b/chromium/third_party/tcmalloc/vendor/src/memfs_malloc.cc
new file mode 100644
index 00000000000..b59f6d9e4e3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/memfs_malloc.cc
@@ -0,0 +1,267 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Arun Sharma
+//
+// A tcmalloc system allocator that uses a memory based filesystem such as
+// tmpfs or hugetlbfs
+//
+// Since these only exist on linux, we only register this allocator there.
+
+#ifdef __linux
+
+#include <config.h>
+#include <errno.h> // for errno, EINVAL
+#include <inttypes.h> // for PRId64
+#include <limits.h> // for PATH_MAX
+#include <stddef.h> // for size_t, NULL
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for int64_t, uintptr_t
+#endif
+#include <stdio.h> // for snprintf
+#include <stdlib.h> // for mkstemp
+#include <string.h> // for strerror
+#include <sys/mman.h> // for mmap, MAP_FAILED, etc
+#include <sys/statfs.h> // for fstatfs, statfs
+#include <unistd.h> // for ftruncate, off_t, unlink
+#include <new> // for operator new
+#include <string>
+
+#include <gperftools/malloc_extension.h>
+#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");
+
+// 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 char hugetlb_space[sizeof(HugetlbSysAllocator)];
+
+// 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 (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 (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 (aligned_size < size) {
+ return fallback_->Alloc(size, actual_size, alignment);
+ }
+
+ void* result = AllocInternal(aligned_size, actual_size, new_alignment);
+ if (result != NULL) {
+ return result;
+ }
+ 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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void *result;
+ result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ FLAGS_memfs_malloc_map_private ? MAP_PRIVATE : MAP_SHARED,
+ hugetlb_fd_, hugetlb_base_);
+ if (result == reinterpret_cast<void*>(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<uintptr_t>(result);
+
+ // Adjust the return memory so it is aligned
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+ ptr += adjust;
+ hugetlb_base_ += (size + extra);
+
+ if (actual_size) {
+ *actual_size = size + extra - adjust;
+ }
+
+ return reinterpret_cast<void*>(ptr);
+}
+
+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) HugetlbSysAllocator(alloc);
+ if (hp->Initialize()) {
+ MallocExtension::instance()->SetSystemAllocator(hp);
+ }
+ }
+});
+
+#endif /* ifdef __linux */
diff --git a/chromium/third_party/tcmalloc/vendor/src/memory_region_map.cc b/chromium/third_party/tcmalloc/vendor/src/memory_region_map.cc
new file mode 100644
index 00000000000..1a811724805
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/memory_region_map.cc
@@ -0,0 +1,652 @@
+/* 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), when the recursion unwinds
+// but before returning from the outer hook call we unwind this stack and
+// move the data from saved_regions to its permanent place in the RegionSet,
+// 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 <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#elif !defined(MAP_FAILED)
+#define MAP_FAILED -1 // the only thing we need from mman.h
+#endif
+#ifdef HAVE_PTHREAD
+#include <pthread.h> // for pthread_t, pthread_self()
+#endif
+#include <stddef.h>
+
+#include <algorithm>
+#include <set>
+
+#include "memory_region_map.h"
+
+#include "base/logging.h"
+#include "base/low_level_alloc.h"
+#include "malloc_hook-inl.h"
+
+#include <gperftools/stacktrace.h>
+#include <gperftools/malloc_hook.h>
+
+// 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;
+
+// ========================================================================= //
+
+// 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;
+static bool initializer = (libpthread_initialized = true, 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<RegionSet*>(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) {
+ 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.
+ 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;
+ }
+ 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;
+}
+
+// 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<void*>(stack_top),
+ reinterpret_cast<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_addr));
+ const_cast<Region*>(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;
+}
+
+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<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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<void*>(region.start_addr),
+ reinterpret_cast<void*>(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);
+ }
+}
+
+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<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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_
+ RAW_VLOG(12, "Initializing region set");
+ regions_ = regions_rep.region_set();
+ recursive_insert = true;
+ new(regions_) RegionSet();
+ HandleSavedRegionsLocked(&DoInsertRegionLocked);
+ recursive_insert = false;
+ }
+ 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':
+ const int depth =
+ max_stack_depth_ > 0
+ ? MallocHook::GetCallerStackTrace(const_cast<void**>(region.call_stack),
+ max_stack_depth_, kStripFrames + 1)
+ : 0;
+ region.set_call_stack_depth(depth); // record stack info fully
+ RAW_VLOG(10, "New global region %p..%p from %p",
+ reinterpret_cast<void*>(region.start_addr),
+ reinterpret_cast<void*>(region.end_addr),
+ reinterpret_cast<void*>(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().
+ 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<uintptr_t>(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.
+ --saved_regions_count;
+ --put_pos;
+ RAW_VLOG(10, ("Insta-Removing saved region %p..%p; "
+ "now have %d saved regions"),
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(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<uintptr_t>(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 %"PRIuS" regions",
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(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<void*>(region->start_addr),
+ reinterpret_cast<void*>(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<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_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<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_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&>(*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<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_addr));
+ const_cast<Region&>(*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<void*>(region->start_addr),
+ reinterpret_cast<void*>(region->end_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 %"PRIuS" regions",
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(end_addr),
+ regions_->size());
+ if (VLOG_IS_ON(12)) LogAllLocked();
+ unmap_size_ += size;
+ Unlock();
+}
+
+void MemoryRegionMap::MmapHook(const void* result,
+ const void* start, size_t size,
+ int prot, int flags,
+ int fd, off_t offset) {
+ // TODO(maxim): replace all 0x%"PRIxS" by %p when RAW_VLOG uses a safe
+ // snprintf reimplementation that does not malloc to pretty-print NULL
+ RAW_VLOG(10, "MMap = 0x%"PRIxPTR" of %"PRIuS" at %"PRIu64" "
+ "prot %d flags %d fd %d offs %"PRId64,
+ reinterpret_cast<uintptr_t>(result), size,
+ reinterpret_cast<uint64>(start), prot, flags, fd,
+ static_cast<int64>(offset));
+ if (result != reinterpret_cast<void*>(MAP_FAILED) && size != 0) {
+ RecordRegionAddition(result, size);
+ }
+}
+
+void MemoryRegionMap::MunmapHook(const void* ptr, size_t size) {
+ RAW_VLOG(10, "MUnmap of %p %"PRIuS"", 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" %"PRIuS" "
+ "to %"PRIuS" 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<void*>(-1)) {
+ RecordRegionRemoval(old_addr, old_size);
+ RecordRegionAddition(result, new_size);
+ }
+}
+
+extern "C" void* __sbrk(ptrdiff_t increment); // defined in libc
+
+void MemoryRegionMap::SbrkHook(const void* result, ptrdiff_t increment) {
+ RAW_VLOG(10, "Sbrk = 0x%"PRIxPTR" of %"PRIdS"", (uintptr_t)result, increment);
+ if (result != reinterpret_cast<void*>(-1)) {
+ if (increment > 0) {
+ void* new_end = sbrk(0);
+ RecordRegionAddition(result, reinterpret_cast<uintptr_t>(new_end) -
+ reinterpret_cast<uintptr_t>(result));
+ } else if (increment < 0) {
+ void* new_end = sbrk(0);
+ RecordRegionRemoval(new_end, reinterpret_cast<uintptr_t>(result) -
+ reinterpret_cast<uintptr_t>(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/chromium/third_party/tcmalloc/vendor/src/memory_region_map.h b/chromium/third_party/tcmalloc/vendor/src/memory_region_map.h
new file mode 100644
index 00000000000..988ea707375
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/memory_region_map.h
@@ -0,0 +1,340 @@
+/* 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 <config.h>
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+#include <stddef.h>
+#include <set>
+#include "base/stl_allocator.h"
+#include "base/spinlock.h"
+#include "base/thread_annotations.h"
+#include "base/low_level_alloc.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;
+
+ 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.
+ // 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);
+
+ // 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();
+
+ // 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<uintptr_t>(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<uintptr_t>(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);
+
+ 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<void*>(p));
+ }
+ };
+
+ // Set of the memory regions
+ typedef std::set<Region, RegionCmp,
+ STL_Allocator<Region, MyAllocator> > 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 ListAllProcessThreads at random spots
+ // simply by acquiring our recursive Lock() before that.
+ static RegionSet* regions_;
+
+ // Lock to protect regions_ variable 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_;
+
+ // 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));
+ // 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);
+
+ // 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);
+};
+
+#endif // BASE_MEMORY_REGION_MAP_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/packed-cache-inl.h b/chromium/third_party/tcmalloc/vendor/src/packed-cache-inl.h
new file mode 100644
index 00000000000..77f42b6b319
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/packed-cache-inl.h
@@ -0,0 +1,238 @@
+// 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 <key, value> 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 <key, value> 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<K, V>(key, value); }
+// V GetOrDefault(K key, V default) { const pair<K, V> &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 <key, value> pair with that key
+// has ever been Put. However, a newly initialized cache will have
+// some <key, value> 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 <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#include "base/basictypes.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<IntType>(1) << ((N)-1))-1 + \
+ (static_cast<IntType>(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 T. See also the big comment at the top of the file.
+template <int kKeybits, typename T>
+class PackedCache {
+ public:
+ typedef uintptr_t K;
+ typedef size_t 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;
+ static const bool kUseWholeKeys = kKeybits + kValuebits <= 8 * sizeof(T);
+
+ explicit PackedCache(V initial_value) {
+ COMPILE_ASSERT(kKeybits <= sizeof(K) * 8, key_size);
+ COMPILE_ASSERT(kValuebits <= sizeof(V) * 8, value_size);
+ COMPILE_ASSERT(kHashbits <= kKeybits, hash_function);
+ COMPILE_ASSERT(kKeybits - kHashbits + kValuebits <= kTbits,
+ entry_size_must_be_big_enough);
+ Clear(initial_value);
+ }
+
+ void Put(K key, V value) {
+ ASSERT(key == (key & kKeyMask));
+ ASSERT(value == (value & kValueMask));
+ array_[Hash(key)] = KeyToUpper(key) | value;
+ }
+
+ bool Has(K key) const {
+ ASSERT(key == (key & kKeyMask));
+ return KeyMatch(array_[Hash(key)], key);
+ }
+
+ V GetOrDefault(K key, V default_value) const {
+ // As with other code in this class, we touch array_ as few times
+ // as we can. Assuming entries are read atomically (e.g., their
+ // type is uintptr_t on most hardware) then certain races are
+ // harmless.
+ ASSERT(key == (key & kKeyMask));
+ T entry = array_[Hash(key)];
+ return KeyMatch(entry, key) ? EntryToValue(entry) : default_value;
+ }
+
+ void Clear(V value) {
+ ASSERT(value == (value & kValueMask));
+ for (int i = 0; i < 1 << kHashbits; i++) {
+ ASSERT(kUseWholeKeys || KeyToUpper(i) == 0);
+ array_[i] = kUseWholeKeys ? (value | KeyToUpper(i)) : value;
+ }
+ }
+
+ private:
+ // We are going to pack a value and the upper part of a key (or a
+ // whole key) into an entry of type T. The UPPER type is for the
+ // upper part of a key, after the key has been masked and shifted
+ // for inclusion in an entry.
+ typedef T UPPER;
+
+ static V EntryToValue(T t) { return t & kValueMask; }
+
+ // If we have space for a whole key, we just shift it left.
+ // Otherwise kHashbits determines where in a K to find the upper
+ // part of the key, and kValuebits determines where in the entry to
+ // put it.
+ static UPPER KeyToUpper(K k) {
+ if (kUseWholeKeys) {
+ return static_cast<T>(k) << kValuebits;
+ } else {
+ const int shift = kHashbits - kValuebits;
+ // Assume kHashbits >= kValuebits. It'd be easy to lift this assumption.
+ return static_cast<T>(k >> shift) & kUpperMask;
+ }
+ }
+
+ static size_t Hash(K key) {
+ return static_cast<size_t>(key) & N_ONES_(size_t, kHashbits);
+ }
+
+ // Does the entry match the relevant part of the given key?
+ static bool KeyMatch(T entry, K key) {
+ return kUseWholeKeys ?
+ (entry >> kValuebits == key) :
+ ((KeyToUpper(key) ^ entry) & kUpperMask) == 0;
+ }
+
+ static const int kTbits = 8 * sizeof(T);
+ static const int kUpperbits = kUseWholeKeys ? kKeybits : kKeybits - kHashbits;
+
+ // For masking a K.
+ static const K kKeyMask = N_ONES_(K, kKeybits);
+
+ // For masking a T.
+ static const T kUpperMask = N_ONES_(T, kUpperbits) << kValuebits;
+
+ // 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/chromium/third_party/tcmalloc/vendor/src/page_heap.cc b/chromium/third_party/tcmalloc/vendor/src/page_heap.cc
new file mode 100644
index 00000000000..18bdb947bee
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/page_heap.cc
@@ -0,0 +1,483 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> // for PRIuPTR
+#endif
+#include <gperftools/malloc_extension.h> // 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]");
+
+namespace tcmalloc {
+
+PageHeap::PageHeap()
+ : pagemap_(MetaDataAlloc),
+ pagemap_cache_(0),
+ scavenge_counter_(0),
+ // Start scavenging at kMaxPages list
+ release_index_(kMaxPages) {
+ COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
+ DLL_Init(&large_.normal);
+ DLL_Init(&large_.returned);
+ 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].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].returned;
+ 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
+}
+
+Span* PageHeap::New(Length n) {
+ ASSERT(Check());
+ ASSERT(n > 0);
+
+ Span* result = SearchFreeAndLargeLists(n);
+ if (result != NULL)
+ return result;
+
+ // Grow the heap and try again.
+ if (!GrowHeap(n)) {
+ ASSERT(Check());
+ return NULL;
+ }
+ return SearchFreeAndLargeLists(n);
+}
+
+Span* PageHeap::AllocLarge(Length n) {
+ // find the best span (closest to n in size).
+ // The following loops implements address-ordered best-fit.
+ Span *best = NULL;
+
+ // Search through normal list
+ for (Span* span = large_.normal.next;
+ span != &large_.normal;
+ span = span->next) {
+ if (span->length >= n) {
+ if ((best == NULL)
+ || (span->length < best->length)
+ || ((span->length == best->length) && (span->start < best->start))) {
+ best = span;
+ ASSERT(best->location == Span::ON_NORMAL_FREELIST);
+ }
+ }
+ }
+
+ // Search through released list in case it has a better fit
+ for (Span* span = large_.returned.next;
+ span != &large_.returned;
+ span = span->next) {
+ if (span->length >= n) {
+ if ((best == NULL)
+ || (span->length < best->length)
+ || ((span->length == best->length) && (span->start < best->start))) {
+ best = span;
+ ASSERT(best->location == Span::ON_RETURNED_FREELIST);
+ }
+ }
+ }
+
+ return best == NULL ? NULL : Carve(best, n);
+}
+
+Span* PageHeap::Split(Span* span, Length n) {
+ ASSERT(0 < n);
+ ASSERT(n < span->length);
+ ASSERT(span->location == Span::IN_USE);
+ ASSERT(span->sizeclass == 0);
+ Event(span, 'T', n);
+
+ const int extra = span->length - n;
+ Span* leftover = NewSpan(span->start + n, extra);
+ ASSERT(leftover->location == Span::IN_USE);
+ Event(leftover, 'U', extra);
+ RecordSpan(leftover);
+ pagemap_.set(span->start + n - 1, span); // Update map from pageid to span
+ span->length = n;
+
+ return leftover;
+}
+
+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;
+ Event(span, 'A', n);
+
+ const int extra = span->length - n;
+ ASSERT(extra >= 0);
+ if (extra > 0) {
+ Span* leftover = NewSpan(span->start + n, extra);
+ leftover->location = old_location;
+ Event(leftover, 'S', extra);
+ RecordSpan(leftover);
+ PrependToFreeList(leftover); // Skip coalescing - no candidates possible
+ span->length = n;
+ pagemap_.set(span->start + n - 1, span);
+ }
+ ASSERT(Check());
+ 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;
+ Event(span, 'D', span->length);
+ MergeIntoFreeList(span); // Coalesces if possible
+ IncrementalScavenge(n);
+ ASSERT(Check());
+}
+
+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 that only similar spans are merged together. For example,
+ // we do not coalesce "returned" spans with "normal" spans.
+ const PageID p = span->start;
+ const Length n = span->length;
+ Span* prev = GetDescriptor(p-1);
+ if (prev != NULL && prev->location == span->location) {
+ // Merge preceding span into this span
+ ASSERT(prev->start + prev->length == p);
+ const Length len = prev->length;
+ RemoveFromFreeList(prev);
+ DeleteSpan(prev);
+ span->start -= len;
+ span->length += len;
+ pagemap_.set(span->start, span);
+ Event(span, 'L', len);
+ }
+ Span* next = GetDescriptor(p+n);
+ if (next != NULL && next->location == span->location) {
+ // Merge next span into this span
+ ASSERT(next->start == p+n);
+ const Length len = next->length;
+ RemoveFromFreeList(next);
+ DeleteSpan(next);
+ span->length += len;
+ pagemap_.set(span->start + span->length - 1, span);
+ Event(span, 'R', len);
+ }
+
+ PrependToFreeList(span);
+}
+
+void PageHeap::PrependToFreeList(Span* span) {
+ ASSERT(span->location != Span::IN_USE);
+ SpanList* list = (span->length < kMaxPages) ? &free_[span->length] : &large_;
+ if (span->location == Span::ON_NORMAL_FREELIST) {
+ stats_.free_bytes += (span->length << kPageShift);
+ DLL_Prepend(&list->normal, span);
+ } else {
+ stats_.unmapped_bytes += (span->length << kPageShift);
+ 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);
+ }
+ 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;
+ }
+
+ 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<double>(released_pages);
+ if (wait > kMaxReleaseDelay) {
+ // Avoid overflow and bound to reasonable range.
+ wait = kMaxReleaseDelay;
+ }
+ scavenge_counter_ = static_cast<int64_t>(wait);
+ }
+}
+
+Length PageHeap::ReleaseLastNormalSpan(SpanList* slist) {
+ Span* s = slist->normal.prev;
+ ASSERT(s->location == Span::ON_NORMAL_FREELIST);
+ RemoveFromFreeList(s);
+ const Length n = s->length;
+ TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
+ static_cast<size_t>(s->length << kPageShift));
+ s->location = Span::ON_RETURNED_FREELIST;
+ MergeIntoFreeList(s); // Coalesces if possible.
+ return n;
+}
+
+Length PageHeap::ReleaseAtLeastNPages(Length num_pages) {
+ Length released_pages = 0;
+ Length prev_released_pages = -1;
+
+ // Round robin through the lists of free spans, releasing the last
+ // span in each list. Stop after releasing at least num_pages.
+ while (released_pages < num_pages) {
+ if (released_pages == prev_released_pages) {
+ // Last iteration of while loop made no progress.
+ break;
+ }
+ prev_released_pages = released_pages;
+
+ for (int i = 0; i < kMaxPages+1 && released_pages < num_pages;
+ i++, release_index_++) {
+ if (release_index_ > kMaxPages) release_index_ = 0;
+ SpanList* slist = (release_index_ == kMaxPages) ?
+ &large_ : &free_[release_index_];
+ if (!DLL_IsEmpty(&slist->normal)) {
+ Length released_len = ReleaseLastNormalSpan(slist);
+ released_pages += released_len;
+ }
+ }
+ }
+ return released_pages;
+}
+
+void PageHeap::RegisterSizeClass(Span* span, size_t 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);
+ Event(span, 'C', sc);
+ 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 s = 0; s < kMaxPages; s++) {
+ result->normal_length[s] = DLL_Length(&free_[s].normal);
+ result->returned_length[s] = DLL_Length(&free_[s].returned);
+ }
+}
+
+void PageHeap::GetLargeSpanStats(LargeSpanStats* result) {
+ result->spans = 0;
+ result->normal_pages = 0;
+ result->returned_pages = 0;
+ for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
+ result->normal_pages += s->length;;
+ result->spans++;
+ }
+ for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
+ result->returned_pages += s->length;
+ result->spans++;
+ }
+}
+
+bool PageHeap::GetNextRange(PageID start, base::MallocRange* r) {
+ Span* span = reinterpret_cast<Span*>(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<void*>(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<Length>(kMinSystemAlloc);
+ size_t actual_size;
+ void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
+ if (ptr == NULL) {
+ if (n < ask) {
+ // Try growing just "n" pages
+ ask = n;
+ ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
+ }
+ if (ptr == NULL) return false;
+ }
+ ask = actual_size >> kPageShift;
+ RecordGrowth(ask << kPageShift);
+
+ uint64_t old_system_bytes = stats_.system_bytes;
+ stats_.system_bytes += (ask << kPageShift);
+ const PageID p = reinterpret_cast<uintptr_t>(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(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() {
+ ASSERT(free_[0].normal.next == &free_[0].normal);
+ ASSERT(free_[0].returned.next == &free_[0].returned);
+ return true;
+}
+
+bool PageHeap::CheckExpensive() {
+ bool result = Check();
+ CheckList(&large_.normal, kMaxPages, 1000000000, Span::ON_NORMAL_FREELIST);
+ CheckList(&large_.returned, kMaxPages, 1000000000, Span::ON_RETURNED_FREELIST);
+ for (Length s = 1; s < kMaxPages; s++) {
+ CheckList(&free_[s].normal, s, s, Span::ON_NORMAL_FREELIST);
+ CheckList(&free_[s].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;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/vendor/src/page_heap.h b/chromium/third_party/tcmalloc/vendor/src/page_heap.h
new file mode 100644
index 00000000000..37188010a6f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/page_heap.h
@@ -0,0 +1,294 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_PAGE_HEAP_H_
+#define TCMALLOC_PAGE_HEAP_H_
+
+#include <config.h>
+#include <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint64_t, int64_t, uint16_t
+#endif
+#include <gperftools/malloc_extension.h>
+#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 <gperftools/stacktrace.h>
+#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 <int BITS> class MapSelector {
+ public:
+ typedef TCMalloc_PageMap3<BITS-kPageShift> Type;
+ typedef PackedCache<BITS-kPageShift, uint64_t> CacheType;
+};
+
+// A two-level map for 32-bit machines
+template <> class MapSelector<32> {
+ public:
+ typedef TCMalloc_PageMap2<32-kPageShift> Type;
+ typedef PackedCache<32-kPageShift, uint16_t> CacheType;
+};
+
+// -------------------------------------------------------------------------
+// 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, size_t 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 Span* GetDescriptor(PageID p) const {
+ return reinterpret_cast<Span*>(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) {}
+ 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
+ };
+ 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.
+ 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
+
+ // 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);
+
+ // Return 0 if we have no information, or else the correct sizeclass for p.
+ // Reads and writes to pagemap_cache_ do not require locking.
+ // The entries are 64 bits on 64-bit hardware and 16 bits on
+ // 32-bit hardware, and we don't mind raciness as long as each read of
+ // an entry yields a valid entry, not a partially updated entry.
+ size_t GetSizeClassIfCached(PageID p) const {
+ return pagemap_cache_.GetOrDefault(p, 0);
+ }
+ void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); }
+
+ 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<kAddressBits>::Type PageMap;
+ typedef MapSelector<kAddressBits>::CacheType PageMapCache;
+ PageMap pagemap_;
+ mutable PageMapCache pagemap_cache_;
+
+ // 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;
+ };
+
+ // List of free spans of length >= kMaxPages
+ SpanList large_;
+
+ // Array mapping from span length to a doubly linked list of free spans
+ 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);
+
+ // 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);
+
+ // Release the last span on the normal portion of this list.
+ // Return the length of that span.
+ Length ReleaseLastNormalSpan(SpanList* slist);
+
+
+ // 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_;
+};
+
+} // namespace tcmalloc
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // TCMALLOC_PAGE_HEAP_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/page_heap_allocator.h b/chromium/third_party/tcmalloc/vendor/src/page_heap_allocator.h
new file mode 100644
index 00000000000..d83528203f1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/page_heap_allocator.h
@@ -0,0 +1,113 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
+#define TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
+
+#include <stddef.h> // 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 T>
+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<void**>(result));
+ } else {
+ if (free_avail_ < sizeof(T)) {
+ // Need more room. We assume that MetaDataAlloc returns
+ // suitably aligned memory.
+ free_area_ = reinterpret_cast<char*>(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<T*>(result);
+ }
+
+ void Delete(T* p) {
+ *(reinterpret_cast<void**>(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_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_PAGE_HEAP_ALLOCATOR_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/pagemap.h b/chromium/third_party/tcmalloc/vendor/src/pagemap.h
new file mode 100644
index 00000000000..27cb3da050f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/pagemap.h
@@ -0,0 +1,323 @@
+// 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 <opensource@google.com>
+//
+// 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 <stddef.h> // for NULL, size_t
+#include <string.h> // for memset
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#include "internal_logging.h" // for ASSERT
+
+// Single-level array
+template <int BITS>
+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<void**>((*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.
+ 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 <int BITS>
+class TCMalloc_PageMap2 {
+ private:
+ // Put 32 entries in the root and (2^BITS)/32 entries in each leaf.
+ static const int ROOT_BITS = 5;
+ static const int ROOT_LENGTH = 1 << ROOT_BITS;
+
+ static const int LEAF_BITS = BITS - ROOT_BITS;
+ static const int LEAF_LENGTH = 1 << LEAF_BITS;
+
+ // Leaf node
+ struct Leaf {
+ void* values[LEAF_LENGTH];
+ };
+
+ Leaf* root_[ROOT_LENGTH]; // Pointers to 32 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_));
+ }
+
+ 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) {
+ ASSERT(k >> BITS == 0);
+ const Number i1 = k >> LEAF_BITS;
+ const Number i2 = k & (LEAF_LENGTH-1);
+ 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<Leaf*>((*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
+ Ensure(0, 1 << BITS);
+ }
+
+ void* Next(Number k) const {
+ while (k < (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 <int BITS>
+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<Node*>((*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;
+ root_ = NewNode();
+ }
+
+ 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<Leaf*>(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<Leaf*>(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<Leaf*>((*allocator_)(sizeof(Leaf)));
+ if (leaf == NULL) return false;
+ memset(leaf, 0, sizeof(*leaf));
+ root_->ptrs[i1]->ptrs[i2] = reinterpret_cast<Node*>(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<Leaf*>(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/chromium/third_party/tcmalloc/vendor/src/pprof b/chromium/third_party/tcmalloc/vendor/src/pprof
new file mode 100644
index 00000000000..727eb43704f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/pprof
@@ -0,0 +1,5348 @@
+#! /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:
+# <count> <stack trace>
+# 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=<regexp> 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=<regexp> 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;
+
+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;
+
+##### Argument parsing #####
+
+sub usage_string {
+ return <<EOF;
+Usage:
+pprof [options] <program> <profiles>
+ <profiles> is a space separated list of profile names.
+pprof [options] <symbolized-profiles>
+ <symbolized-profiles> is a list of profile files where each file contains
+ the necessary symbol mappings as well as profile data (likely generated
+ with --raw).
+pprof [options] <profile>
+ <profile> 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[/<service>] - a location of a service to get profile from
+
+ The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile,
+ $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall,
+ $CENSUSPROFILE_PAGE, or /pprof/filteredprofile.
+ For instance:
+ pprof http://myserver.com:80$HEAP_PAGE
+ If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling).
+pprof --symbols <program>
+ 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=<base> Subtract <base> from <profile> before display
+ --interactive Run in interactive mode (interactive "help" gives help) [default]
+ --seconds=<n> Length of time for dynamic profiles [default=30 secs]
+ --add_lib=<file> Read additional symbols and line info from the given library
+ --lib_prefix=<dir> Comma separated list of library path prefixes
+
+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
+ --callgrind Generate callgrind format to stdout
+ --gv Generate Postscript and display
+ --evince Generate PDF and display
+ --web Generate SVG and display
+ --list=<regexp> Generate source listing of matching routines
+ --disasm=<regexp> Generate disassembly of matching routines
+ --symbols Print demangled symbol names found at given addresses
+ --dot Generate DOT file to stdout
+ --ps Generate Postcript 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)
+
+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=<n> Show at most so many nodes [default=80]
+ --nodefraction=<f> Hide nodes below <f>*total [default=.005]
+ --edgefraction=<f> Hide edges below <f>*total [default=.001]
+ --maxdegree=<n> Max incoming/outgoing edges per node [default=8]
+ --focus=<regexp> Focus on nodes matching <regexp>
+ --ignore=<regexp> Ignore nodes matching <regexp>
+ --scale=<n> Set GV scaling [default=0]
+ --heapcheck Make nodes with non-0 object counts
+ (i.e. direct leak generators) more visible
+
+Miscellaneous:
+ --tools=<prefix or binary:fullpath>[,...] \$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:
+
+pprof /bin/ls ls.prof
+ Enters "interactive" mode
+pprof --text /bin/ls ls.prof
+ Outputs one line per procedure
+pprof --web /bin/ls ls.prof
+ Displays annotated call-graph in web browser
+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 http://localhost:1234/
+ Enters "interactive" mode
+pprof --text localhost:1234
+ Outputs one line per procedure for localhost:1234
+pprof --raw localhost:1234 > ./local.raw
+pprof --text ./local.raw
+ Fetches a remote profile for later analysis and then
+ analyzes it in text mode.
+EOF
+}
+
+sub version_string {
+ return <<EOF
+pprof (part of gperftools $PPROF_VERSION)
+
+Copyright 1998-2007 Google Inc.
+
+This is BSD licensed software; see the source for copying conditions
+and license information.
+There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.
+EOF
+}
+
+sub usage {
+ my $msg = shift;
+ print STDERR "$msg\n\n";
+ print STDERR usage_string();
+ print STDERR "\nFATAL ERROR: $msg\n"; # just as a reminder
+ exit(1);
+}
+
+sub Init() {
+ # Setup tmp-file name and handler to clean it up.
+ # We do this in the very beginning so that we can use
+ # error() and cleanup() function anytime here after.
+ $main::tmpfile_sym = "/tmp/pprof$$.sym";
+ $main::tmpfile_ps = "/tmp/pprof$$";
+ $main::next_tmpfile = 0;
+ $SIG{'INT'} = \&sighandler;
+
+ # Cache from filename/linenumber to source code
+ $main::source_cache = ();
+
+ $main::opt_help = 0;
+ $main::opt_version = 0;
+
+ $main::opt_cum = 0;
+ $main::opt_base = '';
+ $main::opt_addresses = 0;
+ $main::opt_lines = 0;
+ $main::opt_functions = 0;
+ $main::opt_files = 0;
+ $main::opt_lib_prefix = "";
+
+ $main::opt_text = 0;
+ $main::opt_callgrind = 0;
+ $main::opt_list = "";
+ $main::opt_disasm = "";
+ $main::opt_symbols = 0;
+ $main::opt_gv = 0;
+ $main::opt_evince = 0;
+ $main::opt_web = 0;
+ $main::opt_dot = 0;
+ $main::opt_ps = 0;
+ $main::opt_pdf = 0;
+ $main::opt_gif = 0;
+ $main::opt_svg = 0;
+ $main::opt_raw = 0;
+
+ $main::opt_nodecount = 80;
+ $main::opt_nodefraction = 0.005;
+ $main::opt_edgefraction = 0.001;
+ $main::opt_maxdegree = 8;
+ $main::opt_focus = '';
+ $main::opt_ignore = '';
+ $main::opt_scale = 0;
+ $main::opt_heapcheck = 0;
+ $main::opt_seconds = 30;
+ $main::opt_lib = "";
+
+ $main::opt_inuse_space = 0;
+ $main::opt_inuse_objects = 0;
+ $main::opt_alloc_space = 0;
+ $main::opt_alloc_objects = 0;
+ $main::opt_show_bytes = 0;
+ $main::opt_drop_negative = 0;
+ $main::opt_interactive = 0;
+
+ $main::opt_total_delay = 0;
+ $main::opt_contentions = 0;
+ $main::opt_mean_delay = 0;
+
+ $main::opt_tools = "";
+ $main::opt_debug = 0;
+ $main::opt_test = 0;
+
+ # These are undocumented flags used only by unittests.
+ $main::opt_test_stride = 0;
+
+ # Are we using $SYMBOL_PAGE?
+ $main::use_symbol_page = 0;
+
+ # Files returned by TempName.
+ %main::tempnames = ();
+
+ # Type of profile we are dealing with
+ # Supported types:
+ # cpu
+ # heap
+ # growth
+ # contention
+ $main::profile_type = ''; # Empty type means "unknown"
+
+ GetOptions("help!" => \$main::opt_help,
+ "version!" => \$main::opt_version,
+ "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,
+ "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,
+ "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,
+ "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_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])) {
+ $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());
+ }
+ PrintText($symbols, $flat, $cumulative, -1);
+ } elsif ($main::opt_raw) {
+ PrintSymbolizedProfile($symbols, $profile, $main::prog);
+ } 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;
+ }
+
+ # 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) ";
+ $_ = <STDIN>;
+ 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 <<ENDOFHELP;
+Interactive pprof mode
+
+Commands:
+ gv
+ gv [focus] [-ignore1] [-ignore2]
+ Show graphical hierarchical display of current profile. Without
+ any arguments, shows all samples in the profile. With the optional
+ "focus" argument, restricts the samples shown to just those where
+ the "focus" regular expression matches a routine name on the stack
+ trace.
+
+ web
+ web [focus] [-ignore1] [-ignore2]
+ Like GV, but displays profile in your web browser instead of using
+ Ghostview. Works best if your web browser is already running.
+ To change the browser that gets used:
+ On Linux, set the /etc/alternatives/gnome-www-browser symlink.
+ On OS X, change the Finder association for SVG files.
+
+ list [routine_regexp] [-ignore1] [-ignore2]
+ Show source listing of routines whose names match "routine_regexp"
+
+ weblist [routine_regexp] [-ignore1] [-ignore2]
+ Displays a source listing of routines whose names match "routine_regexp"
+ in a web browser. You can click on source lines to view the
+ corresponding disassembly.
+
+ top [--cum] [-ignore1] [-ignore2]
+ top20 [--cum] [-ignore1] [-ignore2]
+ top37 [--cum] [-ignore1] [-ignore2]
+ Show top lines ordered by flat profile count, or cumulative count
+ if --cum is specified. If a number is present after 'top', the
+ top K routines will be shown (defaults to showing the top 10)
+
+ disasm [routine_regexp] [-ignore1] [-ignore2]
+ Show disassembly of routines whose names match "routine_regexp",
+ annotated with sample counts.
+
+ callgrind
+ callgrind [filename]
+ Generates callgrind file. If no filename is given, kcachegrind is called.
+
+ help - This listing
+ quit or ^D - End pprof
+
+For commands that accept optional -ignore tags, samples where any routine in
+the stack trace matches the regular expression in any of the -ignore
+parameters will be ignored.
+
+Further pprof details are available at this location (or one similar):
+
+ /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html
+ /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html
+
+ENDOFHELP
+}
+sub ParseInteractiveArgs {
+ my $args = shift;
+ my $focus = "";
+ my $ignore = "";
+ my @x = split(/ +/, $args);
+ foreach $a (@x) {
+ if ($a =~ m/^(--|-)lines$/) {
+ $main::opt_lines = 1;
+ } elsif ($a =~ m/^(--|-)cum$/) {
+ $main::opt_cum = 1;
+ } elsif ($a =~ m/^-(.*)/) {
+ $ignore .= (($ignore ne "") ? "|" : "" ) . $1;
+ } else {
+ $focus .= (($focus ne "") ? "|" : "" ) . $a;
+ }
+ }
+ if ($ignore ne "") {
+ print STDERR "Ignoring samples in call stacks that match '$ignore'\n";
+ }
+ return ($focus, $ignore);
+}
+
+##### Output code #####
+
+sub TempName {
+ my $fnum = shift;
+ my $ext = shift;
+ my $file = "$main::tmpfile_ps.$fnum.$ext";
+ $main::tempnames{$file} = 1;
+ return $file;
+}
+
+# Print profile data in packed binary format (64-bit) to standard out
+sub PrintProfileData {
+ my $profile = shift;
+
+ # print header (64-bit style)
+ # (zero) (header-size) (version) (sample-period) (zero)
+ print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
+
+ foreach my $k (keys(%{$profile})) {
+ my $count = $profile->{$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.
+ 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
+ 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 (<SRC>) {
+ 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;
+
+ 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");
+ printf 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.
+ printf CG CompressedCGName("fl", $caller_file, \%filename_to_index_map);
+ printf CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map);
+ if (defined $6) {
+ printf CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map);
+ printf CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map);
+ printf CG ("calls=$count $callee_line\n");
+ }
+ printf 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 (<OBJDUMP>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ chop;
+ if (m|\s*([^:\s]+):(\d+)\s*$|) {
+ # Location line of the form:
+ # <filename>:<linenumber>
+ $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 ("<div class=\"legend\">%s<br>Total: %s %s</div>\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';
+<DOCTYPE html>
+<html>
+<head>
+<title>Pprof listing</title>
+<style type="text/css">
+body {
+ font-family: sans-serif;
+}
+h1 {
+ font-size: 1.5em;
+ margin-bottom: 4px;
+}
+.legend {
+ font-size: 1.25em;
+}
+.line {
+ color: #aaaaaa;
+}
+.nop {
+ color: #aaaaaa;
+}
+.unimportant {
+ color: #cccccc;
+}
+.disasmloc {
+ color: #000000;
+}
+.deadsrc {
+ cursor: pointer;
+}
+.deadsrc:hover {
+ background-color: #eeeeee;
+}
+.livesrc {
+ color: #0000ff;
+ cursor: pointer;
+}
+.livesrc:hover {
+ background-color: #eeeeee;
+}
+.asm {
+ color: #008800;
+ display: none;
+}
+</style>
+<script type="text/javascript">
+function pprof_toggle_asm(e) {
+ var target;
+ if (!e) e = window.event;
+ if (e.target) target = e.target;
+ else if (e.srcElement) target = e.srcElement;
+
+ if (target) {
+ var asm = target.nextSibling;
+ if (asm && asm.className == "asm") {
+ asm.style.display = (asm.style.display == "block" ? "" : "block");
+ e.preventDefault();
+ return false;
+ }
+ }
+}
+</script>
+</head>
+<body>
+EOF
+}
+
+sub HtmlListingFooter {
+ return <<'EOF';
+</body>
+</html>
+EOF
+}
+
+sub HtmlEscape {
+ my $text = shift;
+ $text =~ s/&/&amp;/g;
+ $text =~ s/</&lt;/g;
+ $text =~ s/>/&gt;/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 (<FILE>) {
+ 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("<span class=disasmloc>%s:%d</span>",
+ HtmlEscape(CleanFileName($f)), $l);
+ } elsif ($l ne $last_dis_linenum) {
+ # De-emphasize the unchanged file name portion
+ $dis .= sprintf("<span class=unimportant>%s</span>" .
+ "<span class=disasmloc>:%d</span>",
+ HtmlEscape(CleanFileName($f)), $l);
+ } else {
+ # De-emphasize the entire location
+ $dis .= sprintf("<span class=unimportant>%s:%d</span>",
+ 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 (
+ "<h1>%s</h1>%s\n<pre onClick=\"pprof_toggle_asm()\">\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 (<FILE>) {
+ 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 = "<span class=\"asm\">" . $dis . "</span>";
+ }
+ my $source_class = (($n1 + $n2 > 0)
+ ? "livesrc"
+ : (($asm ne "") ? "deadsrc" : "nop"));
+ printf $output (
+ "<span class=\"line\">%5d</span> " .
+ "<span class=\"%s\">%6s %6s %s</span>%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 "</pre>\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 (<FILE>) {
+ 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 = <SVG>;
+ close(SVG);
+ unlink $svgfile;
+ my $svg = join('', @svg);
+
+ # Dot's SVG output is
+ #
+ # <svg width="___" height="___"
+ # viewBox="___" xmlns=...>
+ # <g id="graph0" transform="...">
+ # ...
+ # </g>
+ # </svg>
+ #
+ # Change it to
+ #
+ # <svg width="100%" height="100%"
+ # xmlns=...>
+ # $svg_javascript
+ # <g id="viewport" transform="translate(0,0)">
+ # <g id="graph0" transform="...">
+ # ...
+ # </g>
+ # </g>
+ # </svg>
+
+ # Fix width, height; drop viewBox.
+ $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/;
+
+ # Insert script, viewport <g> above first <g>
+ my $svg_javascript = SvgJavascript();
+ my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n";
+ $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/;
+
+ # Insert final </g> above </svg>.
+ $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/;
+ $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/;
+
+ if ($main::opt_svg) {
+ # --svg: write to standard output.
+ print $svg;
+ } else {
+ # Write back to temporary file.
+ open(SVG, ">$svgfile") || die "open $svgfile: $!";
+ print SVG $svg;
+ close(SVG);
+ }
+}
+
+sub SvgJavascript {
+ return <<'EOF';
+<script type="text/ecmascript"><![CDATA[
+// SVGPan
+// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/
+// Local modification: if(true || ...) below to force panning, never moving.
+
+/**
+ * SVGPan library 1.2
+ * ====================
+ *
+ * Given an unique existing element with id "viewport", including the
+ * the library into any SVG adds the following capabilities:
+ *
+ * - Mouse panning
+ * - Mouse zooming (using the wheel)
+ * - Object dargging
+ *
+ * Known issues:
+ *
+ * - Zooming (while panning) on Safari has still some issues
+ *
+ * Releases:
+ *
+ * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
+ * Fixed a bug with browser mouse handler interaction
+ *
+ * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui
+ * Updated the zoom code to support the mouse wheel on Safari/Chrome
+ *
+ * 1.0, Andrea Leofreddi
+ * First release
+ *
+ * This code is licensed under the following BSD license:
+ *
+ * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``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 Andrea Leofreddi 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 views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of Andrea Leofreddi.
+ */
+
+var root = document.documentElement;
+
+var state = 'none', stateTarget, stateOrigin, stateTf;
+
+setupHandlers(root);
+
+/**
+ * Register handlers
+ */
+function setupHandlers(root){
+ setAttributes(root, {
+ "onmouseup" : "add(evt)",
+ "onmousedown" : "handleMouseDown(evt)",
+ "onmousemove" : "handleMouseMove(evt)",
+ "onmouseup" : "handleMouseUp(evt)",
+ //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element
+ });
+
+ if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
+ window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
+ else
+ window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
+
+ var g = svgDoc.getElementById("svg");
+ g.width = "100%";
+ g.height = "100%";
+}
+
+/**
+ * Instance an SVGPoint object with given event coordinates.
+ */
+function getEventPoint(evt) {
+ var p = root.createSVGPoint();
+
+ p.x = evt.clientX;
+ p.y = evt.clientY;
+
+ return p;
+}
+
+/**
+ * Sets the current transform matrix of an element.
+ */
+function setCTM(element, matrix) {
+ var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
+
+ element.setAttribute("transform", s);
+}
+
+/**
+ * Dumps a matrix to a string (useful for debug).
+ */
+function dumpMatrix(matrix) {
+ var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]";
+
+ return s;
+}
+
+/**
+ * Sets attributes of an element.
+ */
+function setAttributes(element, attributes){
+ for (i in attributes)
+ element.setAttributeNS(null, i, attributes[i]);
+}
+
+/**
+ * Handle mouse move event.
+ */
+function handleMouseWheel(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var delta;
+
+ if(evt.wheelDelta)
+ delta = evt.wheelDelta / 3600; // Chrome/Safari
+ else
+ delta = evt.detail / -90; // Mozilla
+
+ var z = 1 + delta; // Zoom factor: 0.9/1.1
+
+ var g = svgDoc.getElementById("viewport");
+
+ var p = getEventPoint(evt);
+
+ p = p.matrixTransform(g.getCTM().inverse());
+
+ // Compute new scale matrix in current mouse position
+ var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
+
+ setCTM(g, g.getCTM().multiply(k));
+
+ stateTf = stateTf.multiply(k.inverse());
+}
+
+/**
+ * Handle mouse move event.
+ */
+function handleMouseMove(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var g = svgDoc.getElementById("viewport");
+
+ if(state == 'pan') {
+ // Pan mode
+ var p = getEventPoint(evt).matrixTransform(stateTf);
+
+ setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
+ } else if(state == 'move') {
+ // Move mode
+ var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());
+
+ setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));
+
+ stateOrigin = p;
+ }
+}
+
+/**
+ * Handle click event.
+ */
+function handleMouseDown(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ var g = svgDoc.getElementById("viewport");
+
+ if(true || evt.target.tagName == "svg") {
+ // Pan mode
+ state = 'pan';
+
+ stateTf = g.getCTM().inverse();
+
+ stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
+ } else {
+ // Move mode
+ state = 'move';
+
+ stateTarget = evt.target;
+
+ stateTf = g.getCTM().inverse();
+
+ stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
+ }
+}
+
+/**
+ * Handle mouse button release event.
+ */
+function handleMouseUp(evt) {
+ if(evt.preventDefault)
+ evt.preventDefault();
+
+ evt.returnValue = false;
+
+ var svgDoc = evt.target.ownerDocument;
+
+ if(state == 'pan' || state == 'move') {
+ // Quit pan mode
+ state = '';
+ }
+}
+
+]]></script>
+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");
+ } else {
+ push(@result, "$func $fileline");
+ }
+ } elsif ($main::opt_functions) {
+ if ($func eq '??') {
+ push(@result, "$a");
+ } else {
+ push(@result, $func);
+ }
+ } 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 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 = "??: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 $destination = ExtractSymbolLocation($symbols, $address[0]);
+ AddEntry($calls, $destination, $count);
+ for (my $i = 1; $i <= $#address; $i++) {
+ my $source = ExtractSymbolLocation($symbols, $address[$i]);
+ my $call = "$source -> $destination";
+ AddEntry($calls, $call, $count);
+ $destination = $source;
+ }
+ }
+
+ return $calls;
+}
+
+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') {
+ # 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];
+ }
+ print STDERR "Removing $second_pc from all stack traces.\n";
+ foreach my $k (keys(%{$profile})) {
+ my $count = $profile->{$k};
+ my @addrs = split(/\n/, $k);
+ 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 = <SYMBOL>;
+ $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>;
+ $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 (<CMDLINE>) {
+ 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 = shift;
+ 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=<value>' 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 = <PROFILE>)) {
+ $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 * 4, 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] @ <heap-url>/266053
+ # There are two pairs <count: size>, 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] @ <heap-url>_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 (<PROFILE>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ if (/^MAPPED_LIBRARIES:/) {
+ # Read the /proc/self/maps data
+ while (<PROFILE>) {
+ 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 (<PROFILE>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ # Parse "build=<dir>" 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:
+ # <count1>: <bytes1> [<count2>: <bytes2>] @ 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);
+ AddEntries($profile, $pcs, FixCallerAddresses($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 = <PROFILE> ) {
+ $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";
+ }
+ 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 (<OBJDUMP>) {
+ 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 (<OTOOL>) {
+ $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 = 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+(\S+\.(so|dll|dylib|bundle)((\.\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;
+ } 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;
+
+ # 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("----\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 (<SYMBOLS>) {
+ # Read fullfunction and filelineinfo from next pair of lines
+ s/\r?\n$//g;
+ my $fullfunction = $_;
+ $_ = <SYMBOLS>;
+ 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
+
+ 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
+ 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
+ # <tool>:<path>. 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 " pprof \\\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 $symbol_table = {};
+ open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n");
+ my $last_start = "0";
+ my $routine = "";
+ while (<NM>) {
+ 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)];
+ }
+ return $symbol_table;
+}
+
+# Gets the procedure boundaries for all routines in "$image" whose names
+# match "$regexp" and returns them in a hashtable mapping from procedure
+# name to a two-element vector of [start address, end address].
+# Will return an empty map if nm is not installed or not working properly.
+sub GetProcedureBoundaries {
+ my $image = shift;
+ my $regexp = shift;
+
+ # If $image doesn't start with /, then put ./ in front of it. This works
+ # around an obnoxious bug in our probing of nm -f behavior.
+ # "nm -f $image" is supposed to fail on GNU nm, but if:
+ #
+ # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND
+ # b. you have a.out in your current directory (a not uncommon occurence)
+ #
+ # then "nm -f $image" succeeds because -f only looks at the first letter of
+ # the argument, which looks valid because it's [BbSsPp], and then since
+ # there's no image provided, it looks for a.out and finds it.
+ #
+ # This regex makes sure that $image starts with . or /, forcing the -f
+ # parsing to fail since . and / are not valid formats.
+ $image =~ s#^[^/]#./$&#;
+
+ # For libc libraries, the copy in /usr/lib/debug contains debugging symbols
+ my $debugging = DebuggingLibrary($image);
+ if ($debugging) {
+ $image = $debugging;
+ }
+
+ my $nm = $obj_tool_map{"nm"};
+ my $cppfilt = $obj_tool_map{"c++filt"};
+
+ # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
+ # binary doesn't support --demangle. In addition, for OS X we need
+ # to use the -f flag to get 'flat' nm output (otherwise we don't sort
+ # properly and get incorrect results). Unfortunately, GNU nm uses -f
+ # in an incompatible way. So first we test whether our nm supports
+ # --demangle and -f.
+ my $demangle_flag = "";
+ my $cppfilt_flag = "";
+ my $to_devnull = ">$dev_null 2>&1";
+ if (system(ShellEscape($nm, "--demangle", "image") . $to_devnull) == 0) {
+ # In this mode, we do "nm --demangle <foo>"
+ $demangle_flag = "--demangle";
+ $cppfilt_flag = "";
+ } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) {
+ # In this mode, we do "nm <foo> | 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);
+ 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/chromium/third_party/tcmalloc/vendor/src/profile-handler.cc b/chromium/third_party/tcmalloc/vendor/src/profile-handler.cc
new file mode 100644
index 00000000000..20e5cca90cf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/profile-handler.cc
@@ -0,0 +1,555 @@
+// 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 <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <list>
+#include <string>
+
+#include "base/dynamic_annotations.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "maybe_threads.h"
+
+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;
+};
+
+// 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. On systems which
+ // have a separate interval timer for each thread, this function starts the
+ // timer for the current thread.
+ //
+ // The function also attempts to determine whether or not timers are shared by
+ // all threads in the process. (With LinuxThreads, and with NPTL on some
+ // Linux kernel versions, each thread has separate timers.)
+ //
+ // Prior to determining whether timers are shared, this function will
+ // unconditionally start the timer. However, if this function determines
+ // that timers are shared, then it will stop the timer if no callbacks are
+ // currently registered.
+ 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. Registration of the first callback enables the
+ // SIGPROF handler (or SIGALRM if using ITIMER_REAL).
+ ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback,
+ void* callback_arg);
+
+ // Unregisters a previously registered callback. Expects the token returned
+ // by the corresponding RegisterCallback routine. Unregistering the last
+ // callback disables the SIGPROF handler (or SIGALRM if using ITIMER_REAL).
+ void UnregisterCallback(ProfileHandlerToken* token)
+ NO_THREAD_SAFETY_ANALYSIS;
+
+ // Unregisters all the callbacks, stops the timer if shared, disables the
+ // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state.
+ 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();
+
+ // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received.
+ int64 interrupts_ GUARDED_BY(signal_lock_);
+
+ // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
+ int32 frequency_;
+
+ // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
+ int timer_type_;
+
+ // Counts the number of callbacks registered.
+ int32 callback_count_ GUARDED_BY(control_lock_);
+
+ // Is profiling allowed at all?
+ bool allowed_;
+
+ // Whether or not the threading system provides interval timers that are
+ // shared by all threads in a process.
+ enum {
+ // No timer initialization attempted yet.
+ TIMERS_UNTOUCHED,
+ // First thread has registered and set timer.
+ TIMERS_ONE_SET,
+ // Timers are shared by all threads.
+ TIMERS_SHARED,
+ // Timers are separate in each thread.
+ TIMERS_SEPARATE
+ } timer_sharing_ GUARDED_BY(control_lock_);
+
+ // 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<ProfileHandlerToken*> CallbackList;
+ typedef CallbackList::iterator CallbackIterator;
+ CallbackList callbacks_ GUARDED_BY(signal_lock_);
+
+ // Starts the interval timer. If the thread library shares timers between
+ // threads, this function starts the shared timer. Otherwise, this will start
+ // the timer in the current thread.
+ void StartTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Stops the interval timer. If the thread library shares timers between
+ // threads, this fucntion stops the shared timer. Otherwise, this will stop
+ // the timer in the current thread.
+ void StopTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Returns true if the profile interval timer is enabled in the current
+ // thread. This actually checks the kernel's interval timer setting. (It is
+ // used to detect whether timers are shared or separate.)
+ bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Sets the timer interrupt signal handler.
+ void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Disables (ignores) the timer interrupt signal.
+ void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+
+ // Returns true if the handler is not being used by something else.
+ // This checks the kernel's signal handler table.
+ bool IsSignalHandlerAvailable();
+
+ // SIGPROF/SIGALRM handler. Iterate over and call 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
+// 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;
+
+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()
+ : interrupts_(0),
+ callback_count_(0),
+ allowed_(true),
+ timer_sharing_(TIMERS_UNTOUCHED) {
+ SpinLockHolder cl(&control_lock_);
+
+ timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
+
+ // 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 something else is using the signal handler,
+ // assume it has priority over us and stop.
+ if (!IsSignalHandlerAvailable()) {
+ RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.",
+ timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF");
+ allowed_ = false;
+ return;
+ }
+
+ // Ignore signals until we decide to turn profiling on. (Paranoia;
+ // should already be ignored.)
+ DisableHandler();
+}
+
+ProfileHandler::~ProfileHandler() {
+ Reset();
+}
+
+void ProfileHandler::RegisterThread() {
+ SpinLockHolder cl(&control_lock_);
+
+ if (!allowed_) {
+ return;
+ }
+
+ // We try to detect whether timers are being shared by setting a
+ // timer in the first call to this function, then checking whether
+ // it's set in the second call.
+ //
+ // Note that this detection method requires that the first two calls
+ // to RegisterThread must be made from different threads. (Subsequent
+ // calls will see timer_sharing_ set to either TIMERS_SEPARATE or
+ // TIMERS_SHARED, and won't try to detect the timer sharing type.)
+ //
+ // Also note that if timer settings were inherited across new thread
+ // creation but *not* shared, this approach wouldn't work. That's
+ // not an issue for any Linux threading implementation, and should
+ // not be a problem for a POSIX-compliant threads implementation.
+ switch (timer_sharing_) {
+ case TIMERS_UNTOUCHED:
+ StartTimer();
+ timer_sharing_ = TIMERS_ONE_SET;
+ break;
+ case TIMERS_ONE_SET:
+ // If the timer is running, that means that the main thread's
+ // timer setup is seen in this (second) thread -- and therefore
+ // that timers are shared.
+ if (IsTimerRunning()) {
+ timer_sharing_ = TIMERS_SHARED;
+ // If callback is already registered, we have to keep the timer
+ // running. If not, we disable the timer here.
+ if (callback_count_ == 0) {
+ StopTimer();
+ }
+ } else {
+ timer_sharing_ = TIMERS_SEPARATE;
+ StartTimer();
+ }
+ break;
+ case TIMERS_SHARED:
+ // Nothing needed.
+ break;
+ case TIMERS_SEPARATE:
+ StartTimer();
+ break;
+ }
+}
+
+ProfileHandlerToken* ProfileHandler::RegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+
+ ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
+
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ callbacks_.push_back(token);
+ }
+ // Start the timer if timer is shared and this is a first callback.
+ if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) {
+ StartTimer();
+ }
+ ++callback_count_;
+ EnableHandler();
+ 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");
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ delete *it;
+ callbacks_.erase(it);
+ }
+ --callback_count_;
+ if (callback_count_ > 0) {
+ EnableHandler();
+ } else if (timer_sharing_ == TIMERS_SHARED) {
+ StopTimer();
+ }
+ return;
+ }
+ }
+ // Unknown token.
+ RAW_LOG(FATAL, "Invalid token");
+}
+
+void ProfileHandler::Reset() {
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_);
+ CallbackIterator it = callbacks_.begin();
+ while (it != callbacks_.end()) {
+ CallbackIterator tmp = it;
+ ++it;
+ delete *tmp;
+ callbacks_.erase(tmp);
+ }
+ }
+ callback_count_ = 0;
+ if (timer_sharing_ == TIMERS_SHARED) {
+ StopTimer();
+ }
+ timer_sharing_ = TIMERS_UNTOUCHED;
+}
+
+void ProfileHandler::GetState(ProfileHandlerState* state) {
+ SpinLockHolder cl(&control_lock_);
+ DisableHandler();
+ {
+ SpinLockHolder sl(&signal_lock_); // Protects interrupts_.
+ state->interrupts = interrupts_;
+ }
+ if (callback_count_ > 0) {
+ EnableHandler();
+ }
+ state->frequency = frequency_;
+ state->callback_count = callback_count_;
+ state->allowed = allowed_;
+}
+
+void ProfileHandler::StartTimer() {
+ if (!allowed_) {
+ return;
+ }
+ struct itimerval timer;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 1000000 / frequency_;
+ timer.it_value = timer.it_interval;
+ setitimer(timer_type_, &timer, 0);
+}
+
+void ProfileHandler::StopTimer() {
+ if (!allowed_) {
+ return;
+ }
+ struct itimerval timer;
+ memset(&timer, 0, sizeof timer);
+ setitimer(timer_type_, &timer, 0);
+}
+
+bool ProfileHandler::IsTimerRunning() {
+ if (!allowed_) {
+ return false;
+ }
+ struct itimerval current_timer;
+ RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
+ return (current_timer.it_value.tv_sec != 0 ||
+ current_timer.it_value.tv_usec != 0);
+}
+
+void ProfileHandler::EnableHandler() {
+ if (!allowed_) {
+ return;
+ }
+ struct sigaction sa;
+ sa.sa_sigaction = SignalHandler;
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)");
+}
+
+void ProfileHandler::DisableHandler() {
+ if (!allowed_) {
+ return;
+ }
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)");
+}
+
+bool ProfileHandler::IsSignalHandlerAvailable() {
+ struct sigaction sa;
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ 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 = ANNOTATE_UNPROTECTED_READ(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());
+
+extern "C" void ProfileHandlerRegisterThread() {
+ ProfileHandler::Instance()->RegisterThread();
+}
+
+extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+ return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
+}
+
+extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
+ ProfileHandler::Instance()->UnregisterCallback(token);
+}
+
+extern "C" void ProfileHandlerReset() {
+ return ProfileHandler::Instance()->Reset();
+}
+
+extern "C" 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.
+extern "C" void ProfileHandlerRegisterThread() {
+}
+
+extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
+ ProfileHandlerCallback callback, void* callback_arg) {
+ return NULL;
+}
+
+extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
+}
+
+extern "C" void ProfileHandlerReset() {
+}
+
+extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
+}
+
+#endif // OS_CYGWIN
diff --git a/chromium/third_party/tcmalloc/vendor/src/profile-handler.h b/chromium/third_party/tcmalloc/vendor/src/profile-handler.h
new file mode 100644
index 00000000000..4b078ecf59e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/profile-handler.h
@@ -0,0 +1,148 @@
+/* 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 registered threads in the program are profiled.
+ * (Note: if using linux 2.4 or earlier, you must use the Thread class, in
+ * google3/thread, to ensure all threads 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 ITIMER_PROF timer and the
+ * SIGPROF signal.
+ */
+
+#ifndef BASE_PROFILE_HANDLER_H_
+#define BASE_PROFILE_HANDLER_H_
+
+#include "config.h"
+#include <signal.h>
+#ifdef COMPILER_MSVC
+#include "conflict-signal.h"
+#endif
+#include "base/basictypes.h"
+
+/* All this code should be usable from within C apps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* BASE_PROFILE_HANDLER_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/profiledata.cc b/chromium/third_party/tcmalloc/vendor/src/profiledata.cc
new file mode 100644
index 00000000000..5f2531bbb00
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/profiledata.cc
@@ -0,0 +1,331 @@
+// 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 <config.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/time.h>
+#include <string.h>
+#include <fcntl.h>
+
+#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/%" PRIuS "\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<Slot>(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<Slot>(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<Slot>(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<char*>(evict_);
+ size_t bytes = sizeof(evict_[0]) * num_evicted_;
+ total_bytes_ += bytes;
+ FDWrite(out_, buf, bytes);
+ }
+ num_evicted_ = 0;
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/profiledata.h b/chromium/third_party/tcmalloc/vendor/src/profiledata.h
new file mode 100644
index 00000000000..3521bac35b6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/profiledata.h
@@ -0,0 +1,183 @@
+// 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
+// doc/cpuprofile-fileformat.html
+
+
+#ifndef BASE_PROFILEDATA_H_
+#define BASE_PROFILEDATA_H_
+
+#include <config.h>
+#include <time.h> // for time_t
+#include <stdint.h>
+#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 = 64; // 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/chromium/third_party/tcmalloc/vendor/src/profiler.cc b/chromium/third_party/tcmalloc/vendor/src/profiler.cc
new file mode 100644
index 00000000000..dfb6aab52f4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/profiler.cc
@@ -0,0 +1,342 @@
+// 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 <signal.h>
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpid()
+#endif
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h>
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
+#else
+typedef int ucontext_t; // just to quiet the compiler, mostly
+#endif
+#include <sys/time.h>
+#include <string>
+#include <gperftools/profiler.h>
+#include <gperftools/stacktrace.h>
+#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"
+#ifdef HAVE_CONFLICT_SIGNAL_H
+#include "conflict-signal.h" /* used on msvc machines */
+#endif
+
+using std::string;
+
+// Collects up all profile data. This is a singleton, which is
+// initialized by a constructor at startup.
+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);
+};
+
+// 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.
+ char fname[PATH_MAX];
+ if (!GetUniquePathFromEnv("CPUPROFILE", fname)) {
+ return;
+ }
+ // We don't enable profiling if setuid -- it's a security risk
+#ifdef HAVE_GETEUID
+ if (getuid() != geteuid())
+ return;
+#endif
+
+ 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<time_t>(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<CpuProfiler*>(cpu_profiler);
+
+ if (instance->filter_ == NULL ||
+ (*instance->filter_)(instance->filter_arg_)) {
+ void* stack[ProfileData::kMaxStackDepth];
+
+ // The top-most active routine doesn't show up as a normal
+ // frame, but as the "pc" value in the signal handler context.
+ stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
+
+ // We skip the top two stack trace entries (this function 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,
+ 2, signal_ucontext);
+ depth++; // To account for pc value in stack[0];
+
+ instance->collector_.Add(depth, 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);
+}
+
+#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));
+}
+
+#endif // OS_CYGWIN
+
+// DEPRECATED routines
+extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
+extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
diff --git a/chromium/third_party/tcmalloc/vendor/src/raw_printer.cc b/chromium/third_party/tcmalloc/vendor/src/raw_printer.cc
new file mode 100644
index 00000000000..730d6e28e43
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/raw_printer.cc
@@ -0,0 +1,71 @@
+// 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 <config.h>
+#include <stdarg.h>
+#include <stdio.h>
+#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/chromium/third_party/tcmalloc/vendor/src/raw_printer.h b/chromium/third_party/tcmalloc/vendor/src/raw_printer.h
new file mode 100644
index 00000000000..62340bb37f7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/raw_printer.h
@@ -0,0 +1,89 @@
+// 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 <config.h>
+#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/chromium/third_party/tcmalloc/vendor/src/sampler.cc b/chromium/third_party/tcmalloc/vendor/src/sampler.cc
new file mode 100644
index 00000000000..0ea6df1503f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/sampler.cc
@@ -0,0 +1,130 @@
+// 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 <algorithm> // For min()
+#include <math.h>
+#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 {
+
+// Statics for Sampler
+double Sampler::log_table_[1<<kFastlogNumBits];
+
+// Populate the lookup table for FastLog2.
+// This approximates the log2 curve with a step function.
+// Steps have height equal to log2 of the mid-point of the step.
+void Sampler::PopulateFastLog2Table() {
+ for (int i = 0; i < (1<<kFastlogNumBits); i++) {
+ log_table_[i] = (log(1.0 + static_cast<double>(i+0.5)/(1<<kFastlogNumBits))
+ / log(2.0));
+ }
+}
+
+int Sampler::GetSamplePeriod() {
+ return FLAGS_tcmalloc_sample_parameter;
+}
+
+// Run this before using your sampler
+void Sampler::Init(uint32_t seed) {
+ // Initialize PRNG
+ if (seed != 0) {
+ rnd_ = seed;
+ } else {
+ rnd_ = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this));
+ if (rnd_ == 0) {
+ rnd_ = 1;
+ }
+ }
+ // Step it forward 20 times for good measure
+ for (int i = 0; i < 20; i++) {
+ rnd_ = NextRandom(rnd_);
+ }
+ // Initialize counter
+ bytes_until_sample_ = PickNextSamplingPoint();
+}
+
+// Initialize the Statics for the Sampler class
+void Sampler::InitStatics() {
+ PopulateFastLog2Table();
+}
+
+// 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
+size_t Sampler::PickNextSamplingPoint() {
+ 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<uint32_t>(rnd_ >> (prng_mod_power - 26)) + 1.0;
+ // Put the computed p-value through the CDF of a geometric.
+ // For faster performance (save ~1/20th exec time), replace
+ // min(0.0, FastLog2(q) - 26) by (Fastlog2(q) - 26.000705)
+ // The value 26.000705 is used rather than 26 to compensate
+ // for inaccuracies in FastLog2 which otherwise result in a
+ // negative answer.
+ return static_cast<size_t>(min(0.0, (FastLog2(q) - 26)) * (-log(2.0)
+ * FLAGS_tcmalloc_sample_parameter) + 1);
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/vendor/src/sampler.h b/chromium/third_party/tcmalloc/vendor/src/sampler.h
new file mode 100644
index 00000000000..8e67fb0249f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/sampler.h
@@ -0,0 +1,179 @@
+// 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 <stddef.h> // for size_t
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint64_t, uint32_t, int32_t
+#endif
+#include <string.h> // for memcpy
+#include "base/basictypes.h" // for ASSERT
+#include "internal_logging.h" // for ASSERT
+
+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 PERFTOOLS_DLL_DECL Sampler {
+ public:
+ // Initialize this sampler.
+ // Passing a seed of 0 gives a non-deterministic
+ // seed value given by casting the object ("this")
+ 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 512K (or FLAG_tcmalloc_sample_parameter)
+ size_t PickNextSamplingPoint();
+
+ // Initialize the statics for the Sampler class
+ static void InitStatics();
+
+ // Returns the current sample period
+ int GetSamplePeriod();
+
+ // The following are public for the purposes of testing
+ static uint64_t NextRandom(uint64_t rnd_); // Returns the next prng value
+ static double FastLog2(const double & d); // Computes Log2(x) quickly
+ static void PopulateFastLog2Table(); // Populate the lookup table
+
+ private:
+ size_t bytes_until_sample_; // Bytes until we sample next
+ uint64_t rnd_; // Cheap random number generator
+
+ // Statics for the fast log
+ // Note that this code may not depend on anything in //util
+ // hence the duplication of functionality here
+ static const int kFastlogNumBits = 10;
+ static const int kFastlogMask = (1 << kFastlogNumBits) - 1;
+ static double log_table_[1<<kFastlogNumBits]; // Constant
+};
+
+inline bool Sampler::SampleAllocation(size_t k) {
+ if (bytes_until_sample_ < k) {
+ bytes_until_sample_ = PickNextSamplingPoint();
+ return true;
+ } else {
+ bytes_until_sample_ -= k;
+ return false;
+ }
+}
+
+// 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 = 0x5DEECE66DLL;
+ const uint64_t prng_add = 0xB;
+ const uint64_t prng_mod_power = 48;
+ const uint64_t prng_mod_mask =
+ ~((~static_cast<uint64_t>(0)) << prng_mod_power);
+ return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+// Adapted from //util/math/fastmath.[h|cc] by Noam Shazeer
+// This mimics the VeryFastLog2 code in those files
+inline double Sampler::FastLog2(const double & d) {
+ ASSERT(d>0);
+ COMPILE_ASSERT(sizeof(d) == sizeof(uint64_t), DoubleMustBe64Bits);
+ uint64_t x;
+ memcpy(&x, &d, sizeof(x)); // we depend on the compiler inlining this
+ const uint32_t x_high = x >> 32;
+ const uint32_t y = x_high >> (20 - kFastlogNumBits) & kFastlogMask;
+ const int32_t exponent = ((x_high >> 20) & 0x7FF) - 1023;
+ return exponent + log_table_[y];
+}
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_SAMPLER_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/solaris/libstdc++.la b/chromium/third_party/tcmalloc/vendor/src/solaris/libstdc++.la
new file mode 100644
index 00000000000..3edf4254192
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/solaris/libstdc++.la
@@ -0,0 +1,51 @@
+# libstdc++.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# ---
+# NOTE: This file lives in /usr/sfw/lib on Solaris 10. Unfortunately,
+# due to an apparent bug in the Solaris 10 6/06 release,
+# /usr/sfw/lib/libstdc++.la is empty. Below is the correct content,
+# according to
+# http://forum.java.sun.com/thread.jspa?threadID=5073150
+# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
+# this copy of the file rather than the empty copy in /usr/sfw/lib.
+#
+# Also see
+# http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
+#
+# Note: this is for 32-bit systems. If you have a 64-bit system,
+# uncomment the appropriate dependency_libs line below.
+# ----
+
+# The name that we can dlopen(3).
+dlname='libstdc++.so.6'
+
+# Names of this library.
+library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
+
+# The name of the static archive.
+old_library='libstdc++.a'
+
+# Libraries that this one depends upon.
+# 32-bit version:
+dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
+# 64-bit version:
+#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
+
+# Version information for libstdc++.
+current=6
+age=0
+revision=3
+
+# Is this an already installed library?
+installed=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/sfw/lib'
diff --git a/chromium/third_party/tcmalloc/vendor/src/span.cc b/chromium/third_party/tcmalloc/vendor/src/span.cc
new file mode 100644
index 00000000000..760094509e2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/span.cc
@@ -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: Sanjay Ghemawat <opensource@google.com>
+
+#include <config.h>
+#include "span.h"
+
+#include <string.h> // for NULL, memset
+
+#include "internal_logging.h" // for ASSERT
+#include "page_heap_allocator.h" // for PageHeapAllocator
+#include "static_vars.h" // for Static
+
+namespace tcmalloc {
+
+#ifdef SPAN_HISTORY
+void Event(Span* span, char op, int v = 0) {
+ span->history[span->nexthistory] = op;
+ span->value[span->nexthistory] = v;
+ span->nexthistory++;
+ if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0;
+}
+#endif
+
+Span* NewSpan(PageID p, Length len) {
+ Span* result = Static::span_allocator()->New();
+ memset(result, 0, sizeof(*result));
+ result->start = p;
+ result->length = len;
+#ifdef SPAN_HISTORY
+ result->nexthistory = 0;
+#endif
+ 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/chromium/third_party/tcmalloc/vendor/src/span.h b/chromium/third_party/tcmalloc/vendor/src/span.h
new file mode 100644
index 00000000000..08db6292f95
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/span.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: Sanjay Ghemawat <opensource@google.com>
+//
+// A Span is a contiguous run of pages.
+
+#ifndef TCMALLOC_SPAN_H_
+#define TCMALLOC_SPAN_H_
+
+#include <config.h>
+#include "common.h"
+
+namespace tcmalloc {
+
+// 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
+ void* objects; // Linked list of free objects
+ 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?
+
+#undef SPAN_HISTORY
+#ifdef SPAN_HISTORY
+ // For debugging, we can keep a log events per span
+ int nexthistory;
+ char history[64];
+ int value[64];
+#endif
+
+ // What freelist the span is on: IN_USE if on none, or normal or returned
+ enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
+};
+
+#ifdef SPAN_HISTORY
+void Event(Span* span, char op, int v = 0);
+#else
+#define Event(s,o,v) ((void) 0)
+#endif
+
+// 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/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.cc b/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.cc
new file mode 100644
index 00000000000..d258a4f8a23
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.cc
@@ -0,0 +1,159 @@
+// 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 <config.h>
+#include "stack_trace_table.h"
+#include <string.h> // 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 {
+
+bool StackTraceTable::Bucket::KeyEqual(uintptr_t h,
+ const StackTrace& t) const {
+ const bool eq = (this->hash == h && this->trace.depth == t.depth);
+ for (int i = 0; eq && i < t.depth; ++i) {
+ if (this->trace.stack[i] != t.stack[i]) {
+ return false;
+ }
+ }
+ return eq;
+}
+
+StackTraceTable::StackTraceTable()
+ : error_(false),
+ depth_total_(0),
+ bucket_total_(0),
+ table_(new Bucket*[kHashTableSize]()) {
+ memset(table_, 0, kHashTableSize * sizeof(Bucket*));
+}
+
+StackTraceTable::~StackTraceTable() {
+ delete[] table_;
+}
+
+void StackTraceTable::AddTrace(const StackTrace& t) {
+ if (error_) {
+ return;
+ }
+
+ // Hash function borrowed from base/heap-profile-table.cc
+ uintptr_t h = 0;
+ for (int i = 0; i < t.depth; ++i) {
+ h += reinterpret_cast<uintptr_t>(t.stack[i]);
+ h += h << 10;
+ h ^= h >> 6;
+ }
+ h += h << 3;
+ h ^= h >> 11;
+
+ const int idx = h % kHashTableSize;
+
+ Bucket* b = table_[idx];
+ while (b != NULL && !b->KeyEqual(h, t)) {
+ b = b->next;
+ }
+ if (b != NULL) {
+ b->count++;
+ b->trace.size += t.size; // keep cumulative size
+ } else {
+ depth_total_ += t.depth;
+ bucket_total_++;
+ b = Static::bucket_allocator()->New();
+ if (b == NULL) {
+ Log(kLog, __FILE__, __LINE__,
+ "tcmalloc: could not allocate bucket", sizeof(*b));
+ error_ = true;
+ } else {
+ b->hash = h;
+ b->trace = t;
+ b->count = 1;
+ b->next = table_[idx];
+ table_[idx] = b;
+ }
+ }
+}
+
+void** StackTraceTable::ReadStackTracesAndClear() {
+ if (error_) {
+ return NULL;
+ }
+
+ // Allocate output array
+ const int out_len = bucket_total_ * 3 + depth_total_ + 1;
+ void** out = new void*[out_len];
+ if (out == NULL) {
+ Log(kLog, __FILE__, __LINE__,
+ "tcmalloc: allocation failed for stack traces",
+ out_len * sizeof(*out));
+ return NULL;
+ }
+
+ // Fill output array
+ int idx = 0;
+ for (int i = 0; i < kHashTableSize; ++i) {
+ Bucket* b = table_[i];
+ while (b != NULL) {
+ out[idx++] = reinterpret_cast<void*>(static_cast<uintptr_t>(b->count));
+ out[idx++] = reinterpret_cast<void*>(b->trace.size); // cumulative size
+ out[idx++] = reinterpret_cast<void*>(b->trace.depth);
+ for (int d = 0; d < b->trace.depth; ++d) {
+ out[idx++] = b->trace.stack[d];
+ }
+ b = b->next;
+ }
+ }
+ out[idx++] = static_cast<uintptr_t>(0);
+ ASSERT(idx == out_len);
+
+ // Clear state
+ error_ = false;
+ depth_total_ = 0;
+ bucket_total_ = 0;
+ SpinLockHolder h(Static::pageheap_lock());
+ for (int i = 0; i < kHashTableSize; ++i) {
+ Bucket* b = table_[i];
+ while (b != NULL) {
+ Bucket* next = b->next;
+ Static::bucket_allocator()->Delete(b);
+ b = next;
+ }
+ table_[i] = NULL;
+ }
+
+ return out;
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.h b/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.h
new file mode 100644
index 00000000000..26d21c1c7eb
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stack_trace_table.h
@@ -0,0 +1,91 @@
+// 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 <config.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#include "common.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
+ struct Bucket {
+ // Key
+ uintptr_t hash;
+ StackTrace trace;
+
+ // Payload
+ int count;
+ Bucket* next;
+
+ bool KeyEqual(uintptr_t h, const StackTrace& t) const;
+ };
+
+ // For testing
+ int depth_total() const { return depth_total_; }
+ int bucket_total() const { return bucket_total_; }
+
+ private:
+ static const int kHashTableSize = 1 << 14; // => table_ is 128k
+
+ bool error_;
+ int depth_total_;
+ int bucket_total_;
+ Bucket** table_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_STACK_TRACE_TABLE_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/stacktrace.cc b/chromium/third_party/tcmalloc/vendor/src/stacktrace.cc
new file mode 100644
index 00000000000..d96b4d3fa69
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace.cc
@@ -0,0 +1,110 @@
+// 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 <config.h>
+#include <gperftools/stacktrace.h>
+#include "stacktrace_config.h"
+
+#if defined(STACKTRACE_INL_HEADER)
+
+#define IS_STACK_FRAMES 0
+#define IS_WITH_CONTEXT 0
+#define GET_STACK_TRACE_OR_FRAMES \
+ GetStackTrace(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 \
+ GetStackFrames(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 \
+ GetStackTraceWithContext(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 \
+ GetStackFramesWithContext(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
+
+#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"
+#else
+# error Cannot calculate stack trace: will need to write for your environment
+#endif
diff --git a/chromium/third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h
new file mode 100644
index 00000000000..5ee1bf9d01f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h
@@ -0,0 +1,145 @@
+// 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 <stdint.h> // for uintptr_t
+#include "base/basictypes.h" // for NULL
+#include <gperftools/stacktrace.h>
+
+// 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<bool STRICT_UNWINDING>
+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)
+int GET_STACK_TRACE_OR_FRAMES {
+#ifdef __GNUC__
+ void **sp = reinterpret_cast<void**>(__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();
+
+ 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<IS_STACK_FRAMES == 0>(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/chromium/third_party/tcmalloc/vendor/src/stacktrace_config.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_config.h
new file mode 100644
index 00000000000..72d108a8c24
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_config.h
@@ -0,0 +1,85 @@
+// 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: Paul Pluzhnikov
+//
+// Figure out which unwinder to use on a given platform.
+//
+// Defines STACKTRACE_INL_HEADER to the *-inl.h containing
+// actual unwinder implementation.
+//
+// Defines STACKTRACE_SKIP_CONTEXT_ROUTINES if a separate
+// GetStack{Trace,Frames}WithContext should not be provided.
+//
+// This header is "private" to stacktrace.cc and
+// stacktrace_with_context.cc.
+//
+// DO NOT include it into any other files.
+
+#ifndef BASE_STACKTRACE_CONFIG_H_
+#define BASE_STACKTRACE_CONFIG_H_
+
+// First, the i386 and x86_64 case.
+#if (defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_x86-inl.h"
+# define STACKTRACE_SKIP_CONTEXT_ROUTINES 1
+# elif defined(HAVE_LIBUNWIND_H) // a proxy for having libunwind installed
+# define STACKTRACE_INL_HEADER "stacktrace_libunwind-inl.h"
+# define STACKTRACE_USES_LIBUNWIND 1
+# elif defined(__linux)
+# error Cannnot calculate stack trace: need either libunwind or frame-pointers (see INSTALL file)
+# else
+# error Cannnot calculate stack trace: need libunwind (see INSTALL file)
+# endif
+
+// The PowerPC case
+#elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_powerpc-inl.h"
+# else
+# define STACKTRACE_INL_HEADER "stacktrace_generic-inl.h"
+# endif
+
+// The ARM case
+#elif defined(__arm__) && __GNUC__ >= 2
+# if !defined(NO_FRAME_POINTER)
+# define STACKTRACE_INL_HEADER "stacktrace_arm-inl.h"
+# else
+# error stacktrace without frame pointer is not supported on ARM
+# 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.
+#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__)
+# define STACKTRACE_INL_HEADER "stacktrace_win32-inl.h"
+
+#endif // all the cases
+#endif // BASE_STACKTRACE_CONFIG_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h
new file mode 100644
index 00000000000..5a526e228a1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h
@@ -0,0 +1,83 @@
+// 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 <execinfo.h>
+#include <string.h>
+#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)
+int GET_STACK_TRACE_OR_FRAMES {
+ static const int kStackLength = 64;
+ void * stack[kStackLength];
+ int size;
+
+ size = backtrace(stack, kStackLength);
+ skip_count++; // we want to skip the current 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/chromium/third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h
new file mode 100644
index 00000000000..82b0cfeb7ae
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h
@@ -0,0 +1,128 @@
+// 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 <assert.h>
+#include <string.h> // for memset()
+#include <libunwind.h>
+}
+#include "gperftools/stacktrace.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;
+
+#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)
+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;
+
+ unw_getcontext(&uc);
+ int ret = unw_init_local(&cursor, &uc);
+ assert(ret >= 0);
+ skip_count++; // Do not include current frame
+
+ 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/chromium/third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h
new file mode 100644
index 00000000000..acf2884e323
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h
@@ -0,0 +1,170 @@
+// 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 <stdint.h> // for uintptr_t
+#include <stdlib.h> // for NULL
+#include <gperftools/stacktrace.h>
+
+// 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<bool STRICT_UNWINDING>
+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 __APPLE__
+ __asm__ volatile ("mr %0,r1" : "=r" (sp));
+#else
+ __asm__ volatile ("mr %0,1" : "=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<!IS_STACK_FRAMES>(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(_CALL_AIX) || defined(_CALL_DARWIN)
+ result[n] = *(sp+2);
+#elif defined(_CALL_SYSV)
+ result[n] = *(sp+1);
+#elif defined(__APPLE__) || (defined(__linux) && 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);
+#else
+#error Need to specify the PPC ABI for your archiecture.
+#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/chromium/third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h
new file mode 100644
index 00000000000..2af472de5e0
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h
@@ -0,0 +1,91 @@
+// 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 <windows.h> // for GetProcAddress and GetModuleHandle
+#include <assert.h>
+
+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");
+
+PERFTOOLS_DLL_DECL int GetStackTrace(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 + 2, max_depth,
+ result, 0);
+}
+
+PERFTOOLS_DLL_DECL int GetStackFrames(void** /* pcs */,
+ int* /* sizes */,
+ int /* max_depth */,
+ int /* skip_count */) {
+ assert(0 == "Not yet implemented");
+ return 0;
+}
+
+#endif // BASE_STACKTRACE_WIN32_INL_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h b/chromium/third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h
new file mode 100644
index 00000000000..9d76342a144
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h
@@ -0,0 +1,351 @@
+// 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 <stdlib.h> // for NULL
+#include <assert.h>
+#if defined(HAVE_SYS_UCONTEXT_H)
+#include <sys/ucontext.h>
+#elif defined(HAVE_UCONTEXT_H)
+#include <ucontext.h> // for ucontext_t
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+// cygwin/signal.h has a buglet where it uses pthread_attr_t without
+// #including <pthread.h> itself. So we have to do it.
+# ifdef HAVE_PTHREAD
+# include <pthread.h>
+# endif
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h> // 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(),
+// preceeding "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<bool STRICT_UNWINDING, bool WITH_CONTEXT>
+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<const unsigned char *>(
+ rt_sigreturn_symbol_info.address);
+ kernel_vsyscall_address =
+ reinterpret_cast<const unsigned char *>(
+ 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<const ucontext_t *>(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<void **>(ucv->uc_mcontext.gregs[REG_EBP]);
+ const unsigned char *const reg_eip =
+ reinterpret_cast<unsigned char *>(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<void **>(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<void *>(
+ (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<void **>(
+ 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<false>() 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)
+
+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<void**>(__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
+
+ int n = 0;
+ while (sp && n < max_depth) {
+ if (*(sp+1) == reinterpret_cast<void *>(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<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(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/chromium/third_party/tcmalloc/vendor/src/static_vars.cc b/chromium/third_party/tcmalloc/vendor/src/static_vars.cc
new file mode 100644
index 00000000000..6fc852a82d1
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/static_vars.cc
@@ -0,0 +1,73 @@
+// 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 <opensource@google.com>
+
+#include "static_vars.h"
+#include <stddef.h> // for NULL
+#include <new> // for operator new
+#include "internal_logging.h" // for CHECK_CONDITION
+#include "common.h"
+#include "sampler.h" // for Sampler
+
+namespace tcmalloc {
+
+SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
+SizeMap Static::sizemap_;
+CentralFreeListPadded Static::central_cache_[kNumClasses];
+PageHeapAllocator<Span> Static::span_allocator_;
+PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
+Span Static::sampled_objects_;
+PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
+StackTrace* Static::growth_stacks_ = NULL;
+PageHeap* Static::pageheap_ = NULL;
+
+void Static::InitStaticVars() {
+ sizemap_.Init();
+ span_allocator_.Init();
+ span_allocator_.New(); // Reduce cache conflicts
+ span_allocator_.New(); // Reduce cache conflicts
+ stacktrace_allocator_.Init();
+ bucket_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 < kNumClasses; ++i) {
+ central_cache_[i].Init(i);
+ }
+ // It's important to have PageHeap allocated, not in static storage,
+ // so that HeapLeakChecker does not consider all the byte patterns stored
+ // in is caches as pointers that are sources of heap object liveness,
+ // which leads to it missing some memory leaks.
+ pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
+ DLL_Init(&sampled_objects_);
+ Sampler::InitStatics();
+}
+
+} // namespace tcmalloc
diff --git a/chromium/third_party/tcmalloc/vendor/src/static_vars.h b/chromium/third_party/tcmalloc/vendor/src/static_vars.h
new file mode 100644
index 00000000000..185a1d45ea8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/static_vars.h
@@ -0,0 +1,111 @@
+// 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 <opensource@google.com>
+//
+// Static variables shared by multiple classes.
+
+#ifndef TCMALLOC_STATIC_VARS_H_
+#define TCMALLOC_STATIC_VARS_H_
+
+#include <config.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();
+
+ // 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_; }
+
+ //////////////////////////////////////////////////////////////////////
+ // In addition to the explicit initialization comment, the variables below
+ // must be protected by pageheap_lock.
+
+ // Page-level allocator.
+ static PageHeap* pageheap() { return pageheap_; }
+
+ static PageHeapAllocator<Span>* span_allocator() { return &span_allocator_; }
+
+ static PageHeapAllocator<StackTrace>* 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_; }
+ static PageHeapAllocator<StackTraceTable::Bucket>* bucket_allocator() {
+ return &bucket_allocator_;
+ }
+
+ private:
+ 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.
+
+ static SizeMap sizemap_;
+ static CentralFreeListPadded central_cache_[kNumClasses];
+ static PageHeapAllocator<Span> span_allocator_;
+ static PageHeapAllocator<StackTrace> stacktrace_allocator_;
+ static Span sampled_objects_;
+ static PageHeapAllocator<StackTraceTable::Bucket> bucket_allocator_;
+
+ // 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].
+ static StackTrace* growth_stacks_;
+
+ static PageHeap* pageheap_;
+};
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_STATIC_VARS_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/symbolize.cc b/chromium/third_party/tcmalloc/vendor/src/symbolize.cc
new file mode 100644
index 00000000000..d90c4b889ff
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/symbolize.cc
@@ -0,0 +1,280 @@
+// 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 <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h> // for socketpair() -- needed by Symbolize
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h> // for wait() -- needed by Symbolize
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef __MACH__
+#include <mach-o/dyld.h> // for GetProgramInvocationName()
+#include <limits.h> // for PATH_MAX
+#endif
+#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+#include <io.h> // for get_osfhandle()
+#endif
+#include <string>
+#include "base/commandlineflags.h"
+#include "base/logging.h"
+#include "base/sysinfo.h"
+
+using std::string;
+using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
+
+
+DEFINE_string(symbolize_pprof,
+ EnvToString("PPROF_PATH", "pprof"),
+ "Path to pprof to call for reporting function names.");
+
+// heap_profile_table_pprof may be referenced 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 string* g_pprof_path = new string(FLAGS_symbolize_pprof);
+
+// 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 char* GetProgramInvocationName() {
+#if defined(HAVE_PROGRAM_INVOCATION_NAME)
+ extern char* program_invocation_name; // gcc provides this
+ 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;
+#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(g_pprof_path->c_str(), 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(g_pprof_path->c_str(), g_pprof_path->c_str(),
+ "--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<uintptr_t>(iter->first));
+ }
+ write(child_in[1], pprof_buffer, strlen(pprof_buffer));
+ close(child_in[1]); // that's all we need to write
+
+ 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/chromium/third_party/tcmalloc/vendor/src/symbolize.h b/chromium/third_party/tcmalloc/vendor/src/symbolize.h
new file mode 100644
index 00000000000..12c976ba60c
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/symbolize.h
@@ -0,0 +1,83 @@
+// 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 <stdint.h> // for uintptr_t
+#endif
+#include <stddef.h> // for NULL
+#include <map>
+
+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<const void*, const char*> 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/chromium/third_party/tcmalloc/vendor/src/system-alloc.cc b/chromium/third_party/tcmalloc/vendor/src/system-alloc.cc
new file mode 100644
index 00000000000..abfe47213ea
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/system-alloc.cc
@@ -0,0 +1,530 @@
+// 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 <config.h>
+#include <errno.h> // for EAGAIN, errno
+#include <fcntl.h> // for open, O_RDWR
+#include <stddef.h> // for size_t, NULL, ptrdiff_t
+#if defined HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t, intptr_t
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MMAP
+#include <sys/mman.h> // for munmap, mmap, MADV_DONTNEED, etc
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for sbrk, getpagesize, off_t
+#endif
+#include <new> // for operator new
+#include <gperftools/malloc_extension.h>
+#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
+
+// 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 <sys/types.h> // 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;
+
+// Anonymous namespace to avoid name conflicts on "CheckAddressBits".
+namespace {
+
+// Check that no bit is set at position ADDRESS_BITS or higher.
+template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) {
+ return (ptr >> ADDRESS_BITS) == 0;
+}
+
+// Specialize for the bit width of a pointer to avoid undefined shift.
+template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) {
+ return true;
+}
+
+} // Anonymous namespace to avoid name conflicts on "CheckAddressBits".
+
+COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*),
+ address_bits_larger_than_pointer_size);
+
+// Structure for discovering alignment
+union MemoryAligner {
+ void* p;
+ double d;
+ size_t s;
+} CACHELINE_ALIGNED;
+
+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* sys_alloc = NULL;
+
+// 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.");
+
+// static allocators
+class SbrkSysAllocator : public SysAllocator {
+public:
+ SbrkSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t *actual_size, size_t alignment);
+};
+static char sbrk_space[sizeof(SbrkSysAllocator)];
+
+class MmapSysAllocator : public SysAllocator {
+public:
+ MmapSysAllocator() : SysAllocator() {
+ }
+ void* Alloc(size_t size, size_t *actual_size, size_t alignment);
+};
+static char mmap_space[sizeof(MmapSysAllocator)];
+
+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 char default_space[sizeof(DefaultSysAllocator)];
+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) {
+#ifndef HAVE_SBRK
+ failed_ = true;
+ 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<ptrdiff_t>(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<intptr_t>(sbrk(0)) + size < size) {
+ return NULL;
+ }
+
+ void* result = sbrk(size);
+ if (result == reinterpret_cast<void*>(-1)) {
+ return NULL;
+ }
+
+ // Is it aligned?
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(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<uintptr_t>(r2) == (ptr + size)) {
+ // Contiguous with previous result
+ return reinterpret_cast<void*>(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<void*>(-1)) {
+ return NULL;
+ }
+ ptr = reinterpret_cast<uintptr_t>(result);
+ if ((ptr & (alignment-1)) != 0) {
+ ptr += alignment - (ptr & (alignment-1));
+ }
+ return reinterpret_cast<void*>(ptr);
+#endif // HAVE_SBRK
+}
+
+void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
+ size_t alignment) {
+#ifndef HAVE_MMAP
+ failed_ = true;
+ 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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void* result = mmap(NULL, size + extra,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ -1, 0);
+ if (result == reinterpret_cast<void*>(MAP_FAILED)) {
+ return NULL;
+ }
+
+ // Adjust the return memory so it is aligned
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+
+ // Return the unused memory to the system
+ if (adjust > 0) {
+ munmap(reinterpret_cast<void*>(ptr), adjust);
+ }
+ if (adjust < extra) {
+ munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
+ }
+
+ ptr += adjust;
+ return reinterpret_cast<void*>(ptr);
+#endif // HAVE_MMAP
+}
+
+void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
+ size_t alignment) {
+#ifndef HAVE_MMAP
+ failed_ = true;
+ 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<<NBITS).
+ // and extra <= alignment
+ // therefore size + extra < (1<<NBITS)
+ void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
+ MAP_SHARED, physmem_fd, physmem_base);
+ if (result == reinterpret_cast<void*>(MAP_FAILED)) {
+ return NULL;
+ }
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+
+ // Adjust the return memory so it is aligned
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+
+ // Return the unused virtual memory to the system
+ if (adjust > 0) {
+ munmap(reinterpret_cast<void*>(ptr), adjust);
+ }
+ if (adjust < extra) {
+ munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
+ }
+
+ ptr += adjust;
+ physmem_base += adjust + size;
+
+ return reinterpret_cast<void*>(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;
+}
+
+static bool system_alloc_inited = false;
+void InitSystemAllocators(void) {
+ MmapSysAllocator *mmap = new (mmap_space) MmapSysAllocator();
+ SbrkSysAllocator *sbrk = new (sbrk_space) 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) 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);
+ }
+ sys_alloc = 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);
+
+ void* result = sys_alloc->Alloc(size, actual_size, alignment);
+ if (result != NULL) {
+ if (actual_size) {
+ CheckAddressBits<kAddressBits>(
+ reinterpret_cast<uintptr_t>(result) + *actual_size - 1);
+ } else {
+ CheckAddressBits<kAddressBits>(
+ reinterpret_cast<uintptr_t>(result) + size - 1);
+ }
+ }
+ return result;
+}
+
+void 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;
+ }
+ if (pagesize == 0) pagesize = getpagesize();
+ const size_t pagemask = pagesize - 1;
+
+ size_t new_start = reinterpret_cast<size_t>(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<size_t>(start));
+ ASSERT(new_end <= end);
+
+ if (new_end > new_start) {
+ // Note -- ignoring most return codes, because if this fails it
+ // doesn't matter...
+ while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start,
+ MADV_FREE) == -1 &&
+ errno == EAGAIN) {
+ // NOP
+ }
+ }
+#endif
+}
diff --git a/chromium/third_party/tcmalloc/vendor/src/system-alloc.h b/chromium/third_party/tcmalloc/vendor/src/system-alloc.h
new file mode 100644
index 00000000000..814b5564dc7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/system-alloc.h
@@ -0,0 +1,77 @@
+// 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 <config.h>
+#include <stddef.h> // 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 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.)
+extern void TCMalloc_SystemRelease(void* start, size_t length);
+
+// The current system allocator.
+extern PERFTOOLS_DLL_DECL SysAllocator* sys_alloc;
+
+#endif /* TCMALLOC_SYSTEM_ALLOC_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/tcmalloc.cc b/chromium/third_party/tcmalloc/vendor/src/tcmalloc.cc
new file mode 100644
index 00000000000..0a9cb9f68d2
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/tcmalloc.cc
@@ -0,0 +1,1673 @@
+// 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 <opensource@google.com>
+//
+// 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 doc/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"
+#include <gperftools/tcmalloc.h>
+
+#include <errno.h> // for ENOMEM, EINVAL, errno
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // for __THROW
+#endif
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#include <sys/types.h>
+#endif
+#include <stddef.h> // for size_t, NULL
+#include <stdlib.h> // for getenv
+#include <string.h> // for strcmp, memset, strlen, etc
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for getpagesize, write, etc
+#endif
+#include <algorithm> // for max, min
+#include <limits> // for numeric_limits
+#include <new> // for nothrow_t (ptr only), etc
+#include <vector> // for vector
+
+#include <gperftools/malloc_extension.h>
+#include <gperftools/malloc_hook.h> // for MallocHook
+#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
+
+// 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 <malloc.h>
+# elif defined(HAVE_SYS_MALLOC_H)
+# include <sys/malloc.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# endif
+#endif
+
+#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 STL_NAMESPACE::max;
+using STL_NAMESPACE::numeric_limits;
+using STL_NAMESPACE::vector;
+
+#include "libc_override.h"
+
+// __THROW is defined in glibc (via <sys/cdefs.h>). 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 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_int64(tcmalloc_sample_parameter);
+DECLARE_double(tcmalloc_release_rate);
+
+// 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<int64>(1) << 62;
+#else
+const int64 kDefaultLargeAllocReportThreshold = static_cast<int64>(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) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_free(void* ptr) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_realloc(void* ptr, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_calloc(size_t nmemb, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_cfree(void* ptr) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ void* tc_memalign(size_t __alignment, size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ int tc_posix_memalign(void** ptr, size_t align, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_valloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_pvalloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ void tc_malloc_stats(void) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ int tc_mallopt(int cmd, int value) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+#ifdef HAVE_STRUCT_MALLINFO
+ struct mallinfo tc_mallinfo(void) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+#endif
+
+ void* tc_new(size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_delete(void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_newarray(size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_deletearray(void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ // And the nothrow variants of these:
+ void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW
+ 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&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void tc_deletearray_nothrow(void* ptr, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+ // 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) __THROW
+ 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 {
+void InvalidFree(void* ptr) {
+ 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 get per-size-class counts if class_count != NULL
+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 < kNumClasses; ++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<uint64_t>(
+ Static::sizemap()->ByteSizeForClass(cl));
+ r->central_bytes += (size * length) + cache_overhead;
+ r->transfer_bytes += (size * tc_length);
+ if (class_count) 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[kNumClasses];
+ 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("Size class breakdown\n");
+ out->printf("------------------------------------------------\n");
+ uint64_t cumulative = 0;
+ for (int cl = 0; cl < kNumClasses; ++cl) {
+ if (class_count[cl] > 0) {
+ uint64_t class_bytes =
+ class_count[cl] * Static::sizemap()->ByteSizeForClass(cl);
+ cumulative += class_bytes;
+ out->printf("class %3d [ %8" PRIuS " bytes ] : "
+ "%8" PRIu64 " objs; %5.1f MiB; %5.1f cum MiB\n",
+ cl, Static::sizemap()->ByteSizeForClass(cl),
+ class_count[cl],
+ class_bytes / MiB,
+ cumulative / 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 = 0; s < kMaxPages; s++) {
+ const int n_length = small.normal_length[s];
+ const int r_length = small.returned_length[s];
+ 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(">255 large * %6u spans ~ %6.1f MiB; %6.1f MiB cum"
+ "; unmapped: %6.1f MiB; %6.1f MiB cum\n",
+ static_cast<unsigned int>(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<StackTrace*>(
+ 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<StackTrace*>(
+ 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<void*>(static_cast<uintptr_t>(1));
+ result[used_slots+1] = reinterpret_cast<void*>(t->size);
+ result[used_slots+2] = reinterpret_cast<void*>(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<void*>(static_cast<uintptr_t>(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<StackTrace*>(s->objects));
+ }
+ }
+ *sample_period = ThreadCache::GetCache()->GetSamplePeriod();
+ return table.ReadStackTracesAndClear(); // grabs and releases pageheap_lock
+ }
+
+ virtual void** ReadHeapGrowthStackTraces() {
+ return DumpHeapGrowthStackTraces();
+ }
+
+ 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, "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.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;
+ }
+
+ 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;
+ }
+
+ return false;
+ }
+
+ virtual void MarkThreadIdle() {
+ ThreadCache::BecomeIdle();
+ }
+
+ virtual void MarkThreadBusy(); // Implemented below
+
+ virtual SysAllocator* GetSystemAllocator() {
+ SpinLockHolder h(Static::pageheap_lock());
+ return sys_alloc;
+ }
+
+ virtual void SetSystemAllocator(SysAllocator* alloc) {
+ SpinLockHolder h(Static::pageheap_lock());
+ 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<Length>(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) {
+ if (size <= kMaxSize) {
+ const size_t cl = Static::sizemap()->SizeClass(size);
+ const size_t alloc_size = Static::sizemap()->ByteSizeForClass(cl);
+ return alloc_size;
+ } else {
+ return tcmalloc::pages(size) << kPageShift;
+ }
+ }
+
+ // 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<uintptr_t>(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;
+ }
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+ if (cl != 0) {
+ return kOwned;
+ }
+ const Span *span = Static::pageheap()->GetDescriptor(p);
+ return span ? kOwned : kNotOwned;
+ }
+
+ virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* 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 < kNumClasses; ++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[kNumClasses];
+ 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 < kNumClasses; ++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);
+ }
+
+ // 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<size_t>::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];
+ v->push_back(i);
+
+ i.type = kPageHeapUnmappedType;
+ i.total_bytes_free = (s << kPageShift) * small.returned_length[s];
+ v->push_back(i);
+ }
+ }
+};
+
+// 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) {
+#ifdef HAVE_TLS // this is true if the cc/ld/libc combo support TLS
+ // Check whether the kernel also supports TLS (needs to happen at runtime)
+ tcmalloc::CheckIfKernelSupportsTLS();
+#endif
+ 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 = 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<uintptr_t>(ptr) >> kPageShift;
+ size_t cached_value = Static::pageheap()->GetSizeClassIfCached(p);
+ return cached_value == 0 ||
+ cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass;
+}
+
+static inline void* CheckedMallocResult(void *result) {
+ ASSERT(result == NULL || CheckCachedSizeClass(result));
+ return result;
+}
+
+static inline void* SpanToMallocResult(Span *span) {
+ Static::pageheap()->CacheSizeClass(span->start, 0);
+ return
+ CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
+}
+
+static void* DoSampledAllocation(size_t size) {
+ // 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 (span == NULL) {
+ return NULL;
+ }
+
+ // Allocate stack trace
+ StackTrace *stack = Static::stacktrace_allocator()->New();
+ if (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);
+}
+
+namespace {
+
+// Copy of FLAGS_tcmalloc_large_alloc_report_threshold with
+// automatic increases factored in.
+static int64_t large_alloc_threshold =
+ (kPageSize > FLAGS_tcmalloc_large_alloc_report_threshold
+ ? kPageSize : FLAGS_tcmalloc_large_alloc_report_threshold);
+
+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<uint64>(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));
+}
+
+inline void* cpp_alloc(size_t size, bool nothrow);
+inline void* do_malloc(size_t size);
+
+// TODO(willchan): Investigate whether or not lining this much is harmful to
+// performance.
+// This is equivalent to do_malloc() except when tc_new_mode is set to true.
+// Otherwise, it will run the std::new_handler if set.
+inline void* do_malloc_or_cpp_alloc(size_t size) {
+ return tc_new_mode ? cpp_alloc(size, true) : do_malloc(size);
+}
+
+void* cpp_memalign(size_t align, size_t size);
+void* do_memalign(size_t align, size_t size);
+
+inline void* do_memalign_or_cpp_memalign(size_t align, size_t size) {
+ return tc_new_mode ? cpp_memalign(align, size) : do_memalign(align, size);
+}
+
+// Must be called with the page lock held.
+inline bool should_report_large(Length num_pages) {
+ 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;
+ }
+ return false;
+}
+
+// Helper for do_malloc().
+inline void* do_malloc_pages(ThreadCache* heap, size_t size) {
+ void* result;
+ bool report_large;
+
+ Length num_pages = tcmalloc::pages(size);
+ size = num_pages << kPageShift;
+
+ if ((FLAGS_tcmalloc_sample_parameter > 0) && 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 = (span == NULL ? NULL : SpanToMallocResult(span));
+ report_large = should_report_large(num_pages);
+ }
+
+ if (report_large) {
+ ReportLargeAlloc(num_pages, result);
+ }
+ return result;
+}
+
+inline void* do_malloc(size_t size) {
+ void* ret = NULL;
+
+ // The following call forces module initialization
+ ThreadCache* heap = ThreadCache::GetCache();
+ if (size <= kMaxSize) {
+ size_t cl = Static::sizemap()->SizeClass(size);
+ size = Static::sizemap()->class_to_size(cl);
+
+ if ((FLAGS_tcmalloc_sample_parameter > 0) && heap->SampleAllocation(size)) {
+ ret = DoSampledAllocation(size);
+ } else {
+ // The common case, and also the simplest. This just pops the
+ // size-appropriate freelist, after replenishing it if it's empty.
+ ret = CheckedMallocResult(heap->Allocate(size, cl));
+ }
+ } else {
+ ret = do_malloc_pages(heap, size);
+ }
+ if (ret == NULL) errno = ENOMEM;
+ return ret;
+}
+
+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, size);
+ }
+ return result;
+}
+
+static inline ThreadCache* GetCacheIfPresent() {
+ void* const p = ThreadCache::GetCacheIfPresent();
+ return reinterpret_cast<ThreadCache*>(p);
+}
+
+// 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.
+inline void do_free_with_callback(void* ptr, void (*invalid_free_fn)(void*)) {
+ if (ptr == NULL) return;
+ if (Static::pageheap() == NULL) {
+ // We called free() before malloc(). This can occur if the
+ // (system) malloc() is called before tcmalloc is loaded, and then
+ // free() is called after tcmalloc is loaded (and tc_free has
+ // replaced free), but before the global constructor has run that
+ // sets up the tcmalloc data structures.
+ (*invalid_free_fn)(ptr); // Decide how to handle the bad free request
+ return;
+ }
+ const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
+ Span* span = NULL;
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+
+ if (cl == 0) {
+ span = Static::pageheap()->GetDescriptor(p);
+ if (!span) {
+ // span can be NULL because the pointer passed in is 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.
+ (*invalid_free_fn)(ptr); // Decide how to handle the bad free request
+ return;
+ }
+ cl = span->sizeclass;
+ Static::pageheap()->CacheSizeClass(p, cl);
+ }
+ if (cl != 0) {
+ ASSERT(!Static::pageheap()->GetDescriptor(p)->sample);
+ ThreadCache* heap = GetCacheIfPresent();
+ if (heap != NULL) {
+ heap->Deallocate(ptr, cl);
+ } else {
+ // Delete directly into central cache
+ tcmalloc::SLL_SetNext(ptr, NULL);
+ Static::central_cache()[cl].InsertRange(ptr, ptr, 1);
+ }
+ } else {
+ SpinLockHolder h(Static::pageheap_lock());
+ ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
+ ASSERT(span != NULL && span->start == p);
+ if (span->sample) {
+ StackTrace* st = reinterpret_cast<StackTrace*>(span->objects);
+ tcmalloc::DLL_Remove(span);
+ Static::stacktrace_allocator()->Delete(st);
+ span->objects = NULL;
+ }
+ Static::pageheap()->Delete(span);
+ }
+}
+
+// The default "do_free" that uses the default callback.
+inline void do_free(void* ptr) {
+ return do_free_with_callback(ptr, &InvalidFree);
+}
+
+// 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<uintptr_t>(ptr) >> kPageShift;
+ size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
+ if (cl != 0) {
+ return Static::sizemap()->ByteSizeForClass(cl);
+ } else {
+ const Span *span = Static::pageheap()->GetDescriptor(p);
+ if (span == NULL) { // means we do not own this memory
+ return (*invalid_getsize_fn)(ptr);
+ } else if (span->sizeclass != 0) {
+ Static::pageheap()->CacheSizeClass(p, span->sizeclass);
+ return Static::sizemap()->ByteSizeForClass(span->sizeclass);
+ } else {
+ 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.
+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 int lower_bound_to_grow = old_size + old_size / 4;
+ const int upper_bound_to_shrink = old_size / 2;
+ 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 (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);
+ 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;
+ }
+}
+
+inline void* do_realloc(void* old_ptr, size_t new_size) {
+ return do_realloc_with_callback(old_ptr, new_size,
+ &InvalidFree, &InvalidGetSizeForRealloc);
+}
+
+// For use by exported routines below that want specific alignments
+//
+// Note: this code can be slow for alignments > 16, and can
+// significantly fragment memory. The expectation is that
+// memalign/posix_memalign/valloc/pvalloc will not be invoked very
+// often. This requirement simplifies our implementation and allows
+// us to tune for expected allocation patterns.
+void* do_memalign(size_t align, size_t size) {
+ ASSERT((align & (align - 1)) == 0);
+ ASSERT(align > 0);
+ if (size + align < size) return NULL; // Overflow
+
+ // Fall back to malloc if we would already align this memory access properly.
+ if (align <= AlignmentForSize(size)) {
+ void* p = do_malloc(size);
+ ASSERT((reinterpret_cast<uintptr_t>(p) % align) == 0);
+ return p;
+ }
+
+ if (Static::pageheap() == NULL) ThreadCache::InitModule();
+
+ // Allocate at least one byte to avoid boundary conditions below
+ if (size == 0) size = 1;
+
+ if (size <= kMaxSize && align < kPageSize) {
+ // Search through acceptable size classes looking for one with
+ // enough alignment. This depends on the fact that
+ // InitSizeClasses() currently produces several size classes that
+ // are aligned at powers of two. We will waste time and space if
+ // we miss in the size class array, but that is deemed acceptable
+ // since memalign() should be used rarely.
+ int cl = Static::sizemap()->SizeClass(size);
+ while (cl < kNumClasses &&
+ ((Static::sizemap()->class_to_size(cl) & (align - 1)) != 0)) {
+ cl++;
+ }
+ if (cl < kNumClasses) {
+ ThreadCache* heap = ThreadCache::GetCache();
+ size = Static::sizemap()->class_to_size(cl);
+ return CheckedMallocResult(heap->Allocate(size, cl));
+ }
+ }
+
+ // We will allocate directly from the page heap
+ SpinLockHolder h(Static::pageheap_lock());
+
+ if (align <= kPageSize) {
+ // Any page-level allocation will be fine
+ // TODO: We could put the rest of this page in the appropriate
+ // TODO: cache but it does not seem worth it.
+ Span* span = Static::pageheap()->New(tcmalloc::pages(size));
+ return span == NULL ? NULL : SpanToMallocResult(span);
+ }
+
+ // Allocate extra pages and carve off an aligned portion
+ const Length alloc = tcmalloc::pages(size + align);
+ Span* span = Static::pageheap()->New(alloc);
+ if (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<int>(stats.pageheap.system_bytes);
+ info.fsmblks = static_cast<int>(stats.thread_bytes
+ + stats.central_bytes
+ + stats.transfer_bytes);
+ info.fordblks = static_cast<int>(stats.pageheap.free_bytes +
+ stats.pageheap.unmapped_bytes);
+ info.uordblks = static_cast<int>(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
+
+static SpinLock set_new_handler_lock(SpinLock::LINKER_INITIALIZED);
+
+inline void* cpp_alloc(size_t size, bool nothrow) {
+ for (;;) {
+ void* p = do_malloc(size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ 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 p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+void* cpp_memalign(size_t align, size_t size) {
+ for (;;) {
+ void* p = do_memalign(align, size);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // 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) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh)
+ return 0;
+
+ // 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&) {
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+} // end unnamed namespace
+
+// As promised, the definition of this function, declared above.
+size_t TCMallocImplementation::GetAllocatedSize(const void* ptr) {
+ 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) __THROW {
+ 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) __THROW {
+ int old_mode = tc_new_mode;
+ tc_new_mode = flag;
+ return old_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.
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
+ void* result = do_malloc_or_cpp_alloc(size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ do_free(ptr);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n,
+ size_t elem_size) __THROW {
+ 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) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ do_free(ptr);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_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(old_ptr);
+ return NULL;
+ }
+ return do_realloc(old_ptr, new_size);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
+ void* p = cpp_alloc(size, false);
+ // We keep this next instruction out of cpp_alloc for a reason: when
+ // it's in, and new just calls cpp_alloc, the optimizer may fold the
+ // new call into cpp_alloc, which messes up our whole section-based
+ // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
+ // isn't the last thing this fn calls, and prevents the folding.
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+// 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&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
+ void* p = cpp_alloc(size, false);
+ // We keep this next instruction out of cpp_alloc for a reason: when
+ // it's in, and new just calls cpp_alloc, the optimizer may fold the
+ // new call into cpp_alloc, which messes up our whole section-based
+ // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc
+ // isn't the last thing this fn calls, and prevents the folding.
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
+ __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free(p);
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align,
+ size_t size) __THROW {
+ void* result = do_memalign_or_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(
+ void** result_ptr, size_t align, size_t size) __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
+
+ void* result = do_memalign_or_cpp_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ if (result == NULL) {
+ return ENOMEM;
+ } else {
+ *result_ptr = result;
+ return 0;
+ }
+}
+
+static size_t pagesize = 0;
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
+ // Allocate page-aligned object of length >= size bytes
+ if (pagesize == 0) pagesize = getpagesize();
+ void* result = do_memalign_or_cpp_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
+ // 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);
+ void* result = do_memalign_or_cpp_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
+ do_malloc_stats();
+}
+
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
+ return do_mallopt(cmd, value);
+}
+
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
+ return do_mallinfo();
+}
+#endif
+
+extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
+ return MallocExtension::instance()->GetAllocatedSize(ptr);
+}
+
+#endif // TCMALLOC_USING_DEBUGALLOCATION
diff --git a/chromium/third_party/tcmalloc/vendor/src/tcmalloc.h b/chromium/third_party/tcmalloc/vendor/src/tcmalloc.h
new file mode 100644
index 00000000000..3b0fe7cadf8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/tcmalloc.h
@@ -0,0 +1,69 @@
+// 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 <opensource@google.com>
+//
+// 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 <config.h>
+
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 600 // for posix_memalign
+#endif
+#include <stdlib.h> // for posix_memalign
+// FreeBSD has malloc.h, but complains if you use it
+#if defined(HAVE_MALLOC_H) && !defined(__FreeBSD__)
+#include <malloc.h> // 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_CFREE_SYMBOL
+extern "C" void cfree(void* ptr) __THROW;
+#endif
+#if !HAVE_POSIX_MEMALIGN_SYMBOL
+extern "C" int posix_memalign(void** ptr, size_t align, size_t size) __THROW;
+#endif
+#if !HAVE_MEMALIGN_SYMBOL
+extern "C" void* memalign(size_t __alignment, size_t __size) __THROW;
+#endif
+#if !HAVE_VALLOC_SYMBOL
+extern "C" void* valloc(size_t __size) __THROW;
+#endif
+#if !HAVE_PVALLOC_SYMBOL
+extern "C" void* pvalloc(size_t __size) __THROW;
+#endif
diff --git a/chromium/third_party/tcmalloc/vendor/src/tcmalloc_guard.h b/chromium/third_party/tcmalloc/vendor/src/tcmalloc_guard.h
new file mode 100644
index 00000000000..7874dadaea9
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/tcmalloc_guard.h
@@ -0,0 +1,48 @@
+// 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/chromium/third_party/tcmalloc/vendor/src/third_party/valgrind.h b/chromium/third_party/tcmalloc/vendor/src/third_party/valgrind.h
new file mode 100644
index 00000000000..577c59ab0cd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/third_party/valgrind.h
@@ -0,0 +1,3924 @@
+/* -*- c -*-
+ ----------------------------------------------------------------
+
+ Notice that the following BSD-style license applies to this one
+ file (valgrind.h) only. The rest of Valgrind is licensed under the
+ terms of the GNU General Public License, version 2, unless
+ otherwise indicated. See the COPYING file in the source
+ distribution for details.
+
+ ----------------------------------------------------------------
+
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2008 Julian Seward. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+ ----------------------------------------------------------------
+
+ Notice that the above BSD-style license applies to this one file
+ (valgrind.h) only. The entire rest of Valgrind is licensed under
+ the terms of the GNU General Public License, version 2. See the
+ COPYING file in the source distribution for details.
+
+ ----------------------------------------------------------------
+*/
+
+
+/* This file is for inclusion into client (your!) code.
+
+ You can use these macros to manipulate and query Valgrind's
+ execution inside your own programs.
+
+ The resulting executables will still run without Valgrind, just a
+ little bit more slowly than they otherwise would, but otherwise
+ unchanged. When not running on valgrind, each client request
+ consumes very few (eg. 7) instructions, so the resulting performance
+ loss is negligible unless you plan to execute client requests
+ millions of times per second. Nevertheless, if that is still a
+ problem, you can compile with the NVALGRIND symbol defined (gcc
+ -DNVALGRIND) so that client requests are not even compiled in. */
+
+#ifndef __VALGRIND_H
+#define __VALGRIND_H
+
+#include <stdarg.h>
+
+/* Nb: this file might be included in a file compiled with -ansi. So
+ we can't use C++ style "//" comments nor the "asm" keyword (instead
+ use "__asm__"). */
+
+/* Derive some tags indicating what the target platform is. Note
+ that in this file we're using the compiler's CPP symbols for
+ identifying architectures, which are different to the ones we use
+ within the rest of Valgrind. Note, __powerpc__ is active for both
+ 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
+ latter (on Linux, that is). */
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
+
+#if !defined(_AIX) && defined(__i386__)
+# define PLAT_x86_linux 1
+#elif !defined(_AIX) && defined(__x86_64__)
+# define PLAT_amd64_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
+# define PLAT_ppc32_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
+# define PLAT_ppc64_linux 1
+#elif defined(_AIX) && defined(__64BIT__)
+# define PLAT_ppc64_aix5 1
+#elif defined(_AIX) && !defined(__64BIT__)
+# define PLAT_ppc32_aix5 1
+#endif
+
+
+/* If we're not compiling for our target platform, don't generate
+ any inline asms. */
+#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
+ && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
+ && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
+# if !defined(NVALGRIND)
+# define NVALGRIND 1
+# endif
+#endif
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
+/* in here of use to end-users -- skip to the next section. */
+/* ------------------------------------------------------------------ */
+
+#if defined(NVALGRIND)
+
+/* Define NVALGRIND to completely remove the Valgrind magic sequence
+ from the compiled code (analogous to NDEBUG's effects on
+ assert()) */
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { \
+ (_zzq_rlval) = (_zzq_default); \
+ }
+
+#else /* ! NVALGRIND */
+
+/* The following defines the magic code sequences which the JITter
+ spots and handles magically. Don't look too closely at them as
+ they will rot your brain.
+
+ The assembly code sequences for all architectures is in this one
+ file. This is because this file must be stand-alone, and we don't
+ want to have multiple files.
+
+ For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
+ value gets put in the return slot, so that everything works when
+ this is executed not under Valgrind. Args are passed in a memory
+ block, and so there's no intrinsic limit to the number that could
+ be passed, but it's currently five.
+
+ The macro args are:
+ _zzq_rlval result lvalue
+ _zzq_default default value (result returned when running on real CPU)
+ _zzq_request request code
+ _zzq_arg1..5 request params
+
+ The other two macros are used to support function wrapping, and are
+ a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
+ guest's NRADDR pseudo-register and whatever other information is
+ needed to safely run the call original from the wrapper: on
+ ppc64-linux, the R2 value at the divert point is also needed. This
+ information is abstracted into a user-visible type, OrigFn.
+
+ VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
+ guest, but guarantees that the branch instruction will not be
+ redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
+ branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
+ complete inline asm, since it needs to be combined with more magic
+ inline asm stuff to be useful.
+*/
+
+/* ------------------------- x86-linux ------------------------- */
+
+#if defined(PLAT_x86_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "roll $3, %%edi ; roll $13, %%edi\n\t" \
+ "roll $29, %%edi ; roll $19, %%edi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EDX = client_request ( %EAX ) */ \
+ "xchgl %%ebx,%%ebx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EAX = guest_NRADDR */ \
+ "xchgl %%ecx,%%ecx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_EAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%EAX */ \
+ "xchgl %%edx,%%edx\n\t"
+#endif /* PLAT_x86_linux */
+
+/* ------------------------ amd64-linux ------------------------ */
+
+#if defined(PLAT_amd64_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
+ "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned long long int _zzq_args[6]; \
+ volatile unsigned long long int _zzq_result; \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RDX = client_request ( %RAX ) */ \
+ "xchgq %%rbx,%%rbx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RAX = guest_NRADDR */ \
+ "xchgq %%rcx,%%rcx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_RAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%RAX */ \
+ "xchgq %%rdx,%%rdx\n\t"
+#endif /* PLAT_amd64_linux */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[6]; \
+ unsigned int _zzq_result; \
+ unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \
+ "mr 4,%2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" /*result*/ \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_default), "b" (_zzq_ptr) \
+ : "cc", "memory", "r3", "r4"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "cc", "memory", "r3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[6]; \
+ register unsigned long long int _zzq_result __asm__("r3"); \
+ register unsigned long long int* _zzq_ptr __asm__("r4"); \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1" \
+ : "=r" (_zzq_result) \
+ : "0" (_zzq_default), "r" (_zzq_ptr) \
+ : "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr __asm__("r3"); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ unsigned int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[7]; \
+ register unsigned int _zzq_result; \
+ register unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "lwz 3, 24(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[7]; \
+ register unsigned long long int _zzq_result; \
+ register unsigned long long int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int long long)(_zzq_request); \
+ _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int long long)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "ld 3, 48(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_aix5 */
+
+/* Insert assembly code for other platforms here... */
+
+#endif /* NVALGRIND */
+
+
+/* ------------------------------------------------------------------ */
+/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
+/* ugly. It's the least-worst tradeoff I can think of. */
+/* ------------------------------------------------------------------ */
+
+/* This section defines magic (a.k.a appalling-hack) macros for doing
+ guaranteed-no-redirection macros, so as to get from function
+ wrappers to the functions they are wrapping. The whole point is to
+ construct standard call sequences, but to do the call itself with a
+ special no-redirect call pseudo-instruction that the JIT
+ understands and handles specially. This section is long and
+ repetitious, and I can't see a way to make it shorter.
+
+ The naming scheme is as follows:
+
+ CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
+
+ 'W' stands for "word" and 'v' for "void". Hence there are
+ different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
+ and for each, the possibility of returning a word-typed result, or
+ no result.
+*/
+
+/* Use these to write the name of your wrapper. NOTE: duplicates
+ VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
+
+#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
+ _vgwZU_##soname##_##fnname
+
+#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
+ _vgwZZ_##soname##_##fnname
+
+/* Use this macro from within a wrapper function to collect the
+ context (address and possibly other info) of the original function.
+ Once you have that you can then use it in one of the CALL_FN_
+ macros. The type of the argument _lval is OrigFn. */
+#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
+
+/* Derivatives of the main macros below, for calling functions
+ returning void. */
+
+#define CALL_FN_v_v(fnptr) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_v(_junk,fnptr); } while (0)
+
+#define CALL_FN_v_W(fnptr, arg1) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
+
+#define CALL_FN_v_WW(fnptr, arg1,arg2) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
+
+#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
+
+/* ------------------------- x86-linux ------------------------- */
+
+#if defined(PLAT_x86_linux)
+
+/* These regs are trashed by the hidden call. No need to mention eax
+ as gcc can already see that, plus causes gcc to bomb. */
+#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
+
+/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $4, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $8, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $12, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $16, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $20, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $24, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $28, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $32, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $36, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $40, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $44, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "pushl 48(%%eax)\n\t" \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $48, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_x86_linux */
+
+/* ------------------------ amd64-linux ------------------------ */
+
+#if defined(PLAT_amd64_linux)
+
+/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
+ "rdi", "r8", "r9", "r10", "r11"
+
+/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
+ long) == 8. */
+
+/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
+ macros. In order not to trash the stack redzone, we need to drop
+ %rsp by 128 before the hidden call, and restore afterwards. The
+ nastyness is that it is only by luck that the stack still appears
+ to be unwindable during the hidden call - since then the behaviour
+ of any routine using this macro does not match what the CFI data
+ says. Sigh.
+
+ Why is this important? Imagine that a wrapper has a stack
+ allocated local, and passes to the hidden call, a pointer to it.
+ Because gcc does not know about the hidden call, it may allocate
+ that local in the redzone. Unfortunately the hidden call may then
+ trash it before it comes to use it. So we must step clear of the
+ redzone, for the duration of the hidden call, to make it safe.
+
+ Probably the same problem afflicts the other redzone-style ABIs too
+ (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
+ self describing (none of this CFI nonsense) so at least messing
+ with the stack pointer doesn't give a danger of non-unwindable
+ stack. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ "addq $128,%%rsp\n\t" \
+ VALGRIND_CALL_NOREDIR_RAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $8, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $16, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $24, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $32, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $40, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 96(%%rax)\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $48, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_amd64_linux */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+/* This is useful for finding out about the on-stack stuff:
+
+ extern int f9 ( int,int,int,int,int,int,int,int,int );
+ extern int f10 ( int,int,int,int,int,int,int,int,int,int );
+ extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
+ extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
+
+ int g9 ( void ) {
+ return f9(11,22,33,44,55,66,77,88,99);
+ }
+ int g10 ( void ) {
+ return f10(11,22,33,44,55,66,77,88,99,110);
+ }
+ int g11 ( void ) {
+ return f11(11,22,33,44,55,66,77,88,99,110,121);
+ }
+ int g12 ( void ) {
+ return f12(11,22,33,44,55,66,77,88,99,110,121,132);
+ }
+*/
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc32-linux,
+ sizeof(unsigned long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ _argvec[12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,20(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "lwz 3," #_n_fr "(1)\n\t" \
+ "stw 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,68(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "ld 3," #_n_fr "(1)\n\t" \
+ "std 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_aix5 */
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
+/* */
+/* ------------------------------------------------------------------ */
+
+/* Some request codes. There are many more of these, but most are not
+ exposed to end-user view. These are the public ones, all of the
+ form 0x1000 + small_number.
+
+ Core ones are in the range 0x00000000--0x0000ffff. The non-public
+ ones start at 0x2000.
+*/
+
+/* These macros are used by tools -- they must be public, but don't
+ embed them into other programs. */
+#define VG_USERREQ_TOOL_BASE(a,b) \
+ ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
+#define VG_IS_TOOL_USERREQ(a, b, v) \
+ (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+ This enum comprises an ABI exported by Valgrind to programs
+ which use client requests. DO NOT CHANGE THE ORDER OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end. */
+typedef
+ enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
+ VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
+
+ /* These allow any function to be called from the simulated
+ CPU but run on the real CPU. Nb: the first arg passed to
+ the function is always the ThreadId of the running
+ thread! So CLIENT_CALL0 actually requires a 1 arg
+ function, etc. */
+ VG_USERREQ__CLIENT_CALL0 = 0x1101,
+ VG_USERREQ__CLIENT_CALL1 = 0x1102,
+ VG_USERREQ__CLIENT_CALL2 = 0x1103,
+ VG_USERREQ__CLIENT_CALL3 = 0x1104,
+
+ /* Can be useful in regression testing suites -- eg. can
+ send Valgrind's output to /dev/null and still count
+ errors. */
+ VG_USERREQ__COUNT_ERRORS = 0x1201,
+
+ /* These are useful and can be interpreted by any tool that
+ tracks malloc() et al, by using vg_replace_malloc.c. */
+ VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+ VG_USERREQ__FREELIKE_BLOCK = 0x1302,
+ /* Memory pool support. */
+ VG_USERREQ__CREATE_MEMPOOL = 0x1303,
+ VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
+ VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
+ VG_USERREQ__MEMPOOL_FREE = 0x1306,
+ VG_USERREQ__MEMPOOL_TRIM = 0x1307,
+ VG_USERREQ__MOVE_MEMPOOL = 0x1308,
+ VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
+ VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
+
+ /* Allow printfs to valgrind log. */
+ VG_USERREQ__PRINTF = 0x1401,
+ VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
+
+ /* Stack support. */
+ VG_USERREQ__STACK_REGISTER = 0x1501,
+ VG_USERREQ__STACK_DEREGISTER = 0x1502,
+ VG_USERREQ__STACK_CHANGE = 0x1503
+ } Vg_ClientRequest;
+
+#if !defined(__GNUC__)
+# define __extension__ /* */
+#endif
+
+/* Returns the number of Valgrinds this code is running under. That
+ is, 0 if running natively, 1 if running under Valgrind, 2 if
+ running under Valgrind which is running under another Valgrind,
+ etc. */
+#define RUNNING_ON_VALGRIND __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
+ VG_USERREQ__RUNNING_ON_VALGRIND, \
+ 0, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+
+/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
+ _qzz_len - 1]. Useful if you are debugging a JITter or some such,
+ since it provides a way to make sure valgrind will retranslate the
+ invalidated area. Returns no value. */
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DISCARD_TRANSLATIONS, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ }
+
+
+/* These requests are for getting Valgrind itself to print something.
+ Possibly with a backtrace. This is a really ugly hack. */
+
+#if defined(NVALGRIND)
+
+# define VALGRIND_PRINTF(...)
+# define VALGRIND_PRINTF_BACKTRACE(...)
+
+#else /* NVALGRIND */
+
+/* Modern GCC will optimize the static routine out if unused,
+ and unused attribute will shut down warnings about it. */
+static int VALGRIND_PRINTF(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
+ (unsigned long)format, (unsigned long)vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
+ (unsigned long)format, (unsigned long)vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+#endif /* NVALGRIND */
+
+
+/* These requests allow control to move from the simulated CPU to the
+ real CPU, calling an arbitary function.
+
+ Note that the current ThreadId is inserted as the first argument.
+ So this call:
+
+ VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
+
+ requires f to have this signature:
+
+ Word f(Word tid, Word arg1, Word arg2)
+
+ where "Word" is a word-sized type.
+
+ Note that these client requests are not entirely reliable. For example,
+ if you call a function with them that subsequently calls printf(),
+ there's a high chance Valgrind will crash. Generally, your prospects of
+ these working are made higher if the called function does not refer to
+ any global variables, and does not refer to any libc or other functions
+ (printf et al). Any kind of entanglement with libc or dynamic linking is
+ likely to have a bad outcome, for tricky reasons which we've grappled
+ with a lot in the past.
+*/
+#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL0, \
+ _qyy_fn, \
+ 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL1, \
+ _qyy_fn, \
+ _qyy_arg1, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL2, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL3, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, \
+ _qyy_arg3, 0); \
+ _qyy_res; \
+ })
+
+
+/* Counts the number of errors that have been recorded by a tool. Nb:
+ the tool must record the errors with VG_(maybe_record_error)() or
+ VG_(unique_error)() for them to be counted. */
+#define VALGRIND_COUNT_ERRORS \
+ __extension__ \
+ ({unsigned int _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__COUNT_ERRORS, \
+ 0, 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+/* Mark a block of memory as having been allocated by a malloc()-like
+ function. `addr' is the start of the usable block (ie. after any
+ redzone) `rzB' is redzone size if the allocator can apply redzones;
+ use '0' if not. Adding redzones makes it more likely Valgrind will spot
+ block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
+ for calloc(). Put it immediately after the point where a block is
+ allocated.
+
+ If you're using Memcheck: If you're allocating memory via superblocks,
+ and then handing out small chunks of each superblock, if you don't have
+ redzones on your small blocks, it's worth marking the superblock with
+ VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
+ detected. But if you can put redzones on, it's probably better to not do
+ this, so that messages for small overruns are described in terms of the
+ small block rather than the superblock (but if you have a big overrun
+ that skips over a redzone, you could miss an error this way). See
+ memcheck/tests/custom_alloc.c for an example.
+
+ WARNING: if your allocator uses malloc() or 'new' to allocate
+ superblocks, rather than mmap() or brk(), this will not work properly --
+ you'll likely get assertion failures during leak detection. This is
+ because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
+
+ Nb: block must be freed via a free()-like function specified
+ with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MALLOCLIKE_BLOCK, \
+ addr, sizeB, rzB, is_zeroed, 0); \
+ }
+
+/* Mark a block of memory as having been freed by a free()-like function.
+ `rzB' is redzone size; it must match that given to
+ VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
+ checker. Put it immediately after the point where the block is freed. */
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__FREELIKE_BLOCK, \
+ addr, rzB, 0, 0, 0); \
+ }
+
+/* Create a memory pool. */
+#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__CREATE_MEMPOOL, \
+ pool, rzB, is_zeroed, 0, 0); \
+ }
+
+/* Destroy a memory pool. */
+#define VALGRIND_DESTROY_MEMPOOL(pool) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DESTROY_MEMPOOL, \
+ pool, 0, 0, 0, 0); \
+ }
+
+/* Associate a piece of memory with a memory pool. */
+#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_ALLOC, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Disassociate a piece of memory from a memory pool. */
+#define VALGRIND_MEMPOOL_FREE(pool, addr) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_FREE, \
+ pool, addr, 0, 0, 0); \
+ }
+
+/* Disassociate any pieces outside a particular range. */
+#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_TRIM, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MOVE_MEMPOOL, \
+ poolA, poolB, 0, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_CHANGE, \
+ pool, addrA, addrB, size, 0); \
+ }
+
+/* Return 1 if a mempool exists, else 0. */
+#define VALGRIND_MEMPOOL_EXISTS(pool) \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_EXISTS, \
+ pool, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Mark a piece of memory as being a stack. Returns a stack id. */
+#define VALGRIND_STACK_REGISTER(start, end) \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_REGISTER, \
+ start, end, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Unmark the piece of memory associated with a stack id as being a
+ stack. */
+#define VALGRIND_STACK_DEREGISTER(id) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_DEREGISTER, \
+ id, 0, 0, 0, 0); \
+ }
+
+/* Change the start and end address of the stack id. */
+#define VALGRIND_STACK_CHANGE(id, start, end) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_CHANGE, \
+ id, start, end, 0, 0); \
+ }
+
+
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
+
+#endif /* __VALGRIND_H */
diff --git a/chromium/third_party/tcmalloc/vendor/src/thread_cache.cc b/chromium/third_party/tcmalloc/vendor/src/thread_cache.cc
new file mode 100644
index 00000000000..d6dead39c2f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/thread_cache.cc
@@ -0,0 +1,503 @@
+// 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 <opensource@google.com>
+
+#include <config.h>
+#include "thread_cache.h"
+#include <errno.h>
+#include <string.h> // for memcpy
+#include <algorithm> // for max, min
+#include "base/commandlineflags.h" // for SpinLockHolder
+#include "base/spinlock.h" // for SpinLockHolder
+#include "central_freelist.h" // for CentralFreeListPadded
+#include "maybe_threads.h"
+
+using std::min;
+using std::max;
+
+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> threadcache_allocator;
+ThreadCache* ThreadCache::thread_heaps_ = NULL;
+int ThreadCache::thread_heap_count_ = 0;
+ThreadCache* ThreadCache::next_memory_steal_ = NULL;
+#ifdef HAVE_TLS
+__thread ThreadCache* ThreadCache::threadlocal_heap_
+# ifdef HAVE___ATTRIBUTE__
+ __attribute__ ((tls_model ("initial-exec")))
+# endif
+ ;
+#endif
+bool ThreadCache::tsd_inited_ = false;
+pthread_key_t ThreadCache::heap_key_;
+
+#if defined(HAVE_TLS)
+bool kernel_supports_tls = false; // be conservative
+# if defined(_WIN32) // windows has supported TLS since winnt, I think.
+ void CheckIfKernelSupportsTLS() {
+ kernel_supports_tls = true;
+ }
+# elif !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS
+ void CheckIfKernelSupportsTLS() {
+ kernel_supports_tls = false;
+ }
+# else
+# include <sys/utsname.h> // DECL_UNAME checked for <sys/utsname.h> too
+ void CheckIfKernelSupportsTLS() {
+ struct utsname buf;
+ if (uname(&buf) < 0) { // should be impossible
+ Log(kLog, __FILE__, __LINE__,
+ "uname failed assuming no TLS support (errno)", errno);
+ kernel_supports_tls = false;
+ } else if (strcasecmp(buf.sysname, "linux") == 0) {
+ // The linux case: the first kernel to support TLS was 2.6.0
+ if (buf.release[0] < '2' && buf.release[1] == '.') // 0.x or 1.x
+ kernel_supports_tls = false;
+ else if (buf.release[0] == '2' && buf.release[1] == '.' &&
+ buf.release[2] >= '0' && buf.release[2] < '6' &&
+ buf.release[3] == '.') // 2.0 - 2.5
+ kernel_supports_tls = false;
+ else
+ kernel_supports_tls = true;
+ } else if (strcasecmp(buf.sysname, "CYGWIN_NT-6.1-WOW64") == 0) {
+ // In my testing, this version of cygwin, at least, would hang
+ // when using TLS.
+ kernel_supports_tls = false;
+ } else { // some other kernel, we'll be optimisitic
+ kernel_supports_tls = true;
+ }
+ // TODO(csilvers): VLOG(1) the tls status once we support RAW_VLOG
+ }
+# endif // HAVE_DECL_UNAME
+#endif // HAVE_TLS
+
+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.
+ max_size_ = 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 (size_t cl = 0; cl < kNumClasses; ++cl) {
+ list_[cl].Init();
+ }
+
+ 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 (int cl = 0; cl < kNumClasses; ++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(size_t cl, size_t byte_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<int>(list->max_length(), batch_size);
+ void *start, *end;
+ int fetch_count = Static::central_cache()[cl].RemoveRange(
+ &start, &end, num_to_move);
+
+ ASSERT((start == NULL) == (fetch_count == 0));
+ 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<int>(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, size_t cl) {
+ 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);
+ }
+ }
+}
+
+// Remove some objects of class "cl" from thread heap and add to central cache
+void ThreadCache::ReleaseToCentralCache(FreeList* src, size_t 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.
+ //int64 start = CycleClock::Now();
+ for (int cl = 0; cl < kNumClasses; 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<int>(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;
+ 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_->max_size_ -= kStealAmount;
+ 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) {
+ Static::InitStaticVars();
+ threadcache_allocator.Init();
+ phinited = 1;
+ }
+}
+
+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() {
+ // Initialize per-thread data if necessary
+ ThreadCache* heap = NULL;
+ {
+ 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.
+ 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_heap_ = heap;
+#endif
+ heap->in_setspecific_ = false;
+ }
+ 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_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::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_heap_ = NULL;
+#endif
+ DeleteCache(reinterpret_cast<ThreadCache*>(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<double>(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->max_size_ = static_cast<size_t>(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 < kNumClasses; ++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/chromium/third_party/tcmalloc/vendor/src/thread_cache.h b/chromium/third_party/tcmalloc/vendor/src/thread_cache.h
new file mode 100644
index 00000000000..1d0413b2a8a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/thread_cache.h
@@ -0,0 +1,403 @@
+// 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 <opensource@google.com>
+
+#ifndef TCMALLOC_THREAD_CACHE_H_
+#define TCMALLOC_THREAD_CACHE_H_
+
+#include <config.h>
+#ifdef HAVE_PTHREAD
+#include <pthread.h> // for pthread_t, pthread_key_t
+#endif
+#include <stddef.h> // for size_t, NULL
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uint32_t, uint64_t
+#endif
+#include <sys/types.h> // for ssize_t
+#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
+
+namespace tcmalloc {
+
+// Even if we have support for thread-local storage in the compiler
+// and linker, the OS may not support it. We need to check that at
+// runtime. Right now, we have to keep a manual set of "bad" OSes.
+#if defined(HAVE_TLS)
+extern bool kernel_supports_tls; // defined in thread_cache.cc
+void CheckIfKernelSupportsTLS();
+inline bool KernelSupportsTLS() {
+ return kernel_supports_tls;
+}
+#endif // HAVE_TLS
+
+//-------------------------------------------------------------------
+// Data kept per thread
+//-------------------------------------------------------------------
+
+class ThreadCache {
+ public:
+ // All ThreadCache objects are kept in a linked list (for stats collection)
+ ThreadCache* next_;
+ ThreadCache* prev_;
+
+ void Init(pthread_t tid);
+ void Cleanup();
+
+ // Accessors (mostly just for printing stats)
+ int freelist_length(size_t 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, size_t cl);
+ void Deallocate(void* ptr, size_t size_class);
+
+ void Scavenge();
+
+ int GetSamplePeriod();
+
+ // Record allocation of "k" bytes. Return true iff allocation
+ // should be sampled
+ bool SampleAllocation(size_t k);
+
+ static void InitModule();
+ static void InitTSD();
+ static ThreadCache* GetThreadHeap();
+ static ThreadCache* GetCache();
+ static ThreadCache* GetCacheIfPresent();
+ static ThreadCache* CreateCacheIfNecessary();
+ static void BecomeIdle();
+
+ // Return the number of thread heaps in use.
+ static inline int HeapsInUse();
+
+ // Writes to total_bytes the total number of bytes used by all thread heaps.
+ // class_count must be an array of size kNumClasses. Writes the number of
+ // items on the corresponding freelist. class_count may be NULL.
+ // The storage of both parameters must be zero intialized.
+ // 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
+
+ public:
+ void Init() {
+ list_ = NULL;
+ length_ = 0;
+ lowater_ = 0;
+ max_length_ = 1;
+ length_overages_ = 0;
+ }
+
+ // Return current length of list
+ size_t length() const {
+ return length_;
+ }
+
+ // 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_; }
+
+ void Push(void* ptr) {
+ SLL_Push(&list_, ptr);
+ length_++;
+ }
+
+ void* Pop() {
+ ASSERT(list_ != NULL);
+ length_--;
+ if (length_ < lowater_) lowater_ = length_;
+ return SLL_Pop(&list_);
+ }
+
+ 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(size_t cl, size_t byte_size);
+
+ // 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, size_t cl);
+
+ // Releases N items from this thread cache.
+ void ReleaseToCentralCache(FreeList* src, size_t cl, int N);
+
+ // 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
+ static __thread ThreadCache* threadlocal_heap_
+# ifdef HAVE___ATTRIBUTE__
+ __attribute__ ((tls_model ("initial-exec")))
+# endif
+ ;
+#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 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.
+
+ size_t size_; // Combined size of data
+ size_t max_size_; // size_ > max_size_ --> Scavenge()
+
+ // We sample allocations, biased by the size of the allocation
+ Sampler sampler_; // A sampler
+
+ FreeList list_[kNumClasses]; // Array indexed by size-class
+
+ 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();
+
+ // 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> threadcache_allocator;
+
+inline int ThreadCache::HeapsInUse() {
+ return threadcache_allocator.inuse();
+}
+
+inline bool ThreadCache::SampleAllocation(size_t k) {
+ return sampler_.SampleAllocation(k);
+}
+
+inline void* ThreadCache::Allocate(size_t size, size_t cl) {
+ ASSERT(size <= kMaxSize);
+ ASSERT(size == Static::sizemap()->ByteSizeForClass(cl));
+
+ FreeList* list = &list_[cl];
+ if (list->empty()) {
+ return FetchFromCentralCache(cl, size);
+ }
+ size_ -= size;
+ return list->Pop();
+}
+
+inline void ThreadCache::Deallocate(void* ptr, size_t cl) {
+ FreeList* list = &list_[cl];
+ size_ += Static::sizemap()->ByteSizeForClass(cl);
+ ssize_t size_headroom = max_size_ - size_ - 1;
+
+ // 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());
+
+ list->Push(ptr);
+ ssize_t list_headroom =
+ static_cast<ssize_t>(list->max_length()) - list->length();
+
+ // There are two relatively uncommon things that require further work.
+ // In the common case we're done, and in that case we need a single branch
+ // because of the bitwise-or trick that follows.
+ if ((list_headroom | size_headroom) < 0) {
+ if (list_headroom < 0) {
+ ListTooLong(list, cl);
+ }
+ if (size_ >= max_size_) Scavenge();
+ }
+}
+
+inline ThreadCache* ThreadCache::GetThreadHeap() {
+#ifdef HAVE_TLS
+ // __thread is faster, but only when the kernel supports it
+ if (KernelSupportsTLS())
+ return threadlocal_heap_;
+#endif
+ return reinterpret_cast<ThreadCache *>(
+ perftools_pthread_getspecific(heap_key_));
+}
+
+inline ThreadCache* ThreadCache::GetCache() {
+ ThreadCache* ptr = NULL;
+ if (!tsd_inited_) {
+ InitModule();
+ } else {
+ ptr = GetThreadHeap();
+ }
+ 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() {
+ if (!tsd_inited_) return NULL;
+ return GetThreadHeap();
+}
+
+} // namespace tcmalloc
+
+#endif // TCMALLOC_THREAD_CACHE_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/TODO b/chromium/third_party/tcmalloc/vendor/src/windows/TODO
new file mode 100644
index 00000000000..708ec237ac4
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c b/chromium/third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c
new file mode 100644
index 00000000000..5c65a0357e5
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c
@@ -0,0 +1,163 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <dbghelp.h>
+
+#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 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], "-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 : %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;
+ }
+
+ 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 addr = _strtoui64(buf, NULL, 16);
+ ULONG64 buffer[(sizeof(SYMBOL_INFO) +
+ MAX_SYM_NAME*sizeof(TCHAR) +
+ sizeof(ULONG64) - 1)
+ / sizeof(ULONG64)];
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+ IMAGEHLP_LINE64 line;
+ DWORD dummy;
+ pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ pSymbol->MaxNameLen = MAX_SYM_NAME;
+ if (print_function_name) {
+ if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
+ printf("%s\n", pSymbol->Name);
+ } else {
+ printf("??\n");
+ }
+ }
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ if (SymGetLineFromAddr64(process, (DWORD64)addr, &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/chromium/third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h b/chromium/third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h
new file mode 100644
index 00000000000..5a047977395
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h
@@ -0,0 +1,155 @@
+// 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 <typename T>
+class AutoTestingHookImpl : public AutoTestingHookBase {
+ public:
+ static AutoTestingHookImpl<T> MakeTestingHook(T target_function,
+ T replacement_function,
+ bool do_it) {
+ return AutoTestingHookImpl<T>(target_function, replacement_function, do_it);
+ }
+
+ static AutoTestingHookImpl<T>* MakeTestingHookHolder(T target_function,
+ T replacement_function,
+ bool do_it) {
+ return new AutoTestingHookImpl<T>(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 <typename T>
+inline AutoTestingHookImpl<T> MakeTestingHook(T target,
+ T replacement,
+ bool do_it) {
+ return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, do_it);
+}
+
+template <typename T>
+inline AutoTestingHookImpl<T> MakeTestingHook(T target, T replacement) {
+ return AutoTestingHookImpl<T>::MakeTestingHook(target, replacement, true);
+}
+
+template <typename T>
+inline AutoTestingHookImpl<T>* MakeTestingHookHolder(T target, T replacement) {
+ return AutoTestingHookImpl<T>::MakeTestingHookHolder(target, replacement,
+ true);
+}
+
+}; // namespace sidestep
+
+#endif // CEEE_TESTING_SIDESTEP_AUTO_TESTING_HOOK_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/config.h b/chromium/third_party/tcmalloc/vendor/src/windows/config.h
new file mode 100644
index 00000000000..9d61884e298
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/config.h
@@ -0,0 +1,306 @@
+/* A manual version of config.h fit for windows machines. */
+
+/* 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_
+
+/* define this if you are linking tcmalloc statically and overriding the
+ * default allocators.
+ * For instructions on how to use this mode, see
+ * http://groups.google.com/group/google-perftools/browse_thread/thread/41cd3710af85e57b
+ */
+#undef WIN32_OVERRIDE_ALLOCATORS
+
+/* Define to 1 if your libc has a snprintf implementation */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if compiler supports __builtin_stack_pointer */
+#undef HAVE_BUILTIN_STACK_POINTER
+
+/* Define to 1 if you have the <conflict-signal.h> header file. */
+#undef HAVE_CONFLICT_SIGNAL_H
+
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
+/* 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 `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 `uname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_UNAME
+
+/* 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 <dlfcn.h> 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 <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `geteuid' function. */
+#undef HAVE_GETEUID
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1 /* we define it in windows/port.cc */
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libunwind.h> header file. */
+#undef HAVE_LIBUNWIND_H
+
+/* Define to 1 if you have the <linux/ptrace.h> header file. */
+#undef HAVE_LINUX_PTRACE_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <malloc/malloc.h> header file. */
+#undef HAVE_MALLOC_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if the compiler implements namespaces */
+#define HAVE_NAMESPACES 1
+
+/* Define to 1 if you have the <poll.h> 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
+
+/* Define to 1 if you have the <pwd.h> 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 <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/malloc.h> header file. */
+#undef HAVE_SYS_MALLOC_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* <sys/ucontext.h> is broken on redhat 7 */
+#undef HAVE_SYS_UCONTEXT_H
+
+/* Define to 1 if you have the <sys/wait.h> 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 <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <unwind.h> header file. */
+#undef HAVE_UNWIND_H
+
+/* Define to 1 if you have the <valgrind.h> header file. */
+#undef HAVE_VALGRIND_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define to 1 if compiler supports __environ */
+#undef HAVE___ENVIRON
+
+/* Define to 1 if the system has the type `__int64'. */
+#define HAVE___INT64 1
+
+/* 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 in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 'volatile' if __malloc_hook is declared volatile */
+#undef MALLOC_HOOK_MAYBE_VOLATILE
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "gperftools"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opensource@google.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.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "gperftools"
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.0"
+
+/* 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
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIdS "Id"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIuS "Iu"
+
+/* printf format code for printing a size_t and ssize_t */
+#define PRIxS "Ix"
+
+/* 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
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Version number of package */
+#undef VERSION
+
+/* C99 says: define this to get the PRI... macros from stdint.h */
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#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/chromium/third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc b/chromium/third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc
new file mode 100644
index 00000000000..e8a96dfff7d
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc
@@ -0,0 +1,64 @@
+// 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 <sys/types.h> // for size_t
+#include <new> // 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/chromium/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h b/chromium/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h
new file mode 100644
index 00000000000..c7db6319426
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h
@@ -0,0 +1,34 @@
+/* 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.
+ */
+#include <gperftools/tcmalloc.h>
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h b/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h
new file mode 100644
index 00000000000..db32c5366ab
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h.in file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR 2
+#define TC_VERSION_MINOR 0
+#define TC_VERSION_PATCH ""
+#define TC_VERSION_STRING "gperftools 2.0"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if 0
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in b/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in
new file mode 100644
index 00000000000..d09ec953622
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in
@@ -0,0 +1,123 @@
+/* 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 <opensource@google.com>
+ * .h.in file by Craig Silverstein <opensource@google.com>
+ */
+
+#ifndef TCMALLOC_TCMALLOC_H_
+#define TCMALLOC_TCMALLOC_H_
+
+#include <stddef.h> // for size_t
+#ifdef HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h> // where glibc defines __THROW
+#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
+
+// 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@"
+
+#include <stdlib.h> // for struct mallinfo, if it's defined
+
+// 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
+namespace std {
+struct nothrow_t;
+}
+
+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) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
+
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
+#if 0
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
+#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) __THROW;
+
+#ifdef __cplusplus
+ PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
+ const std::nothrow_t&) __THROW;
+}
+#endif
+
+#endif // #ifndef TCMALLOC_TCMALLOC_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc b/chromium/third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc
new file mode 100644
index 00000000000..142c7cbea60
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc
@@ -0,0 +1,121 @@
+/* Copyright (c) 2007, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Joi Sigurdsson
+ *
+ * Table of relevant information about how to decode the ModR/M byte.
+ * Based on information in the IA-32 Intel® Architecture
+ * Software Developer's Manual Volume 2: Instruction Set Reference.
+ */
+
+#include "mini_disassembler.h"
+#include "mini_disassembler_types.h"
+
+namespace sidestep {
+
+const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, false, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_WORD },
+ /* r/m == 001 */ { true, false, OS_WORD },
+ /* r/m == 010 */ { true, false, OS_WORD },
+ /* r/m == 011 */ { true, false, OS_WORD },
+ /* r/m == 100 */ { true, false, OS_WORD },
+ /* r/m == 101 */ { true, false, OS_WORD },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { true, false, OS_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO }
+};
+
+const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, true, OS_ZERO },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, true, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+};
+
+}; // namespace sidestep
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc b/chromium/third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc
new file mode 100644
index 00000000000..e14279cd345
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc
@@ -0,0 +1,1219 @@
+/* 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/chromium/third_party/tcmalloc/vendor/src/windows/mingw.h b/chromium/third_party/tcmalloc/vendor/src/windows/mingw.h
new file mode 100644
index 00000000000..2aa5eb3ed27
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/mingw.h
@@ -0,0 +1,67 @@
+/* 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
+
+#define HAVE_SNPRINTF 1
+
+// 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.
+#undef HAVE_PTHREAD
+
+#include "windows/port.h"
+
+#endif /* __MINGW32__ */
+
+#endif /* GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc
new file mode 100644
index 00000000000..9e336ba4f9a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc
@@ -0,0 +1,431 @@
+/* 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/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.h b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.h
new file mode 100644
index 00000000000..85be6748e95
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler.h
@@ -0,0 +1,197 @@
+/* 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 <windows.h>
+#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 <b>incremented</b> by
+ // the length in bytes of the instruction.
+ // @return enItJump, enItReturn or enItGeneric on success. enItUnknown
+ // if unable to disassemble, enItUnused if this seems to be an unused
+ // opcode. In the last two (error) cases, cbInstruction will be set
+ // to 0xffffffff.
+ //
+ // @post This instance of the disassembler is ready to be used again,
+ // with unchanged defaults from creation time.
+ InstructionType Disassemble(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/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h
new file mode 100644
index 00000000000..83dee8ba920
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h
@@ -0,0 +1,236 @@
+/* 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.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+
+ // Alternative opcode info if certain prefixes are specified.
+ // In most cases, all of these are zeroed-out. Only used if
+ // bPrefixDependent is true.
+ bool is_prefix_dependent_;
+ SpecificOpcode opcode_if_f2_prefix_;
+ SpecificOpcode opcode_if_f3_prefix_;
+ SpecificOpcode opcode_if_66_prefix_;
+};
+
+// Information about each table entry.
+struct OpcodeTable {
+ // Table of instruction entries
+ const Opcode* table_;
+ // How many bytes left to shift ModR/M byte <b>before</b> applying mask
+ unsigned char shift_;
+ // Mask to apply to byte being looked at before comparing to table
+ unsigned char mask_;
+ // Minimum/maximum indexes in table.
+ unsigned char min_lim_;
+ unsigned char max_lim_;
+};
+
+// Information about each entry in table used to decode ModR/M byte.
+struct ModrmEntry {
+ // Is the operand encoded as bytes in the instruction (rather than
+ // if it's e.g. a register in which case it's just encoded in the
+ // ModR/M byte)
+ bool is_encoded_in_instruction_;
+
+ // Is there a SIB byte? In this case we always need to decode it.
+ bool use_sib_byte_;
+
+ // What is the size of the operand (only important if it's encoded
+ // in the instruction)?
+ OperandSize operand_size_;
+};
+
+}; // namespace sidestep
+
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H_
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/nm-pdb.c b/chromium/third_party/tcmalloc/vendor/src/windows/nm-pdb.c
new file mode 100644
index 00000000000..9beb21dea99
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/nm-pdb.c
@@ -0,0 +1,273 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h> // for _strdup
+
+#include <windows.h>
+#include <dbghelp.h>
+
+// 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] <module or filename>\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/chromium/third_party/tcmalloc/vendor/src/windows/override_functions.cc b/chromium/third_party/tcmalloc/vendor/src/windows/override_functions.cc
new file mode 100644
index 00000000000..e634fe27280
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/override_functions.cc
@@ -0,0 +1,122 @@
+// 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 <config.h>
+
+#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* _recalloc(void* p, size_t n, size_t size) {
+ void* result = realloc(p, n * size);
+ memset(result, 0, n * size);
+ return result;
+}
+
+extern "C" void* _calloc_impl(size_t n, size_t size) {
+ return calloc(n, size);
+}
+
+extern "C" size_t _msize(void* p) {
+ return MallocExtension::instance()->GetAllocatedSize(p);
+}
+
+extern "C" intptr_t _get_heap_handle() {
+ return 0;
+}
+
+// The CRT heap initialization stub.
+extern "C" 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.
+extern "C" void _heap_term() {
+}
+
+extern "C" int _set_new_mode(int flag) {
+ return tc_set_new_mode(flag);
+}
+
+#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
+
+// 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.
+extern "C" void* _crtheap = reinterpret_cast<void*>(1);
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/patch_functions.cc b/chromium/third_party/tcmalloc/vendor/src/windows/patch_functions.cc
new file mode 100644
index 00000000000..7a7e6adf039
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/patch_functions.cc
@@ -0,0 +1,1080 @@
+// 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 <config.h>
+
+#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 <windows.h>
+#include <stdio.h>
+#include <malloc.h> // for _msize and _expand
+#include <Psapi.h> // for EnumProcessModules, GetModuleInformation, etc.
+#include <set>
+#include <map>
+#include <vector>
+#include <base/logging.h>
+#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.
+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";
+
+// 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<HMODULE>(const_cast<void*>(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,
+ 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 arugment -- 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<int> 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_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<const HMODULE>(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",
+};
+
+// 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,
+};
+
+template<int T> GenericFnPtr LibcInfoWithPatchFunctions<T>::origstub_fn_[] = {
+ // This will get filled in at run-time, as patching is done.
+};
+
+template<int T>
+const GenericFnPtr LibcInfoWithPatchFunctions<T>::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,
+};
+
+/*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<int T>
+bool LibcInfoWithPatchFunctions<T>::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.
+ // 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*)(origstub_fn_[i]);
+ 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<int T>
+void LibcInfoWithPatchFunctions<T>::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<HMODULE> *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<ModuleEntryCopy> 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<HMODULE> currently_loaded_modules;
+ {
+ SpinLockHolder h(&patch_all_modules_lock);
+ if (!g_last_loaded) g_last_loaded = new std::set<HMODULE>;
+ // 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<ModuleEntryCopy>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_malloc(size_t size) __THROW {
+ void* result = do_malloc_or_cpp_alloc(size);
+ MallocHook::InvokeNewHook(result, size);
+ return result;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::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]);
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::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]);
+ 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<int T>
+void* LibcInfoWithPatchFunctions<T>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_new(size_t size) {
+ void* p = cpp_alloc(size, false);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_newarray(size_t size) {
+ void* p = cpp_alloc(size, false);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_delete(void *p) {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_deletearray(void *p) {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_new_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void* LibcInfoWithPatchFunctions<T>::Perftools_newarray_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
+ void* p = cpp_alloc(size, true);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_delete_nothrow(
+ void *p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+template<int T>
+void LibcInfoWithPatchFunctions<T>::Perftools_deletearray_nothrow(
+ void *p, const std::nothrow_t&) __THROW {
+ MallocHook::InvokeDeleteHook(p);
+ do_free_with_callback(p, (void (*)(void*))origstub_fn_[kFree]);
+}
+
+
+// _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<int T>
+size_t LibcInfoWithPatchFunctions<T>::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<int T>
+void* LibcInfoWithPatchFunctions<T>::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);
+}
+
+// g_load_map holds a copy of windows' refcount for how many times
+// each currently loaded module has been loaded and unloaded. We use
+// it as an optimization when the same module is loaded more than
+// once: as long as the refcount stays above 1, we don't need to worry
+// about patching because it's already patched. Likewise, we don't
+// need to unpatch until the refcount drops to 0. load_map is
+// maintained in LoadLibraryExW and FreeLibrary, and only covers
+// modules explicitly loaded/freed via those interfaces.
+static std::map<HMODULE, int>* g_load_map = NULL;
+
+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/chromium/third_party/tcmalloc/vendor/src/windows/port.cc b/chromium/third_party/tcmalloc/vendor/src/windows/port.cc
new file mode 100644
index 00000000000..e68de163d3e
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/port.cc
@@ -0,0 +1,294 @@
+/* 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 <config.h>
+#include <string.h> // for strlen(), memset(), memcmp()
+#include <assert.h>
+#include <stdarg.h> // for va_list, va_start, va_end
+#include <windows.h>
+#include "port.h"
+#include "base/logging.h"
+#include "base/spinlock.h"
+#include "internal_logging.h"
+#include "system-alloc.h"
+
+// -----------------------------------------------------------------------
+// Basic libraries
+
+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
+
+// Declared (not extern "C") in thread_cache.h
+bool CheckIfKernelSupportsTLS() {
+ // TODO(csilvers): return true (all win's since win95, at least, support this)
+ return false;
+}
+
+// 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 http://www.codeproject.com/threads/tls.asp.
+// 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.
+extern "C" {
+// This tells the linker to run these functions.
+#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"
+
+#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 replace system-alloc.cc
+
+// This is mostly like MmapSysAllocator::Alloc, except it does these weird
+// munmap's in the middle of the page, which is forbidden in windows.
+extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
+ size_t alignment) {
+ // Align on the pagesize boundary
+ const int pagesize = getpagesize();
+ if (alignment < pagesize) alignment = pagesize;
+ size = ((size + alignment - 1) / alignment) * alignment;
+
+ // Safest is to make actual_size same as input-size.
+ if (actual_size) {
+ *actual_size = size;
+ }
+
+ // Ask for extra memory if alignment > pagesize
+ size_t extra = 0;
+ if (alignment > pagesize) {
+ extra = alignment - pagesize;
+ }
+
+ void* result = VirtualAlloc(0, size + extra,
+ MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ if (result == NULL)
+ return NULL;
+
+ // Adjust the return memory so it is aligned
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
+ size_t adjust = 0;
+ if ((ptr & (alignment - 1)) != 0) {
+ adjust = alignment - (ptr & (alignment - 1));
+ }
+
+ ptr += adjust;
+ return reinterpret_cast<void*>(ptr);
+}
+
+void TCMalloc_SystemRelease(void* start, size_t length) {
+ // TODO(csilvers): should I be calling VirtualFree here?
+}
+
+bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {
+ return false; // we don't allow registration on windows, right now
+}
+
+void DumpSystemAllocatorStats(TCMalloc_Printer* printer) {
+ // We don't dump stats on windows, right now
+}
+
+// The current system allocator
+SysAllocator* sys_alloc = NULL;
+
+
+// -----------------------------------------------------------------------
+// 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/chromium/third_party/tcmalloc/vendor/src/windows/port.h b/chromium/third_party/tcmalloc/vendor/src/windows/port.h
new file mode 100644
index 00000000000..e9a020656b3
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/port.h
@@ -0,0 +1,474 @@
+/* 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 <windows.h>
+#include <io.h> /* because we so often use open/close/etc */
+#include <direct.h> /* for _getcwd */
+#include <process.h> /* for _getpid */
+#include <limits.h> /* for PATH_MAX */
+#include <stdarg.h> /* for va_list */
+#include <stdio.h> /* need this to override stdio's (v)snprintf */
+#include <sys/types.h> /* for _off_t */
+#include <assert.h>
+#include <stdlib.h> /* for rand, srand, _strtoxxx */
+
+/*
+ * 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
+#ifndef HAVE___INT64 /* we need to have all the __intX names */
+# error Do not know how to set up type aliases. Edit port.h for your system.
+#endif
+
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif /* #ifndef HAVE_STDINT_H */
+
+/* I guess MSVC's <types.h> 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;
+}
+
+/* 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 */
+#endif /* HAVE_PTHREAD */
+
+inline void sched_yield(void) {
+ Sleep(0);
+}
+
+/*
+ * __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_SNPRINTF
+inline int snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ int r;
+ va_start(ap, format);
+ r = perftools_vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return r;
+}
+#endif
+
+#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
+
+/* ----------------------------------- 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 */
+
+typedef int pid_t;
+#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 int getpagesize(); /* in port.cc */
+
+/* ----------------------------------- OTHER */
+
+inline void srandom(unsigned int seed) { srand(seed); }
+inline long random(void) { return rand(); }
+inline unsigned int sleep(unsigned int seconds) {
+ Sleep(seconds * 1000);
+ return 0;
+}
+
+// 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
+
+inline int nanosleep(const struct timespec *req, struct timespec *rem) {
+ Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
+ return 0;
+}
+
+#ifndef __MINGW32__
+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);
+}
+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();
+
+// ----------------------------------- BUILD-SPECIFIC
+
+/*
+ * 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
+
+
+#endif /* _WIN32 */
+
+#undef inline
+#undef EXTERN_C
+
+#endif /* GOOGLE_BASE_WINDOWS_H_ */
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc
new file mode 100644
index 00000000000..b27a95bcb6f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc
@@ -0,0 +1,684 @@
+/* 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, <replacement_function>
+// 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<void*>(&relative_offset),
+ reinterpret_cast<void*>(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<void*>(&relative_offset),
+ reinterpret_cast<void*>(target + 1), 1);
+ new_target = target + 2 + relative_offset;
+ } else if (target[0] == ASM_JMP32ABS_0 &&
+ target[1] == ASM_JMP32ABS_1) {
+ // 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<void*>(&target_offset),
+ reinterpret_cast<void*>(target + 2), 4);
+ new_target_v = reinterpret_cast<void**>(target + target_offset + 6);
+ } else {
+ SIDESTEP_ASSERT(sizeof(new_target) == 4);
+ memcpy(&new_target_v, reinterpret_cast<void*>(target + 2), 4);
+ }
+ new_target = reinterpret_cast<unsigned char*>(*new_target_v);
+ } 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<void*>(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<void*>(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<void*>(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<unsigned char*>(target_function);
+ target = reinterpret_cast<unsigned char*>(
+ ResolveTargetImpl(
+ target, reinterpret_cast<unsigned char*>(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<void*>(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<unsigned char*>(
+ 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 orignal 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<void*>(target + target_bytes),
+ reinterpret_cast<void*>(reinterpret_cast<unsigned char*>(
+ 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<unsigned char*>(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<void*>(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<PreamblePage*>(AllocPageNear(target));
+ SIDESTEP_ASSERT(preamble_page != NULL && "Could not allocate page!");
+ void** pp = &preamble_page->free_;
+ unsigned char* ptr = reinterpret_cast<unsigned char*>(preamble_page) +
+ MAX_PREAMBLE_STUB_SIZE;
+ unsigned char* limit = reinterpret_cast<unsigned char*>(preamble_page) +
+ pagesize_;
+ while (ptr < limit) {
+ *pp = ptr;
+ pp = reinterpret_cast<void**>(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<unsigned char*>(preamble_page->free_);
+ preamble_page->free_ = *(reinterpret_cast<void**>(preamble_page->free_));
+ return ret;
+}
+
+void PreamblePatcher::FreePreambleBlock(unsigned char* block) {
+ SIDESTEP_ASSERT(block != NULL);
+ SIDESTEP_ASSERT(granularity_ != 0);
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(block);
+ ptr -= ptr & (granularity_ - 1);
+ PreamblePage* preamble_page = reinterpret_cast<PreamblePage*>(ptr);
+ SIDESTEP_ASSERT(preamble_page->magic_ == kPreamblePageMagic);
+ *(reinterpret_cast<void**>(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<unsigned char*>(
+ 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 <= NULL) {
+ // Less than 0
+ break;
+ }
+ pv = ::VirtualAlloc(reinterpret_cast<void*>(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<unsigned char*>(
+ (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<void*>(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::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) {
+ unsigned char* original_jump_dest = (source + 2) + 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<void*>(target),
+ reinterpret_cast<void*>(&jmpcode), 2);
+ memcpy(reinterpret_cast<void*>(target + 2),
+ reinterpret_cast<void*>(&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<unsigned char *>(
+ reinterpret_cast<__int64>(source + instruction_size) +
+ *(reinterpret_cast<int*>(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<unsigned char>(
+ fixup_jump_offset) << 8) | (0x70 | (source[1] & 0xf));
+ memcpy(reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(&jmpcode),
+ 2);
+ } else {
+ target[0] = ASM_JMP8REL;
+ target[1] = static_cast<unsigned char>(fixup_jump_offset);
+ }
+ }
+ } else {
+ *target_bytes = instruction_size;
+ if (target_size > *target_bytes) {
+ memcpy(reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(source),
+ jmp_offset_in_instruction);
+ memcpy(reinterpret_cast<void*>(target + jmp_offset_in_instruction),
+ reinterpret_cast<void*>(&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 <offset>
+ unsigned char* original_mov_dest = reinterpret_cast<unsigned char*>(
+ reinterpret_cast<__int64>(source + instruction_size) +
+ *(reinterpret_cast<int*>(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<void*>(target),
+ reinterpret_cast<void*>(source),
+ mov_offset_in_instruction);
+ memcpy(reinterpret_cast<void*>(target + mov_offset_in_instruction),
+ reinterpret_cast<void*>(&fixup_mov_offset),
+ 4);
+ }
+ return SIDESTEP_SUCCESS;
+}
+
+}; // namespace sidestep
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.h b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.h
new file mode 100644
index 00000000000..4fdb7d00165
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher.h
@@ -0,0 +1,611 @@
+/* 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 <windows.h>
+
+// 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 <class T>
+ 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 <class T>
+ 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 <class T>
+ 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);
+
+ // 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);
+
+ // 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/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc
new file mode 100644
index 00000000000..41ab551cc99
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc
@@ -0,0 +1,367 @@
+/* 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 <windows.h>
+#include <tchar.h>
+
+// Turning off all optimizations for this file, since the official build's
+// "Whole program optimization" seems to cause the TestPatchUsingDynamicStub
+// test to crash with an access violation. We debugged this and found
+// that the optimized access a register that is changed by a call to the hook
+// function.
+#pragma optimize("", off)
+
+// A convenience macro to avoid a lot of casting in the tests.
+// I tried to make this a templated function, but windows complained:
+// error C2782: 'sidestep::SideStepError `anonymous-namespace'::Unpatch(T,T,T *)' : template parameter 'T' is ambiguous
+// could be 'int (int)'
+// or 'int (__cdecl *)(int)'
+// My life isn't long enough to try to figure out how to fix this.
+#define UNPATCH(target_function, replacement_function, original_function_stub) \
+ sidestep::PreamblePatcher::Unpatch((void*)(target_function), \
+ (void*)(replacement_function), \
+ (void*)(original_function))
+
+namespace {
+
+// Function for testing - this is what we patch
+//
+// NOTE: Because of the way the compiler optimizes this function in
+// release builds, we need to use a different input value every time we
+// call it within a function, otherwise the compiler will just reuse the
+// last calculated incremented value.
+int __declspec(noinline) IncrementNumber(int i) {
+#ifdef _M_X64
+ __int64 i2 = i + 1;
+ return (int) i2;
+#else
+ return i + 1;
+#endif
+}
+
+extern "C" int TooShortFunction(int);
+
+extern "C" int JumpShortCondFunction(int);
+
+extern "C" int JumpNearCondFunction(int);
+
+extern "C" int JumpAbsoluteFunction(int);
+
+extern "C" int CallNearRelativeFunction(int);
+
+typedef int (*IncrementingFunc)(int);
+IncrementingFunc original_function = NULL;
+
+int HookIncrementNumber(int i) {
+ SIDESTEP_ASSERT(original_function != NULL);
+ int incremented_once = original_function(i);
+ return incremented_once + 1;
+}
+
+// For the AutoTestingHook test, we can't use original_function, because
+// all that is encapsulated.
+// This function "increments" by 10, just to set it apart from the other
+// functions.
+int __declspec(noinline) AutoHookIncrementNumber(int i) {
+ return i + 10;
+}
+
+}; // namespace
+
+namespace sidestep {
+
+bool TestDisassembler() {
+ unsigned int instruction_size = 0;
+ sidestep::MiniDisassembler disassembler;
+ void * target = reinterpret_cast<unsigned char *>(IncrementNumber);
+ void * new_target = PreamblePatcher::ResolveTarget(target);
+ if (target != new_target)
+ target = new_target;
+
+ while (1) {
+ sidestep::InstructionType instructionType = disassembler.Disassemble(
+ reinterpret_cast<unsigned char *>(target) + instruction_size,
+ instruction_size);
+ if (sidestep::IT_RETURN == instructionType) {
+ return true;
+ }
+ }
+}
+
+bool TestPatchWithLongJump() {
+ original_function = NULL;
+ void *p = ::VirtualAlloc(reinterpret_cast<void *>(0x0000020000000000), 4096,
+ MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ SIDESTEP_EXPECT_TRUE(p != NULL);
+ memset(p, 0xcc, 4096);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ (IncrementingFunc) p,
+ &original_function));
+ SIDESTEP_ASSERT((*original_function)(1) == 2);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ (IncrementingFunc)p,
+ original_function));
+ ::VirtualFree(p, 0, MEM_RELEASE);
+ return true;
+}
+
+bool TestPatchWithPreambleShortCondJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpShortCondFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpShortCondFunction,
+ (void*)HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleNearRelativeCondJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpNearCondFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpNearCondFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleAbsoluteJump() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(JumpAbsoluteFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(JumpAbsoluteFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchWithPreambleNearRelativeCall() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(
+ CallNearRelativeFunction,
+ HookIncrementNumber,
+ &original_function));
+ (*original_function)(0);
+ (*original_function)(1);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(CallNearRelativeFunction,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool TestPatchUsingDynamicStub() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &original_function));
+ SIDESTEP_EXPECT_TRUE(original_function);
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 4);
+ SIDESTEP_EXPECT_TRUE(original_function(3) == 4);
+
+ // Clearbox test to see that the function has been patched.
+ sidestep::MiniDisassembler disassembler;
+ unsigned int instruction_size = 0;
+ SIDESTEP_EXPECT_TRUE(sidestep::IT_JUMP == disassembler.Disassemble(
+ reinterpret_cast<unsigned char*>(IncrementNumber),
+ instruction_size));
+
+ // Since we patched IncrementNumber, its first statement is a
+ // jmp to the hook function. So verify that we now can not patch
+ // IncrementNumber because it starts with a jump.
+#if 0
+ IncrementingFunc dummy = NULL;
+ // TODO(joi@chromium.org): restore this test once flag is added to
+ // disable JMP following
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_JUMP_INSTRUCTION ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &dummy));
+
+ // This test disabled because code in preamble_patcher_with_stub.cc
+ // asserts before returning the error code -- so there is no way
+ // to get an error code here, in debug build.
+ dummy = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_FUNCTION_TOO_SMALL ==
+ sidestep::PreamblePatcher::Patch(TooShortFunction,
+ HookIncrementNumber,
+ &dummy));
+#endif
+
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ HookIncrementNumber,
+ original_function));
+ return true;
+}
+
+bool PatchThenUnpatch() {
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(IncrementNumber,
+ HookIncrementNumber,
+ &original_function));
+ SIDESTEP_EXPECT_TRUE(original_function);
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 3);
+ SIDESTEP_EXPECT_TRUE(original_function(2) == 3);
+
+ SIDESTEP_EXPECT_TRUE(sidestep::SIDESTEP_SUCCESS ==
+ UNPATCH(IncrementNumber,
+ HookIncrementNumber,
+ original_function));
+ original_function = NULL;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool AutoTestingHookTest() {
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+
+ // Inner scope, so we can test what happens when the AutoTestingHook
+ // goes out of scope
+ {
+ AutoTestingHook hook = MakeTestingHook(IncrementNumber,
+ AutoHookIncrementNumber);
+ (void) hook;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
+ }
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool AutoTestingHookInContainerTest() {
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(1) == 2);
+
+ // Inner scope, so we can test what happens when the AutoTestingHook
+ // goes out of scope
+ {
+ AutoTestingHookHolder hook(MakeTestingHookHolder(IncrementNumber,
+ AutoHookIncrementNumber));
+ (void) hook;
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(2) == 12);
+ }
+ SIDESTEP_EXPECT_TRUE(IncrementNumber(3) == 4);
+
+ return true;
+}
+
+bool TestPreambleAllocation() {
+ __int64 diff = 0;
+ void* p1 = reinterpret_cast<void*>(0x110000000);
+ void* p2 = reinterpret_cast<void*>(0x810000000);
+ unsigned char* b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
+ SIDESTEP_EXPECT_TRUE(b1 != NULL);
+ diff = reinterpret_cast<__int64>(p1) - reinterpret_cast<__int64>(b1);
+ // Ensure blocks are within 2GB
+ SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
+ unsigned char* b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
+ SIDESTEP_EXPECT_TRUE(b2 != NULL);
+ diff = reinterpret_cast<__int64>(p2) - reinterpret_cast<__int64>(b2);
+ SIDESTEP_EXPECT_TRUE(diff <= INT_MAX && diff >= INT_MIN);
+
+ // Ensure we're reusing free blocks
+ unsigned char* b3 = b1;
+ unsigned char* b4 = b2;
+ PreamblePatcher::FreePreambleBlock(b1);
+ PreamblePatcher::FreePreambleBlock(b2);
+ b1 = PreamblePatcher::AllocPreambleBlockNear(p1);
+ SIDESTEP_EXPECT_TRUE(b1 == b3);
+ b2 = PreamblePatcher::AllocPreambleBlockNear(p2);
+ SIDESTEP_EXPECT_TRUE(b2 == b4);
+ PreamblePatcher::FreePreambleBlock(b1);
+ PreamblePatcher::FreePreambleBlock(b2);
+
+ return true;
+}
+
+bool UnitTests() {
+ return TestPatchWithPreambleNearRelativeCall() &&
+ TestPatchWithPreambleAbsoluteJump() &&
+ TestPatchWithPreambleNearRelativeCondJump() &&
+ TestPatchWithPreambleShortCondJump() &&
+ TestDisassembler() && TestPatchWithLongJump() &&
+ TestPatchUsingDynamicStub() && PatchThenUnpatch() &&
+ AutoTestingHookTest() && AutoTestingHookInContainerTest() &&
+ TestPreambleAllocation();
+}
+
+}; // namespace sidestep
+
+int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (size == 0) // not even room for a \0?
+ return -1; // not what C99 says to do, but what windows does
+ str[size-1] = '\0';
+ return _vsnprintf(str, size-1, format, ap);
+}
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ bool ret = sidestep::UnitTests();
+ printf("%s\n", ret ? "PASS" : "FAIL");
+ return ret ? 0 : -1;
+}
+
+#pragma optimize("", on)
diff --git a/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc
new file mode 100644
index 00000000000..b0dc393d975
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc
@@ -0,0 +1,296 @@
+/* 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<unsigned char*>(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>
+ //
+ // trampoline:
+ // nop
+ // mov rax, <replacement_function>
+ // 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 (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<void*>(preamble_stub + stub_bytes),
+ reinterpret_cast<void*>(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<unsigned char*>(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<void*>(preamble_stub + stub_bytes + 1),
+ reinterpret_cast<void*>(&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<void*>(preamble_stub + trampoline_pos + 3),
+ reinterpret_cast<void*>(&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<unsigned char*>(replacement_function) -
+ reinterpret_cast<unsigned char*>(target) - 5;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ // complete the jmp instruction
+ memcpy(reinterpret_cast<void*>(target + 1),
+ reinterpret_cast<void*>(&offset_to_replacement_function), 4);
+
+ // Set any remaining bytes that were moved to the preamble-stub to INT3 so
+ // as not to cause confusion (otherwise you might see some strange
+ // instructions if you look at the disassembly, or even invalid
+ // instructions). Also, by doing this, we will break into the debugger if
+ // some code calls into this portion of the code. If this happens, it
+ // means that this function cannot be patched using this patcher without
+ // further thought.
+ if (preamble_bytes > kRequiredTargetPatchBytes) {
+ memset(reinterpret_cast<void*>(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/chromium/third_party/tcmalloc/vendor/src/windows/shortproc.asm b/chromium/third_party/tcmalloc/vendor/src/windows/shortproc.asm
new file mode 100644
index 00000000000..7e8e3d78395
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/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/chromium/third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
new file mode 100644
index 00000000000..a4ffae47daf
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="addr2line-pdb"
+ ProjectGUID="{81CA712E-90B8-4AE5-9E89-5B436578D6DA}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dbghelp.lib"
+ OutputFile="$(OutDir)/addr2line-pdb.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/addr2line-pdb.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dbghelp.lib"
+ OutputFile="$(OutDir)/addr2line-pdb.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\windows\addr2line-pdb.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
new file mode 100644
index 00000000000..d31836ffba8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="addressmap_unittest"
+ ProjectGUID="{32EECEB6-7D18-477E-BC7A-30CE98457A88}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/addressmap_unittest.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/addressmap_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/addressmap_unittest.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\addressmap_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\addressmap-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-macosx.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_linux-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_posix-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\cycleclock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj
new file mode 100644
index 00000000000..8e852533315
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="frag_unittest"
+ ProjectGUID="{24754725-DE0D-4214-8979-324247AAD78E}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/frag_unittest.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/frag_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/frag_unittest.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\frag_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
new file mode 100644
index 00000000000..f71a6891550
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
@@ -0,0 +1,785 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="libtcmalloc_minimal"
+ ProjectGUID="{55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBTCMALLOC_MINIMAL_EXPORTS"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/libtcmalloc_minimal-debug.dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/libtcmalloc_minimal.pdb"
+ SubSystem="2"
+ ImportLibrary="$(OutDir)/libtcmalloc_minimal-debug.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBTCMALLOC_MINIMAL_EXPORTS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/libtcmalloc_minimal.dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(OutDir)/libtcmalloc_minimal.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\central_freelist.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\heap-profile-table.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\symbolize.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\ia32_modrm_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\ia32_opcode_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\common.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\internal_logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_extension.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\memory_region_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\sampler.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\patch_functions.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher_with_stub.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\raw_printer.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\span.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stack_trace_table.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\static_vars.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\thread_cache.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\addressmap-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\central_freelist.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\googleinit.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\heap-checker.h">
+ </File>
+ <File
+ RelativePath="..\..\src\heap-profile-table.h">
+ </File>
+ <File
+ RelativePath="..\..\src\symbolize.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\heap-profiler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\common.h">
+ </File>
+ <File
+ RelativePath="..\..\src\internal_logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\linked_list.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-macosx.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_linux-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_posix-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_extension.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_hook.h">
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\memory_region_map.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler_types.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\mutex.h">
+ </File>
+ <File
+ RelativePath="..\..\src\packed-cache-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap_allocator.h">
+ </File>
+ <File
+ RelativePath="..\..\src\pagemap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\profiler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\raw_printer.h">
+ </File>
+ <File
+ RelativePath="..\..\src\sampler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\span.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\stacktrace.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace_config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stack_trace_table.h">
+ </File>
+ <File
+ RelativePath="..\..\src\static_vars.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\stl_allocator.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.h">
+ </File>
+ <File
+ RelativePath="..\..\src\system-alloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tcmalloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\thread_annotations.h">
+ </File>
+ <File
+ RelativePath="..\..\src\thread_cache.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
new file mode 100644
index 00000000000..bee8133e32a
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
@@ -0,0 +1,373 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="low_level_alloc_unittest"
+ ProjectGUID="{A765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/low_level_alloc_unittest.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/low_level_alloc_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/low_level_alloc_unittest.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\low_level_alloc_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-macosx.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_linux-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_posix-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\cycleclock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_hook.h">
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace_win32-inl.h.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\stacktrace.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\stacktrace_config.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
new file mode 100644
index 00000000000..f56323619e6
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="malloc_extension_test"
+ ProjectGUID="{3765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/malloc_extension_test.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/malloc_extension_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/malloc_extension_test.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{3FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\malloc_extension_test.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{33995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\gperftools\malloc_extension.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_extension_c.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj
new file mode 100644
index 00000000000..701a8cbc0fd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="markidle_unittest"
+ ProjectGUID="{4AF7E21D-9D0A-410C-A7DB-7D21DA5166C0}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/markidle_unittest.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/markidle_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/markidle_unittest.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\markidle_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj
new file mode 100644
index 00000000000..5982e3c6d2f
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="nm-pdb"
+ ProjectGUID="{3A559C75-FD26-4300-B86B-165FD43EE1CE}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dbghelp.lib"
+ OutputFile="$(OutDir)/nm-pdb.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/nm-pdb.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dbghelp.lib"
+ OutputFile="$(OutDir)/nm-pdb.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\windows\nm-pdb.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj
new file mode 100644
index 00000000000..387746c7fa7
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="packed-cache_test"
+ ProjectGUID="{605D3CED-B530-424E-B7D2-2A31F14FD570}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/packed-cache_test.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/packed-cache_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/packed-cache_test.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\packed-cache_test.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-macosx.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_linux-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_posix-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\cycleclock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.h">
+ </File>
+ <File
+ RelativePath="..\..\src\packed-cache-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj
new file mode 100644
index 00000000000..6159ca6e11b
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="page_heap_test"
+ ProjectGUID="{9765198D-5305-4AB0-9A21-A0CD8201EB2B}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/page_heap_test.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/page_heap_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/page_heap_test.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{9FC737F1-C7A5-4376-A066-2A32D752A2FE}">
+ <File
+ RelativePath="..\..\src\tests\page_heap_test.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFE}">
+ <File
+ RelativePath="..\..\src\page_heap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\common.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
new file mode 100644
index 00000000000..f3d89ffb991
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="pagemap_unittest"
+ ProjectGUID="{9765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/pagemap_unittest.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/pagemap_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/pagemap_unittest.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{9FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\pagemap_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\pagemap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj
new file mode 100644
index 00000000000..7b19efcfdbe
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="realloc_unittest"
+ ProjectGUID="{4765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/realloc_unittest.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/realloc_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/realloc_unittest.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\realloc_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{43995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj
new file mode 100644
index 00000000000..9447f01e606
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="sampler_test"
+ ProjectGUID="{B765198D-5305-4AB0-9A21-A0CD8201EB2A}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/sampler_test.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/sampler_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/sampler_test.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{BFC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\sampler_test.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{B3995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
new file mode 100644
index 00000000000..bfac5766aef
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="stack_trace_table_test"
+ ProjectGUID="{A4754725-DE0D-4214-8979-324247AAD78E}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/stack_trace_table_test.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/stack_trace_table_test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/stack_trace_table_test.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{AFC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\stack_trace_table_test.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{A3995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stack_trace_table.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
new file mode 100644
index 00000000000..cd9f00745dd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="tcmalloc_minimal_large_unittest"
+ ProjectGUID="{2D8B9599-C74C-4298-B723-6CF6077563E3}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_large_unittest.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/tcmalloc_minimal_large_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_large_unittest.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\tcmalloc_large_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
new file mode 100644
index 00000000000..47f6f74a307
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="tcmalloc_minimal_unittest"
+ ProjectGUID="{7CC73D97-C057-43A6-82EF-E6B567488D02}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_unittest.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/tcmalloc_minimal_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_unittest.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\tcmalloc_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
new file mode 100644
index 00000000000..62c076603fd
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="thread_dealloc_unittest"
+ ProjectGUID="{6CFFBD0F-09E3-4282-A711-0564451FDF74}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/thread_dealloc_unittest.exe"
+ LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/thread_dealloc_unittest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/thread_dealloc_unittest.exe"
+ LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\tests\testutil.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\thread_dealloc_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj b/chromium/third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj
new file mode 100644
index 00000000000..3b1db3248d8
--- /dev/null
+++ b/chromium/third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj
@@ -0,0 +1,884 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="tcmalloc_minimal_unittest-static"
+ ProjectGUID="{8F708DCB-7EE4-4BA0-81AA-A52A0BA73B74}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_unittest-static.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/tcmalloc_minimal_unittest-static.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/tcmalloc_minimal_unittest-static.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\src\central_freelist.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\dynamic_annotations.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\heap-profile-table.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\symbolize.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\ia32_modrm_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\ia32_opcode_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\common.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\internal_logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_extension.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\memory_region_map.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\sampler.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\patch_functions.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher_with_stub.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\raw_printer.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\span.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\stack_trace_table.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\static_vars.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\tcmalloc_unittest.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\thread_cache.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/D PERFTOOLS_DLL_DECL="
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\src\addressmap-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\basictypes.h">
+ </File>
+ <File
+ RelativePath="..\..\src\central_freelist.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\commandlineflags.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\config_for_unittests.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\googleinit.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\heap-checker.h">
+ </File>
+ <File
+ RelativePath="..\..\src\heap-profile-table.h">
+ </File>
+ <File
+ RelativePath="..\..\src\symbolize.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\heap-profiler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\common.h">
+ </File>
+ <File
+ RelativePath="..\..\src\internal_logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\linked_list.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\logging.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\low_level_alloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-arm-gcc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-linuxppc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-macosx.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_internal.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_linux-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_posix-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\spinlock_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_extension.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\malloc_hook.h">
+ </File>
+ <File
+ RelativePath="..\..\src\malloc_hook-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\memory_region_map.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\mini_disassembler_types.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\mutex.h">
+ </File>
+ <File
+ RelativePath="..\..\src\packed-cache-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\page_heap_allocator.h">
+ </File>
+ <File
+ RelativePath="..\..\src\pagemap.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\port.h">
+ </File>
+ <File
+ RelativePath="..\..\src\windows\preamble_patcher.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\profiler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\span.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\stacktrace.h">
+ </File>
+ <File
+ RelativePath="..\..\src\gperftools\stacktrace_config.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stacktrace_win32-inl.h">
+ </File>
+ <File
+ RelativePath="..\..\src\raw_printer.h">
+ </File>
+ <File
+ RelativePath="..\..\src\sampler.h">
+ </File>
+ <File
+ RelativePath="..\..\src\stack_trace_table.h">
+ </File>
+ <File
+ RelativePath="..\..\src\static_vars.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\stl_allocator.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\sysinfo.h">
+ </File>
+ <File
+ RelativePath="..\..\src\system-alloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tcmalloc.h">
+ </File>
+ <File
+ RelativePath="..\..\src\tests\testutil.h">
+ </File>
+ <File
+ RelativePath="..\..\src\base\thread_annotations.h">
+ </File>
+ <File
+ RelativePath="..\..\src\thread_cache.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>