Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 //#define _XOPEN_SOURCE 500 | 55 //#define _XOPEN_SOURCE 500 |
| 56 | 56 |
| 57 #include <string.h> // for memcmp | 57 #include <string.h> // for memcmp |
| 58 #if defined(HAVE_SYS_UCONTEXT_H) | 58 #if defined(HAVE_SYS_UCONTEXT_H) |
| 59 #include <sys/ucontext.h> | 59 #include <sys/ucontext.h> |
| 60 #elif defined(HAVE_UCONTEXT_H) | 60 #elif defined(HAVE_UCONTEXT_H) |
| 61 #include <ucontext.h> // for ucontext_t (and also mcontext_t) | 61 #include <ucontext.h> // for ucontext_t (and also mcontext_t) |
| 62 #elif defined(HAVE_CYGWIN_SIGNAL_H) | 62 #elif defined(HAVE_CYGWIN_SIGNAL_H) |
| 63 #include <cygwin/signal.h> | 63 #include <cygwin/signal.h> |
| 64 typedef ucontext ucontext_t; | 64 typedef ucontext ucontext_t; |
| 65 #elif defined(__ANDROID__) | |
| 66 #include <unwind.h> | |
| 65 #endif | 67 #endif |
| 66 | 68 |
| 67 | 69 |
| 68 // Take the example where function Foo() calls function Bar(). For | 70 // Take the example where function Foo() calls function Bar(). For |
| 69 // many architectures, Bar() is responsible for setting up and tearing | 71 // many architectures, Bar() is responsible for setting up and tearing |
| 70 // down its own stack frame. In that case, it's possible for the | 72 // down its own stack frame. In that case, it's possible for the |
| 71 // interrupt to happen when execution is in Bar(), but the stack frame | 73 // interrupt to happen when execution is in Bar(), but the stack frame |
| 72 // is not properly set up (either before it's done being set up, or | 74 // is not properly set up (either before it's done being set up, or |
| 73 // after it's been torn down but before Bar() returns). In those | 75 // after it's been torn down but before Bar() returns). In those |
| 74 // cases, the stack trace cannot see the caller function anymore. | 76 // cases, the stack trace cannot see the caller function anymore. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 102 int return_sp_offset; | 104 int return_sp_offset; |
| 103 }; | 105 }; |
| 104 | 106 |
| 105 | 107 |
| 106 // The dereferences needed to get the PC from a struct ucontext were | 108 // The dereferences needed to get the PC from a struct ucontext were |
| 107 // determined at configure time, and stored in the macro | 109 // determined at configure time, and stored in the macro |
| 108 // PC_FROM_UCONTEXT in config.h. The only thing we need to do here, | 110 // PC_FROM_UCONTEXT in config.h. The only thing we need to do here, |
| 109 // then, is to do the magic call-unrolling for systems that support it. | 111 // then, is to do the magic call-unrolling for systems that support it. |
| 110 | 112 |
| 111 // -- Special case 1: linux x86, for which we have CallUnrollInfo | 113 // -- Special case 1: linux x86, for which we have CallUnrollInfo |
| 112 #if defined(__linux) && defined(__i386) && defined(__GNUC__) | 114 #if defined(__linux) && defined(__i386) && defined(__GNUC__) |
|
Dai Mikurube (NOT FULLTIME)
2013/05/03 08:53:00
I'm not sure if we have x86 Android, but we may wa
bulach
2013/05/07 14:55:51
we do have x86, added the guard here.
| |
| 113 static const CallUnrollInfo callunrollinfo[] = { | 115 static const CallUnrollInfo callunrollinfo[] = { |
| 114 // Entry to a function: push %ebp; mov %esp,%ebp | 116 // Entry to a function: push %ebp; mov %esp,%ebp |
| 115 // Top-of-stack contains the caller IP. | 117 // Top-of-stack contains the caller IP. |
| 116 { 0, | 118 { 0, |
| 117 {0x55, 0x89, 0xe5}, 3, | 119 {0x55, 0x89, 0xe5}, 3, |
| 118 0 | 120 0 |
| 119 }, | 121 }, |
| 120 // Entry to a function, second instruction: push %ebp; mov %esp,%ebp | 122 // Entry to a function, second instruction: push %ebp; mov %esp,%ebp |
| 121 // Top-of-stack contains the old frame, caller IP is +4. | 123 // Top-of-stack contains the old frame, caller IP is +4. |
| 122 { -1, | 124 { -1, |
| 123 {0x55, 0x89, 0xe5}, 3, | 125 {0x55, 0x89, 0xe5}, 3, |
| 124 4 | 126 4 |
| 125 }, | 127 }, |
| 126 // Return from a function: RET. | 128 // Return from a function: RET. |
| 127 // Top-of-stack contains the caller IP. | 129 // Top-of-stack contains the caller IP. |
| 128 { 0, | 130 { 0, |
| 129 {0xc3}, 1, | 131 {0xc3}, 1, |
| 130 0 | 132 0 |
| 131 } | 133 } |
| 132 }; | 134 }; |
| 133 | 135 |
| 134 inline void* GetPC(const ucontext_t& signal_ucontext) { | 136 inline void* GetPC(const ucontext_t& signal_ucontext) { |
| 135 // See comment above struct CallUnrollInfo. Only try instruction | 137 // See comment above struct CallUnrollInfo. Only try instruction |
| 136 // flow matching if both eip and esp looks reasonable. | 138 // flow matching if both eip and esp looks reasonable. |
| 137 const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP]; | 139 const int eip = signal_ucontext.uc_mcontext.gregs[REG_EIP]; |
| 138 const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP]; | 140 const int esp = signal_ucontext.uc_mcontext.gregs[REG_ESP]; |
| 139 if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 && | 141 if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 && |
| 140 (esp & 0xffff0000) != 0) { | 142 (esp & 0xffff0000) != 0) { |
| 141 char* eip_char = reinterpret_cast<char*>(eip); | 143 char* eip_char = reinterpret_cast<char*>(eip); |
| 142 for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) { | 144 for (int i = 0; i < sizeof(CallUnrollInfo)/sizeof(*callunrollinfo); ++i) { |
|
Dai Mikurube (NOT FULLTIME)
2013/05/03 08:53:00
It's necessary? (Since tcmalloc is a third_party
bulach
2013/05/07 14:55:51
Done.
| |
| 143 if (!memcmp(eip_char + callunrollinfo[i].pc_offset, | 145 if (!memcmp(eip_char + callunrollinfo[i].pc_offset, |
| 144 callunrollinfo[i].ins, callunrollinfo[i].ins_size)) { | 146 callunrollinfo[i].ins, callunrollinfo[i].ins_size)) { |
| 145 // We have a match. | 147 // We have a match. |
| 146 void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset); | 148 void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset); |
| 147 return *retaddr; | 149 return *retaddr; |
| 148 } | 150 } |
| 149 } | 151 } |
| 150 } | 152 } |
| 151 return (void*)eip; | 153 return (void*)eip; |
| 152 } | 154 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 164 | 166 |
| 165 #include "base/logging.h" // for RAW_LOG | 167 #include "base/logging.h" // for RAW_LOG |
| 166 #ifndef HAVE_CYGWIN_SIGNAL_H | 168 #ifndef HAVE_CYGWIN_SIGNAL_H |
| 167 typedef int ucontext_t; | 169 typedef int ucontext_t; |
| 168 #endif | 170 #endif |
| 169 | 171 |
| 170 inline void* GetPC(const struct ucontext_t& signal_ucontext) { | 172 inline void* GetPC(const struct ucontext_t& signal_ucontext) { |
| 171 RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n"); | 173 RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n"); |
| 172 return NULL; | 174 return NULL; |
| 173 } | 175 } |
| 176 #elif defined(__ANDROID__) | |
| 174 | 177 |
| 178 typedef struct _Unwind_Context ucontext_t; | |
| 179 | |
| 180 inline void* GetPC(const ucontext_t& signal_ucontext) { | |
| 181 // Bionic doesn't export ucontext, see | |
| 182 // https://code.google.com/p/android/issues/detail?id=34784. | |
| 183 return reinterpret_cast<void*>(_Unwind_GetIP( | |
| 184 const_cast<ucontext_t*>(&signal_ucontext))); | |
| 185 } | |
| 186 #else | |
| 187 // | |
| 175 // Normal cases. If this doesn't compile, it's probably because | 188 // Normal cases. If this doesn't compile, it's probably because |
| 176 // PC_FROM_UCONTEXT is the empty string. You need to figure out | 189 // PC_FROM_UCONTEXT is the empty string. You need to figure out |
| 177 // the right value for your system, and add it to the list in | 190 // the right value for your system, and add it to the list in |
| 178 // configure.ac (or set it manually in your config.h). | 191 // configure.ac (or set it manually in your config.h). |
| 179 #else | |
| 180 inline void* GetPC(const ucontext_t& signal_ucontext) { | 192 inline void* GetPC(const ucontext_t& signal_ucontext) { |
| 181 return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h | 193 return (void*)signal_ucontext.PC_FROM_UCONTEXT; // defined in config.h |
| 182 } | 194 } |
| 183 | 195 |
| 184 #endif | 196 #endif |
| 185 | 197 |
| 186 #endif // BASE_GETPC_H_ | 198 #endif // BASE_GETPC_H_ |
| OLD | NEW |