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