| Index: third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
|
| ===================================================================
|
| --- third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc (revision 0)
|
| +++ third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc (revision 0)
|
| @@ -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;
|
| +}
|
|
|
| Property changes on: third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
|
| ___________________________________________________________________
|
| Added: svn:mergeinfo
|
|
|
|
|