16d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// -*- mode: C++ -*- 26d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 36d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Copyright (c) 2010, Google Inc. 46d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// All rights reserved. 56d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 66d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Redistribution and use in source and binary forms, with or without 76d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// modification, are permitted provided that the following conditions are 86d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// met: 96d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Redistributions of source code must retain the above copyright 116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// notice, this list of conditions and the following disclaimer. 126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Redistributions in binary form must reproduce the above 136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// copyright notice, this list of conditions and the following disclaimer 146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// in the documentation and/or other materials provided with the 156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// distribution. 166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// * Neither the name of Google Inc. nor the names of its 176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// contributors may be used to endorse or promote products derived from 186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// this software without specific prior written permission. 196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// 206d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 216d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 226d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 236d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 246d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 256d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 266d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 276d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 286d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 296d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 306d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 316d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 326d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 336d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 346d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy// cfi_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions. 356d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 366d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_ 376d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#define PROCESSOR_CFI_FRAME_INFO_INL_H_ 386d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 396d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#include <string.h> 406d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 416d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandynamespace google_breakpad { 426d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 436d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandytemplate <typename RegisterType, class RawContextType> 446d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandybool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters( 456d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy const MemoryRegion &memory, 466d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy const CFIFrameInfo &cfi_frame_info, 476d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy const RawContextType &callee_context, 486d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy int callee_validity, 496d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy RawContextType *caller_context, 506d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy int *caller_validity) const { 516d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap; 526d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ValueMap callee_registers; 536d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy ValueMap caller_registers; 546d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Just for brevity. 556d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy typename ValueMap::const_iterator caller_none = caller_registers.end(); 566d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 576d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Populate callee_registers with register values from callee_context. 586d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy for (size_t i = 0; i < map_size_; i++) { 596d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy const RegisterSet &r = register_map_[i]; 606d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (callee_validity & r.validity_flag) 616d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy callee_registers[r.name] = callee_context.*r.context_member; 626d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 636d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 646d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Apply the rules, and see what register values they yield. 656d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory, 666d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy &caller_registers)) 676d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy return false; 686d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 696d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Populate *caller_context with the values the rules placed in 706d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // caller_registers. 711cbdeae78d3d70cc5a3d8de9477b9d93b9412b71jessicag.feedback@gmail.com memset(caller_context, 0xda, sizeof(*caller_context)); 726d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy *caller_validity = 0; 736d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy for (size_t i = 0; i < map_size_; i++) { 746d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy const RegisterSet &r = register_map_[i]; 756d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy typename ValueMap::const_iterator caller_entry; 766d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 776d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Did the rules provide a value for this register by its name? 786d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_entry = caller_registers.find(r.name); 796d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (caller_entry != caller_none) { 806d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_context->*r.context_member = caller_entry->second; 816d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy *caller_validity |= r.validity_flag; 826d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy continue; 836d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 846d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 856d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Did the rules provide a value for this register under its 866d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // alternate name? 876d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (r.alternate_name) { 886d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_entry = caller_registers.find(r.alternate_name); 896d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (caller_entry != caller_none) { 906d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_context->*r.context_member = caller_entry->second; 916d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy *caller_validity |= r.validity_flag; 926d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy continue; 936d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 946d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 956d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 966d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Is this a callee-saves register? The walker assumes that these 976d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // still hold the caller's value if the CFI doesn't mention them. 986d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // 996d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Note that other frame walkers may fail to recover callee-saves 1006d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // registers; for example, the x86 "traditional" strategy only 1016d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi 1026d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // are callee-saves, too. It is not correct to blindly set the 1036d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // valid bit for all callee-saves registers, without first 1046d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // checking its validity bit in the callee. 1056d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy if (r.callee_saves && (callee_validity & r.validity_flag) != 0) { 1066d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy caller_context->*r.context_member = callee_context.*r.context_member; 1076d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy *caller_validity |= r.validity_flag; 1086d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy continue; 1096d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 1106d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1116d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy // Otherwise, the register's value is unknown. 1126d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy } 1136d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1146d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy return true; 1156d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} 1166d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1176d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy} // namespace google_breakpad 1186d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy 1196d3a825dbf5b924c2e754309b3008e462af1d8d2jimblandy#endif // PROCESSOR_CFI_FRAME_INFO_INL_H_ 120