/thirdparty/breakpad/processor/cfi_frame_info-inl.h

http://github.com/tomahawk-player/tomahawk · C++ Header · 119 lines · 53 code · 17 blank · 49 comment · 12 complexity · 6d16a38c2eb2e54f372cb65da56bca6a MD5 · raw file

  1. // -*- mode: C++ -*-
  2. // Copyright (c) 2010, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
  31. // cfi_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions.
  32. #ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
  33. #define PROCESSOR_CFI_FRAME_INFO_INL_H_
  34. #include <string.h>
  35. namespace google_breakpad {
  36. template <typename RegisterType, class RawContextType>
  37. bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
  38. const MemoryRegion &memory,
  39. const CFIFrameInfo &cfi_frame_info,
  40. const RawContextType &callee_context,
  41. int callee_validity,
  42. RawContextType *caller_context,
  43. int *caller_validity) const {
  44. typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
  45. ValueMap callee_registers;
  46. ValueMap caller_registers;
  47. // Just for brevity.
  48. typename ValueMap::const_iterator caller_none = caller_registers.end();
  49. // Populate callee_registers with register values from callee_context.
  50. for (size_t i = 0; i < map_size_; i++) {
  51. const RegisterSet &r = register_map_[i];
  52. if (callee_validity & r.validity_flag)
  53. callee_registers[r.name] = callee_context.*r.context_member;
  54. }
  55. // Apply the rules, and see what register values they yield.
  56. if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
  57. &caller_registers))
  58. return false;
  59. // Populate *caller_context with the values the rules placed in
  60. // caller_registers.
  61. memset(caller_context, 0xda, sizeof(*caller_context));
  62. *caller_validity = 0;
  63. for (size_t i = 0; i < map_size_; i++) {
  64. const RegisterSet &r = register_map_[i];
  65. typename ValueMap::const_iterator caller_entry;
  66. // Did the rules provide a value for this register by its name?
  67. caller_entry = caller_registers.find(r.name);
  68. if (caller_entry != caller_none) {
  69. caller_context->*r.context_member = caller_entry->second;
  70. *caller_validity |= r.validity_flag;
  71. continue;
  72. }
  73. // Did the rules provide a value for this register under its
  74. // alternate name?
  75. if (r.alternate_name) {
  76. caller_entry = caller_registers.find(r.alternate_name);
  77. if (caller_entry != caller_none) {
  78. caller_context->*r.context_member = caller_entry->second;
  79. *caller_validity |= r.validity_flag;
  80. continue;
  81. }
  82. }
  83. // Is this a callee-saves register? The walker assumes that these
  84. // still hold the caller's value if the CFI doesn't mention them.
  85. //
  86. // Note that other frame walkers may fail to recover callee-saves
  87. // registers; for example, the x86 "traditional" strategy only
  88. // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi
  89. // are callee-saves, too. It is not correct to blindly set the
  90. // valid bit for all callee-saves registers, without first
  91. // checking its validity bit in the callee.
  92. if (r.callee_saves && (callee_validity & r.validity_flag) != 0) {
  93. caller_context->*r.context_member = callee_context.*r.context_member;
  94. *caller_validity |= r.validity_flag;
  95. continue;
  96. }
  97. // Otherwise, the register's value is unknown.
  98. }
  99. return true;
  100. }
  101. } // namespace google_breakpad
  102. #endif // PROCESSOR_CFI_FRAME_INFO_INL_H_