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 |