// -*- mode: C++ -*-

// Copyright (c) 2010, 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.

// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>

// cfi_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions.

#ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
#define PROCESSOR_CFI_FRAME_INFO_INL_H_

#include <string.h>

namespace google_breakpad {

template <typename RegisterType, class RawContextType>
bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
    const MemoryRegion &memory,
    const CFIFrameInfo &cfi_frame_info,
    const RawContextType &callee_context,
    int callee_validity,
    RawContextType *caller_context,
    int *caller_validity) const {
  typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
  ValueMap callee_registers;
  ValueMap caller_registers;
  // Just for brevity.
  typename ValueMap::const_iterator caller_none = caller_registers.end();

  // Populate callee_registers with register values from callee_context.
  for (size_t i = 0; i < map_size_; i++) {
    const RegisterSet &r = register_map_[i];
    if (callee_validity & r.validity_flag)
      callee_registers[r.name] = callee_context.*r.context_member;
  }

  // Apply the rules, and see what register values they yield.
  if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
                                                   &caller_registers))
    return false;

  // Populate *caller_context with the values the rules placed in
  // caller_registers.
  memset(caller_context, 0xda, sizeof(*caller_context));
  *caller_validity = 0;
  for (size_t i = 0; i < map_size_; i++) {
    const RegisterSet &r = register_map_[i];
    typename ValueMap::const_iterator caller_entry;

    // Did the rules provide a value for this register by its name?
    caller_entry = caller_registers.find(r.name);
    if (caller_entry != caller_none) {
      caller_context->*r.context_member = caller_entry->second;
      *caller_validity |= r.validity_flag;
      continue;
    }

    // Did the rules provide a value for this register under its
    // alternate name?
    if (r.alternate_name) {
      caller_entry = caller_registers.find(r.alternate_name);
      if (caller_entry != caller_none) {
        caller_context->*r.context_member = caller_entry->second;
        *caller_validity |= r.validity_flag;
        continue;
      }
    }

    // Is this a callee-saves register? The walker assumes that these
    // still hold the caller's value if the CFI doesn't mention them.
    //
    // Note that other frame walkers may fail to recover callee-saves
    // registers; for example, the x86 "traditional" strategy only
    // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi
    // are callee-saves, too. It is not correct to blindly set the
    // valid bit for all callee-saves registers, without first
    // checking its validity bit in the callee.
    if (r.callee_saves && (callee_validity & r.validity_flag) != 0) {
      caller_context->*r.context_member = callee_context.*r.context_member;
      *caller_validity |= r.validity_flag;
      continue;
    }

    // Otherwise, the register's value is unknown.
  }

  return true;
}

} // namespace google_breakpad

#endif // PROCESSOR_CFI_FRAME_INFO_INL_H_
