1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "linux_shadow_stacks.h"
12 static const int kMaxShadowIndex
= 2048;
13 static const char kOverflowMessage
[] = "Shadow stack overflow\n";
17 int shadow_index
= -1;
19 void *shadow_ip_stack
[kMaxShadowIndex
];
21 void *shadow_sp_stack
[kMaxShadowIndex
];
23 enum Status
{UNINITIALIZED
= -1, DISABLED
, ENABLED
};
24 Status status
= UNINITIALIZED
;
27 if (!getenv("KEEP_SHADOW_STACKS")) {
34 void __cyg_profile_func_enter(void *this_fn
, void *call_site
) {
35 if (status
== DISABLED
) return;
36 if (status
== UNINITIALIZED
) {
38 if (status
== DISABLED
) return;
41 if (shadow_index
> kMaxShadowIndex
) {
42 // Avoid memory allocation when reporting an error.
43 write(2, kOverflowMessage
, sizeof(kOverflowMessage
));
47 // Update the shadow IP stack
48 shadow_ip_stack
[shadow_index
] = this_fn
;
49 // Update the shadow SP stack. The code for obtaining the frame address was
50 // borrowed from Google Perftools, http://code.google.com/p/google-perftools/
52 // Copyright (c) 2005, Google Inc.
53 // All rights reserved.
55 // Redistribution and use in source and binary forms, with or without
56 // modification, are permitted provided that the following conditions are
59 // * Redistributions of source code must retain the above copyright
60 // notice, this list of conditions and the following disclaimer.
61 // * Redistributions in binary form must reproduce the above
62 // copyright notice, this list of conditions and the following disclaimer
63 // in the documentation and/or other materials provided with the
65 // * Neither the name of Google Inc. nor the names of its
66 // contributors may be used to endorse or promote products derived from
67 // this software without specific prior written permission.
69 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
70 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
71 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
72 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
73 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
75 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
76 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
77 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
78 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
79 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__
82 // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8.
83 // It's always correct on llvm, and the techniques below aren't (in
84 // particular, llvm-gcc will make a copy of this_fn, so it's not in sp[2]),
85 // so we also prefer __builtin_frame_address when running under llvm.
86 sp
= reinterpret_cast<void**>(__builtin_frame_address(0));
87 #elif defined(__i386__)
88 // Stack frame format:
89 // sp[0] pointer to previous frame
90 // sp[1] caller address
91 // sp[2] first argument
93 // NOTE: This will break under llvm, since result is a copy and not in sp[2]
94 sp
= (void **)&this_fn
- 2;
95 #elif defined(__x86_64__)
97 // Move the value of the register %rbp into the local variable rbp.
98 // We need 'volatile' to prevent this instruction from getting moved
99 // around during optimization to before function prologue is done.
100 // An alternative way to achieve this
101 // would be (before this __asm__ instruction) to call Noop() defined as
102 // static void Noop() __attribute__ ((noinline)); // prevent inlining
103 // static void Noop() { asm(""); } // prevent optimizing-away
104 __asm__
volatile ("mov %%rbp, %0" : "=r" (rbp
));
105 // Arguments are passed in registers on x86-64, so we can't just
106 // offset from &result
109 # error Cannot obtain SP (possibly compiling on a non x86 architecture)
111 shadow_sp_stack
[shadow_index
] = (void*)sp
;
115 void __cyg_profile_func_exit(void *this_fn
, void *call_site
) {
116 if (status
== DISABLED
) return;
120 void *get_shadow_ip_stack(int *index
/*OUT*/) {
121 *index
= shadow_index
;
122 return shadow_ip_stack
;
125 void *get_shadow_sp_stack(int *index
/*OUT*/) {
126 *index
= shadow_index
;
127 return shadow_sp_stack
;