toolkit/crashreporter/breakpad-patches/12-bug863475.patch

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 # HG changeset patch
     2 # User Julian Seward <jseward@acm.org>
     3 # Date 1371190160 -7200
     4 #      Fri Jun 14 08:09:20 2013 +0200
     5 # Node ID e74de3db7dd27ffda8f4772f892cfb52c5c35649
     6 # Parent  4dcd4220c31068e116d88a58e5b396fbb01719dd
     7 Bug 863475 - integrate ARM EXIDX unwind parsing into Breakpad.  r=glandium,ted
     9 diff --git a/Makefile.am b/Makefile.am
    10 --- a/Makefile.am
    11 +++ b/Makefile.am
    12 @@ -428,16 +428,18 @@ src_tools_linux_dump_syms_dump_syms_SOUR
    13  	src/common/dwarf_line_to_module.cc \
    14  	src/common/language.cc \
    15  	src/common/module.cc \
    16  	src/common/stabs_reader.cc \
    17  	src/common/stabs_to_module.cc \
    18  	src/common/dwarf/bytereader.cc \
    19  	src/common/dwarf/dwarf2diehandler.cc \
    20  	src/common/dwarf/dwarf2reader.cc \
    21 +        src/common/arm_ex_reader.cc \
    22 +        src/common/arm_ex_to_module.cc \
    23  	src/common/linux/dump_symbols.cc \
    24  	src/common/linux/elf_symbols_to_module.cc \
    25  	src/common/linux/elfutils.cc \
    26  	src/common/linux/file_id.cc \
    27  	src/common/linux/linux_libc_support.cc \
    28  	src/common/linux/memory_mapped_file.cc \
    29  	src/common/linux/safe_readlink.cc \
    30  	src/tools/linux/dump_syms/dump_syms.cc
    31 @@ -1010,16 +1012,20 @@ EXTRA_DIST = \
    32  	src/client/windows/handler/exception_handler.vcproj \
    33  	src/client/windows/sender/crash_report_sender.cc \
    34  	src/client/windows/sender/crash_report_sender.h \
    35  	src/client/windows/sender/crash_report_sender.vcproj \
    36  	src/common/convert_UTF.c \
    37  	src/common/convert_UTF.h \
    38  	src/common/linux/dump_symbols.cc \
    39  	src/common/linux/dump_symbols.h \
    40 +        src/common/arm_ex_reader.cc \
    41 +        src/common/arm_ex_reader.h \
    42 +        src/common/arm_ex_to_module.cc \
    43 +        src/common/arm_ex_to_module.h \
    44  	src/common/linux/elf_symbols_to_module.cc \
    45  	src/common/linux/elf_symbols_to_module.h \
    46  	src/common/linux/elfutils.cc \
    47  	src/common/linux/elfutils.h \
    48  	src/common/linux/file_id.cc \
    49  	src/common/linux/file_id.h \
    50  	src/common/linux/guid_creator.cc \
    51  	src/common/linux/guid_creator.h \
    52 diff --git a/src/common/arm_ex_reader.cc b/src/common/arm_ex_reader.cc
    53 new file mode 100644
    54 --- /dev/null
    55 +++ b/src/common/arm_ex_reader.cc
    56 @@ -0,0 +1,502 @@
    57 +
    58 +/* libunwind - a platform-independent unwind library
    59 +   Copyright 2011 Linaro Limited
    60 +
    61 +This file is part of libunwind.
    62 +
    63 +Permission is hereby granted, free of charge, to any person obtaining
    64 +a copy of this software and associated documentation files (the
    65 +"Software"), to deal in the Software without restriction, including
    66 +without limitation the rights to use, copy, modify, merge, publish,
    67 +distribute, sublicense, and/or sell copies of the Software, and to
    68 +permit persons to whom the Software is furnished to do so, subject to
    69 +the following conditions:
    70 +
    71 +The above copyright notice and this permission notice shall be
    72 +included in all copies or substantial portions of the Software.
    73 +
    74 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    75 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    76 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    77 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    78 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    79 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    80 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
    81 +
    82 +// Copyright (c) 2010 Google Inc.
    83 +// All rights reserved.
    84 +//
    85 +// Redistribution and use in source and binary forms, with or without
    86 +// modification, are permitted provided that the following conditions are
    87 +// met:
    88 +//
    89 +//     * Redistributions of source code must retain the above copyright
    90 +// notice, this list of conditions and the following disclaimer.
    91 +//     * Redistributions in binary form must reproduce the above
    92 +// copyright notice, this list of conditions and the following disclaimer
    93 +// in the documentation and/or other materials provided with the
    94 +// distribution.
    95 +//     * Neither the name of Google Inc. nor the names of its
    96 +// contributors may be used to endorse or promote products derived from
    97 +// this software without specific prior written permission.
    98 +//
    99 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   100 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   101 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   102 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   103 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   104 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   105 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   106 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   107 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   108 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   109 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   110 +
   111 +
   112 +// Derived from libunwind, with extensive modifications.
   113 +
   114 +
   115 +#include "common/arm_ex_reader.h"
   116 +#include "common/logging.h"
   117 +
   118 +#include <assert.h>
   119 +
   120 +// This file, in conjunction with arm_ex_to_module.cc, translates
   121 +// EXIDX unwind information into the same format that Breakpad uses
   122 +// for CFI information.  Hence Breakpad's CFI unwinding abilities
   123 +// also become usable for EXIDX.
   124 +//
   125 +// See: "Exception Handling ABI for the ARM Architecture", ARM IHI 0038A
   126 +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
   127 +
   128 +// EXIDX data is presented in two parts:
   129 +//
   130 +// * an index table.  This contains two words per routine,
   131 +//   the first of which identifies the routine, and the second
   132 +//   of which is a reference to the unwind bytecode.  If the
   133 +//   bytecode is very compact -- 3 bytes or less -- it can be
   134 +//   stored directly in the second word.
   135 +//
   136 +// * an area containing the unwind bytecodes.
   137 +
   138 +// General flow is: ExceptionTableInfo::Start iterates over all
   139 +// of the index table entries (pairs).  For each entry, it:
   140 +//
   141 +// * calls ExceptionTableInfo::ExtabEntryExtract to copy the bytecode
   142 +//   out into an intermediate buffer.
   143 +
   144 +// * uses ExceptionTableInfo::ExtabEntryDecode to parse the intermediate
   145 +//   buffer.  Each bytecode instruction is bundled into a
   146 +//   arm_ex_to_module::extab_data structure, and handed to ..
   147 +//
   148 +// * .. ARMExToModule::ImproveStackFrame, which in turn hands it to
   149 +//   ARMExToModule::TranslateCmd, and that generates the pseudo-CFI
   150 +//   records that Breakpad stores.
   151 +
   152 +#define ARM_EXIDX_CANT_UNWIND 0x00000001
   153 +#define ARM_EXIDX_COMPACT     0x80000000
   154 +#define ARM_EXTBL_OP_FINISH   0xb0
   155 +#define ARM_EXIDX_TABLE_LIMIT (255*4)
   156 +
   157 +namespace arm_ex_reader {
   158 +
   159 +using arm_ex_to_module::ARM_EXIDX_CMD_FINISH;
   160 +using arm_ex_to_module::ARM_EXIDX_CMD_SUB_FROM_VSP;
   161 +using arm_ex_to_module::ARM_EXIDX_CMD_ADD_TO_VSP;
   162 +using arm_ex_to_module::ARM_EXIDX_CMD_REG_POP;
   163 +using arm_ex_to_module::ARM_EXIDX_CMD_REG_TO_SP;
   164 +using arm_ex_to_module::ARM_EXIDX_CMD_VFP_POP;
   165 +using arm_ex_to_module::ARM_EXIDX_CMD_WREG_POP;
   166 +using arm_ex_to_module::ARM_EXIDX_CMD_WCGR_POP;
   167 +using arm_ex_to_module::ARM_EXIDX_CMD_RESERVED;
   168 +using arm_ex_to_module::ARM_EXIDX_CMD_REFUSED;
   169 +using arm_ex_to_module::exidx_entry;
   170 +using arm_ex_to_module::ARM_EXIDX_VFP_SHIFT_16;
   171 +using arm_ex_to_module::ARM_EXIDX_VFP_FSTMD;
   172 +using google_breakpad::MemoryRange;
   173 +
   174 +
   175 +static void* Prel31ToAddr(const void* addr) 
   176 +{
   177 +  uint32_t offset32 = *reinterpret_cast<const uint32_t*>(addr);
   178 +  // sign extend offset32[30:0] to 64 bits -- copy bit 30 to positions
   179 +  // 63:31 inclusive.
   180 +  uint64_t offset64 = offset32;
   181 +  if (offset64 & (1ULL << 30))
   182 +    offset64 |= 0xFFFFFFFF80000000ULL;
   183 +  else
   184 +    offset64 &= 0x000000007FFFFFFFULL;
   185 +  return ((char*)addr) + (uintptr_t)offset64;
   186 +}
   187 +
   188 +
   189 +// Extract unwind bytecode for the function denoted by |entry| into |buf|,
   190 +// and return the number of bytes of |buf| written, along with a code
   191 +// indicating the outcome.
   192 +
   193 +ExceptionTableInfo::ExExtractResult
   194 +ExceptionTableInfo::ExtabEntryExtract(const struct exidx_entry* entry,
   195 +                                      uint8_t* buf, size_t buf_size,
   196 +                                      /*OUT*/size_t* buf_used)
   197 +{
   198 +  MemoryRange mr_out(buf, buf_size);
   199 +
   200 +  *buf_used = 0;
   201 +
   202 +# define PUT_BUF_U8(_byte) \
   203 +  do { if (!mr_out.Covers(*buf_used, 1)) return ExOutBufOverflow; \
   204 +       buf[(*buf_used)++] = (_byte); } while (0)
   205 +
   206 +# define GET_EX_U32(_lval, _addr, _sec_mr) \
   207 +  do { if (!(_sec_mr).Covers(reinterpret_cast<const uint8_t*>(_addr) \
   208 +                             - (_sec_mr).data(), 4)) \
   209 +         return ExInBufOverflow; \
   210 +       (_lval) = *(reinterpret_cast<const uint32_t*>(_addr)); } while (0)
   211 +
   212 +# define GET_EXIDX_U32(_lval, _addr) \
   213 +            GET_EX_U32(_lval, _addr, mr_exidx_)
   214 +# define GET_EXTAB_U32(_lval, _addr) \
   215 +            GET_EX_U32(_lval, _addr, mr_extab_)
   216 +
   217 +  uint32_t data;
   218 +  GET_EXIDX_U32(data, &entry->data);
   219 +
   220 +  // A function can be marked CANT_UNWIND if (eg) it is known to be
   221 +  // at the bottom of the stack.
   222 +  if (data == ARM_EXIDX_CANT_UNWIND)
   223 +    return ExCantUnwind;
   224 +
   225 +  uint32_t  pers;          // personality number
   226 +  uint32_t  extra;         // number of extra data words required
   227 +  uint32_t  extra_allowed; // number of extra data words allowed
   228 +  uint32_t* extbl_data;    // the handler entry, if not inlined
   229 +
   230 +  if (data & ARM_EXIDX_COMPACT) {
   231 +    // The handler table entry has been inlined into the index table entry.
   232 +    // In this case it can only be an ARM-defined compact model, since
   233 +    // bit 31 is 1.  Only personalities 0, 1 and 2 are defined for the
   234 +    // ARM compact model, but 1 and 2 are "Long format" and may require
   235 +    // extra data words.  Hence the allowable personalities here are:
   236 +    //   personality 0, in which case 'extra' has no meaning
   237 +    //   personality 1, with zero extra words
   238 +    //   personality 2, with zero extra words
   239 +    extbl_data = NULL;
   240 +    pers  = (data >> 24) & 0x0F;
   241 +    extra = (data >> 16) & 0xFF;
   242 +    extra_allowed = 0;
   243 +  }
   244 +  else {
   245 +    // The index table entry is a pointer to the handler entry.  Note
   246 +    // that Prel31ToAddr will read the given address, but we already
   247 +    // range-checked above.
   248 +    extbl_data = reinterpret_cast<uint32_t*>(Prel31ToAddr(&entry->data));
   249 +    GET_EXTAB_U32(data, extbl_data);
   250 +    if (!(data & ARM_EXIDX_COMPACT)) {
   251 +      // This denotes a "generic model" handler.  That will involve
   252 +      // executing arbitary machine code, which is something we
   253 +      // can't represent here; hence reject it.
   254 +      return ExCantRepresent;
   255 +    }
   256 +    // So we have a compact model representation.  Again, 3 possible
   257 +    // personalities, but this time up to 255 allowable extra words.
   258 +    pers  = (data >> 24) & 0x0F;
   259 +    extra = (data >> 16) & 0xFF;
   260 +    extra_allowed = 255;
   261 +    extbl_data++;
   262 +  }
   263 +
   264 +  // Now look at the the handler table entry.  The first word is
   265 +  // |data| and subsequent words start at |*extbl_data|.  The number
   266 +  // of extra words to use is |extra|, provided that the personality
   267 +  // allows extra words.  Even if it does, none may be available --
   268 +  // extra_allowed is the maximum number of extra words allowed. */
   269 +  if (pers == 0) {
   270 +    // "Su16" in the documentation -- 3 unwinding insn bytes
   271 +    // |extra| has no meaning here; instead that byte is an unwind-info byte
   272 +    PUT_BUF_U8(data >> 16);
   273 +    PUT_BUF_U8(data >> 8);
   274 +    PUT_BUF_U8(data);
   275 +  }
   276 +  else if ((pers == 1 || pers == 2) && extra <= extra_allowed) {
   277 +    // "Lu16" or "Lu32" respectively -- 2 unwinding insn bytes,
   278 +    // and up to 255 extra words.
   279 +    PUT_BUF_U8(data >> 8);
   280 +    PUT_BUF_U8(data);
   281 +    for (uint32_t j = 0; j < extra; j++) {
   282 +      GET_EXTAB_U32(data, extbl_data);
   283 +      extbl_data++;
   284 +      PUT_BUF_U8(data >> 24);
   285 +      PUT_BUF_U8(data >> 16);
   286 +      PUT_BUF_U8(data >> 8);
   287 +      PUT_BUF_U8(data >> 0);
   288 +    }
   289 +  }
   290 +  else {
   291 +    // The entry is invalid.
   292 +    return ExInvalid;
   293 +  }
   294 +
   295 +  // Make sure the entry is terminated with "FINISH"
   296 +  if (*buf_used > 0 && buf[(*buf_used) - 1] != ARM_EXTBL_OP_FINISH)
   297 +    PUT_BUF_U8(ARM_EXTBL_OP_FINISH);
   298 +
   299 +  return ExSuccess;
   300 +
   301 +# undef GET_EXTAB_U32
   302 +# undef GET_EXIDX_U32
   303 +# undef GET_U32
   304 +# undef PUT_BUF_U8
   305 +}
   306 +
   307 +
   308 +// Take the unwind information extracted by ExtabEntryExtract
   309 +// and parse it into frame-unwind instructions.  These are as
   310 +// specified in "Table 4, ARM-defined frame-unwinding instructions"
   311 +// in the specification document detailed in comments at the top
   312 +// of this file.
   313 +//
   314 +// This reads from |buf[0, +data_size)|.  It checks for overruns of
   315 +// the input buffer and returns a negative value if that happens, or
   316 +// for any other failure cases.  It returns zero in case of success.
   317 +int ExceptionTableInfo::ExtabEntryDecode(const uint8_t* buf, size_t buf_size)
   318 +{
   319 +  if (buf == NULL || buf_size == 0)
   320 +    return -1;
   321 +
   322 +  MemoryRange mr_in(buf, buf_size);
   323 +  const uint8_t* buf_initially = buf;
   324 +
   325 +# define GET_BUF_U8(_lval) \
   326 +  do { if (!mr_in.Covers(buf - buf_initially, 1)) return -1; \
   327 +       (_lval) = *(buf++); } while (0)
   328 +
   329 +  const uint8_t* end = buf + buf_size;
   330 +
   331 +  while (buf < end) {
   332 +    struct arm_ex_to_module::extab_data edata;
   333 +    memset(&edata, 0, sizeof(edata));
   334 +
   335 +    uint8_t op;
   336 +    GET_BUF_U8(op);
   337 +    if ((op & 0xc0) == 0x00) {
   338 +      // vsp = vsp + (xxxxxx << 2) + 4
   339 +      edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
   340 +      edata.data = (((int)op & 0x3f) << 2) + 4;
   341 +    }
   342 +    else if ((op & 0xc0) == 0x40) {
   343 +      // vsp = vsp - (xxxxxx << 2) - 4
   344 +      edata.cmd = ARM_EXIDX_CMD_SUB_FROM_VSP;
   345 +      edata.data = (((int)op & 0x3f) << 2) + 4;
   346 +    }
   347 +    else if ((op & 0xf0) == 0x80) {
   348 +      uint8_t op2;
   349 +      GET_BUF_U8(op2);
   350 +      if (op == 0x80 && op2 == 0x00) {
   351 +        // Refuse to unwind
   352 +        edata.cmd = ARM_EXIDX_CMD_REFUSED;
   353 +      } else {
   354 +        // Pop up to 12 integer registers under masks {r15-r12},{r11-r4}
   355 +        edata.cmd = ARM_EXIDX_CMD_REG_POP;
   356 +        edata.data = ((op & 0xf) << 8) | op2;
   357 +        edata.data = edata.data << 4;
   358 +      }
   359 +    }
   360 +    else if ((op & 0xf0) == 0x90) {
   361 +      if (op == 0x9d || op == 0x9f) {
   362 +        // 9d: Reserved as prefix for ARM register to register moves
   363 +        // 9f: Reserved as perfix for Intel Wireless MMX reg to reg moves
   364 +        edata.cmd = ARM_EXIDX_CMD_RESERVED;
   365 +      } else {
   366 +        // Set vsp = r[nnnn]
   367 +        edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
   368 +        edata.data = op & 0x0f;
   369 +      }
   370 +    }
   371 +    else if ((op & 0xf0) == 0xa0) {
   372 +      // Pop r4 to r[4+nnn],          or
   373 +      // Pop r4 to r[4+nnn] and r14   or
   374 +      unsigned end = (op & 0x07);
   375 +      edata.data = (1 << (end + 1)) - 1;
   376 +      edata.data = edata.data << 4;
   377 +      if (op & 0x08) edata.data |= 1 << 14;
   378 +      edata.cmd = ARM_EXIDX_CMD_REG_POP;
   379 +    }
   380 +    else if (op == ARM_EXTBL_OP_FINISH) {
   381 +      // Finish
   382 +      edata.cmd = ARM_EXIDX_CMD_FINISH;
   383 +      buf = end;
   384 +    }
   385 +    else if (op == 0xb1) {
   386 +      uint8_t op2;
   387 +      GET_BUF_U8(op2);
   388 +      if (op2 == 0 || (op2 & 0xf0)) {
   389 +        // Spare
   390 +        edata.cmd = ARM_EXIDX_CMD_RESERVED;
   391 +      } else {
   392 +        // Pop integer registers under mask {r3,r2,r1,r0}
   393 +        edata.cmd = ARM_EXIDX_CMD_REG_POP;
   394 +        edata.data = op2 & 0x0f;
   395 +      }
   396 +    }
   397 +    else if (op == 0xb2) {
   398 +      // vsp = vsp + 0x204 + (uleb128 << 2)
   399 +      uint64_t offset = 0;
   400 +      uint8_t byte, shift = 0;
   401 +      do {
   402 +        GET_BUF_U8(byte);
   403 +        offset |= (byte & 0x7f) << shift;
   404 +        shift += 7;
   405 +      } while ((byte & 0x80) && buf < end);
   406 +      edata.data = offset * 4 + 0x204;
   407 +      edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
   408 +    }
   409 +    else if (op == 0xb3 || op == 0xc8 || op == 0xc9) {
   410 +      // b3: Pop VFP regs D[ssss]    to D[ssss+cccc],    FSTMFDX-ishly
   411 +      // c8: Pop VFP regs D[16+ssss] to D[16+ssss+cccc], FSTMFDD-ishly
   412 +      // c9: Pop VFP regs D[ssss]    to D[ssss+cccc],    FSTMFDD-ishly
   413 +      edata.cmd = ARM_EXIDX_CMD_VFP_POP;
   414 +      GET_BUF_U8(edata.data);
   415 +      if (op == 0xc8) edata.data |= ARM_EXIDX_VFP_SHIFT_16;
   416 +      if (op != 0xb3) edata.data |= ARM_EXIDX_VFP_FSTMD;
   417 +    }
   418 +    else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) {
   419 +      // b8: Pop VFP regs D[8] to D[8+nnn], FSTMFDX-ishly
   420 +      // d0: Pop VFP regs D[8] to D[8+nnn], FSTMFDD-ishly
   421 +      edata.cmd = ARM_EXIDX_CMD_VFP_POP;
   422 +      edata.data = 0x80 | (op & 0x07);
   423 +      if ((op & 0xf8) == 0xd0) edata.data |= ARM_EXIDX_VFP_FSTMD;
   424 +    }
   425 +    else if (op >= 0xc0 && op <= 0xc5) {
   426 +      // Intel Wireless MMX pop wR[10]-wr[10+nnn], nnn != 6,7
   427 +      edata.cmd = ARM_EXIDX_CMD_WREG_POP;
   428 +      edata.data = 0xa0 | (op & 0x07);
   429 +    }
   430 +    else if (op == 0xc6) {
   431 +      // Intel Wireless MMX pop wR[ssss] to wR[ssss+cccc]
   432 +      edata.cmd = ARM_EXIDX_CMD_WREG_POP;
   433 +      GET_BUF_U8(edata.data);
   434 +    }
   435 +    else if (op == 0xc7) {
   436 +      uint8_t op2;
   437 +      GET_BUF_U8(op2);
   438 +      if (op2 == 0 || (op2 & 0xf0)) {
   439 +        // Spare
   440 +        edata.cmd = ARM_EXIDX_CMD_RESERVED;
   441 +      } else {
   442 +        // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
   443 +        edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
   444 +        edata.data = op2 & 0x0f;
   445 +      }
   446 +    }
   447 +    else {
   448 +      // Spare
   449 +      edata.cmd = ARM_EXIDX_CMD_RESERVED;
   450 +    }
   451 +
   452 +    int ret = handler_->ImproveStackFrame(&edata);
   453 +    if (ret < 0) return ret;
   454 +  }
   455 +  return 0;
   456 +
   457 +# undef GET_BUF_U8
   458 +}
   459 +
   460 +void ExceptionTableInfo::Start()
   461 +{
   462 +  const struct exidx_entry* start
   463 +    = reinterpret_cast<const struct exidx_entry*>(mr_exidx_.data());
   464 +  const struct exidx_entry* end
   465 +    = reinterpret_cast<const struct exidx_entry*>(mr_exidx_.data()
   466 +                                                  + mr_exidx_.length());
   467 +
   468 +  // Iterate over each of the EXIDX entries (pairs of 32-bit words).
   469 +  // These occupy the entire .exidx section.
   470 +  for (const struct exidx_entry* entry = start; entry < end; ++entry) {
   471 +
   472 +    // Figure out the code address range that this table entry is
   473 +    // associated with.
   474 +    uint32_t addr = (reinterpret_cast<char*>(Prel31ToAddr(&entry->addr))
   475 +                     - mapping_addr_ + loading_addr_) & 0x7fffffff;
   476 +    uint32_t next_addr;
   477 +    if (entry < end - 1)
   478 +      next_addr = (reinterpret_cast<char*>(Prel31ToAddr(&((entry + 1)->addr)))
   479 +                   - mapping_addr_ + loading_addr_) & 0x7fffffff;
   480 +    else {
   481 +      // This is the last EXIDX entry in the sequence, so we don't
   482 +      // have an address for the start of the next function, to limit
   483 +      // this one.  Instead use the address of the last byte of the
   484 +      // text section associated with this .exidx section, that we
   485 +      // have been given.  So as to avoid junking up the CFI unwind
   486 +      // tables with absurdly large address ranges in the case where
   487 +      // text_last_svma_ is wrong, only use the value if it is nonzero
   488 +      // and within one page of |addr|.  Otherwise assume a length of 1.
   489 +      //
   490 +      // In some cases, gcc has been observed to finish the exidx
   491 +      // section with an entry of length 1 marked CANT_UNWIND,
   492 +      // presumably exactly for the purpose of giving a definite
   493 +      // length for the last real entry, without having to look at
   494 +      // text segment boundaries.
   495 +      bool plausible = false;
   496 +      next_addr = addr + 1;
   497 +      if (text_last_svma_ != 0) {
   498 +        uint32_t maybe_next_addr = text_last_svma_ + 1;
   499 +        if (maybe_next_addr > addr && maybe_next_addr - addr <= 4096) {
   500 +          next_addr = maybe_next_addr;
   501 +          plausible = true;
   502 +        }
   503 +      }
   504 +      if (!plausible)
   505 +        BPLOG(INFO) << "ExceptionTableInfo: implausible EXIDX last entry size "
   506 +                    << (int32_t)(text_last_svma_ - addr)
   507 +                    << "; using 1 instead.";
   508 +    }
   509 +
   510 +    // Extract the unwind info into |buf|.  This might fail for
   511 +    // various reasons.  It involves reading both the .exidx and
   512 +    // .extab sections.  All accesses to those sections are
   513 +    // bounds-checked.
   514 +    uint8_t buf[ARM_EXIDX_TABLE_LIMIT];
   515 +    size_t buf_used = 0;
   516 +    ExExtractResult res = ExtabEntryExtract(entry, buf, sizeof(buf), &buf_used);
   517 +    if (res != ExSuccess) {
   518 +      // Couldn't extract the unwind info, for some reason.  Move on.
   519 +      switch (res) {
   520 +        case ExInBufOverflow:
   521 +          BPLOG(INFO) << "ExtabEntryExtract: .exidx/.extab section overrun";
   522 +          break;
   523 +        case ExOutBufOverflow:
   524 +          BPLOG(INFO) << "ExtabEntryExtract: bytecode buffer overflow";
   525 +          break;
   526 +        case ExCantUnwind:
   527 +          BPLOG(INFO) << "ExtabEntryExtract: function is marked CANT_UNWIND";
   528 +          break;
   529 +        case ExCantRepresent:
   530 +          BPLOG(INFO) << "ExtabEntryExtract: bytecode can't be represented";
   531 +          break;
   532 +        case ExInvalid:
   533 +          BPLOG(INFO) << "ExtabEntryExtract: index table entry is invalid";
   534 +          break;
   535 +        default:
   536 +          BPLOG(INFO) << "ExtabEntryExtract: unknown error: " << (int)res;
   537 +          break;
   538 +      }
   539 +      continue;
   540 +    }
   541 +
   542 +    // Finally, work through the unwind instructions in |buf| and
   543 +    // create CFI entries that Breakpad can use.  This can also fail.
   544 +    // First, add a new stack frame entry, into which ExtabEntryDecode
   545 +    // will write the CFI entries.
   546 +    handler_->AddStackFrame(addr, next_addr - addr);
   547 +    int ret = ExtabEntryDecode(buf, buf_used);
   548 +    if (ret < 0) {
   549 +      handler_->DeleteStackFrame();
   550 +      BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
   551 +      continue;
   552 +    }
   553 +    handler_->SubmitStackFrame();
   554 +
   555 +  } /* iterating over .exidx */
   556 +}
   557 +
   558 +} // arm_ex_reader
   559 diff --git a/src/common/arm_ex_reader.h b/src/common/arm_ex_reader.h
   560 new file mode 100644
   561 --- /dev/null
   562 +++ b/src/common/arm_ex_reader.h
   563 @@ -0,0 +1,115 @@
   564 +
   565 +/* libunwind - a platform-independent unwind library
   566 +   Copyright 2011 Linaro Limited
   567 +
   568 +This file is part of libunwind.
   569 +
   570 +Permission is hereby granted, free of charge, to any person obtaining
   571 +a copy of this software and associated documentation files (the
   572 +"Software"), to deal in the Software without restriction, including
   573 +without limitation the rights to use, copy, modify, merge, publish,
   574 +distribute, sublicense, and/or sell copies of the Software, and to
   575 +permit persons to whom the Software is furnished to do so, subject to
   576 +the following conditions:
   577 +
   578 +The above copyright notice and this permission notice shall be
   579 +included in all copies or substantial portions of the Software.
   580 +
   581 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   582 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   583 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   584 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   585 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   586 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   587 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
   588 +
   589 +// Copyright (c) 2010 Google Inc.
   590 +// All rights reserved.
   591 +//
   592 +// Redistribution and use in source and binary forms, with or without
   593 +// modification, are permitted provided that the following conditions are
   594 +// met:
   595 +//
   596 +//     * Redistributions of source code must retain the above copyright
   597 +// notice, this list of conditions and the following disclaimer.
   598 +//     * Redistributions in binary form must reproduce the above
   599 +// copyright notice, this list of conditions and the following disclaimer
   600 +// in the documentation and/or other materials provided with the
   601 +// distribution.
   602 +//     * Neither the name of Google Inc. nor the names of its
   603 +// contributors may be used to endorse or promote products derived from
   604 +// this software without specific prior written permission.
   605 +//
   606 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   607 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   608 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   609 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   610 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   611 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   612 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   613 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   614 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   615 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   616 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   617 +
   618 +
   619 +// Derived from libunwind, with extensive modifications.
   620 +
   621 +#ifndef COMMON_ARM_EX_READER_H__
   622 +#define COMMON_ARM_EX_READER_H__
   623 +
   624 +#include "common/arm_ex_to_module.h"
   625 +#include "common/memory_range.h"
   626 +
   627 +namespace arm_ex_reader {
   628 +
   629 +// This class is a reader for ARM unwind information
   630 +// from .ARM.exidx and .ARM.extab sections.
   631 +class ExceptionTableInfo {
   632 + public:
   633 +  ExceptionTableInfo(const char* exidx, size_t exidx_size,
   634 +                     const char* extab, size_t extab_size,
   635 +                     uint32_t text_last_svma,
   636 +                     arm_ex_to_module::ARMExToModule* handler,
   637 +                     const char* mapping_addr,
   638 +                     uint32_t loading_addr)
   639 +      : mr_exidx_(google_breakpad::MemoryRange(exidx, exidx_size)),
   640 +        mr_extab_(google_breakpad::MemoryRange(extab, extab_size)),
   641 +        text_last_svma_(text_last_svma),
   642 +        handler_(handler), mapping_addr_(mapping_addr),
   643 +        loading_addr_(loading_addr) { }
   644 +
   645 +  ~ExceptionTableInfo() { }
   646 +
   647 +  // Parses the entries in .ARM.exidx and possibly
   648 +  // in .ARM.extab tables, reports what we find to
   649 +  // arm_ex_to_module::ARMExToModule.
   650 +  void Start();
   651 +
   652 + private:
   653 +  google_breakpad::MemoryRange mr_exidx_;
   654 +  google_breakpad::MemoryRange mr_extab_;
   655 +  uint32_t text_last_svma_;
   656 +  arm_ex_to_module::ARMExToModule* handler_;
   657 +  const char* mapping_addr_;
   658 +  uint32_t loading_addr_;
   659 +
   660 +  enum ExExtractResult {
   661 +    ExSuccess,        // success
   662 +    ExInBufOverflow,  // out-of-range while reading .exidx
   663 +    ExOutBufOverflow, // output buffer is too small
   664 +    ExCantUnwind,     // this function is marked CANT_UNWIND
   665 +    ExCantRepresent,  // entry valid, but we can't represent it
   666 +    ExInvalid         // entry is invalid
   667 +  };
   668 +  ExExtractResult
   669 +    ExtabEntryExtract(const struct arm_ex_to_module::exidx_entry* entry,
   670 +                      uint8_t* buf, size_t buf_size,
   671 +                      /*OUT*/size_t* buf_used);
   672 +
   673 +  int ExtabEntryDecode(const uint8_t* buf, size_t buf_size);
   674 +};
   675 +
   676 +} // namespace arm_ex_reader
   677 +
   678 +#endif // COMMON_ARM_EX_READER_H__
   679 diff --git a/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc
   680 new file mode 100644
   681 --- /dev/null
   682 +++ b/src/common/arm_ex_to_module.cc
   683 @@ -0,0 +1,206 @@
   684 +
   685 +/* libunwind - a platform-independent unwind library
   686 +   Copyright 2011 Linaro Limited
   687 +
   688 +This file is part of libunwind.
   689 +
   690 +Permission is hereby granted, free of charge, to any person obtaining
   691 +a copy of this software and associated documentation files (the
   692 +"Software"), to deal in the Software without restriction, including
   693 +without limitation the rights to use, copy, modify, merge, publish,
   694 +distribute, sublicense, and/or sell copies of the Software, and to
   695 +permit persons to whom the Software is furnished to do so, subject to
   696 +the following conditions:
   697 +
   698 +The above copyright notice and this permission notice shall be
   699 +included in all copies or substantial portions of the Software.
   700 +
   701 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   702 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   703 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   704 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   705 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   706 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   707 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
   708 +
   709 +// Copyright (c) 2010 Google Inc.
   710 +// All rights reserved.
   711 +//
   712 +// Redistribution and use in source and binary forms, with or without
   713 +// modification, are permitted provided that the following conditions are
   714 +// met:
   715 +//
   716 +//     * Redistributions of source code must retain the above copyright
   717 +// notice, this list of conditions and the following disclaimer.
   718 +//     * Redistributions in binary form must reproduce the above
   719 +// copyright notice, this list of conditions and the following disclaimer
   720 +// in the documentation and/or other materials provided with the
   721 +// distribution.
   722 +//     * Neither the name of Google Inc. nor the names of its
   723 +// contributors may be used to endorse or promote products derived from
   724 +// this software without specific prior written permission.
   725 +//
   726 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   727 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   728 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   729 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   730 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   731 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   732 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   733 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   734 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   735 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   736 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   737 +
   738 +
   739 +// Derived from libunwind, with extensive modifications.
   740 +
   741 +#include "common/unique_string.h"
   742 +#include "common/arm_ex_to_module.h"
   743 +
   744 +#include <stdio.h>
   745 +#include <assert.h>
   746 +
   747 +// For big-picture comments on how the EXIDX reader works, 
   748 +// see arm_ex_reader.cc.
   749 +
   750 +#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
   751 +#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
   752 +#define ARM_EXBUF_END(x)   (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
   753 +
   754 +using google_breakpad::ustr__pc;
   755 +using google_breakpad::ustr__lr;
   756 +using google_breakpad::ustr__sp;
   757 +using google_breakpad::Module;
   758 +using google_breakpad::ToUniqueString;
   759 +using google_breakpad::UniqueString;
   760 +
   761 +namespace arm_ex_to_module {
   762 +
   763 +// Translate command from extab_data to command for Module.
   764 +int ARMExToModule::TranslateCmd(const struct extab_data* edata,
   765 +                                Module::StackFrameEntry* entry, string& vsp) {
   766 +  int ret = 0;
   767 +  switch (edata->cmd) {
   768 +    case ARM_EXIDX_CMD_FINISH:
   769 +      /* Copy LR to PC if there isn't currently a rule for PC in force. */
   770 +      if (entry->initial_rules.find(ustr__pc())
   771 +          == entry->initial_rules.end()) {
   772 +        if (entry->initial_rules.find(ustr__lr())
   773 +            == entry->initial_rules.end()) {
   774 +          entry->initial_rules[ustr__pc()] = Module::Expr("lr");
   775 +        } else {
   776 +          entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()];
   777 +        }
   778 +      }
   779 +      break;
   780 +    case ARM_EXIDX_CMD_SUB_FROM_VSP:
   781 +      {
   782 +        char c[16];
   783 +        sprintf(c, " %d -", edata->data);
   784 +        vsp += c;
   785 +      }
   786 +      break;
   787 +    case ARM_EXIDX_CMD_ADD_TO_VSP:
   788 +      {
   789 +        char c[16];
   790 +        sprintf(c, " %d +", edata->data);
   791 +        vsp += c;
   792 +      }
   793 +      break;
   794 +    case ARM_EXIDX_CMD_REG_POP:
   795 +      for (unsigned int i = 0; i < 16; i++) {
   796 +        if (edata->data & (1 << i)) {
   797 +          entry->initial_rules[ToUniqueString(regnames[i])]
   798 +            = Module::Expr(vsp + " ^");
   799 +          vsp += " 4 +";
   800 +        }
   801 +      }
   802 +      /* Set cfa in case the SP got popped. */
   803 +      if (edata->data & (1 << 13)) {
   804 +        Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
   805 +        // It must be a postfix expression (we don't generate anything
   806 +        // else here), so return -1 to fail out if it isn't.
   807 +        if (!vsp_expr.isExprPostfix()) {
   808 +          ret = -1;
   809 +          break;
   810 +        };
   811 +        vsp = vsp_expr.getExprPostfix();
   812 +      }
   813 +      break;
   814 +    case ARM_EXIDX_CMD_REG_TO_SP: {
   815 +      assert (edata->data < 16);
   816 +      const char* const regname = regnames[edata->data];
   817 +      const UniqueString* regname_us = ToUniqueString(regname);
   818 +      if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) {
   819 +        entry->initial_rules[ustr__sp()] = Module::Expr(regname);
   820 +      } else {
   821 +        entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us];
   822 +      }
   823 +      Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
   824 +      if (!vsp_expr.isExprPostfix()) {
   825 +        ret = -1;
   826 +        break;
   827 +      };
   828 +      vsp = vsp_expr.getExprPostfix();
   829 +      break;
   830 +    }
   831 +    case ARM_EXIDX_CMD_VFP_POP:
   832 +      /* Don't recover VFP registers, but be sure to adjust the stack
   833 +         pointer. */
   834 +      for (unsigned int i = ARM_EXBUF_START(edata->data);
   835 +           i <= ARM_EXBUF_END(edata->data); i++) {
   836 +        vsp += " 8 +";
   837 +      }
   838 +      if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
   839 +        vsp += " 4 +";
   840 +      }
   841 +      break;
   842 +    case ARM_EXIDX_CMD_WREG_POP:
   843 +      for (unsigned int i = ARM_EXBUF_START(edata->data);
   844 +           i <= ARM_EXBUF_END(edata->data); i++) {
   845 +        vsp += " 8 +";
   846 +      }
   847 +      break;
   848 +    case ARM_EXIDX_CMD_WCGR_POP:
   849 +      // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
   850 +      for (unsigned int i = 0; i < 4; i++) {
   851 +        if (edata->data & (1 << i)) {
   852 +          vsp += " 4 +";
   853 +        }
   854 +      }
   855 +      break;
   856 +    case ARM_EXIDX_CMD_REFUSED:
   857 +    case ARM_EXIDX_CMD_RESERVED:
   858 +      ret = -1;
   859 +      break;
   860 +  }
   861 +  return ret;
   862 +}
   863 +
   864 +void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
   865 +  stack_frame_entry_ = new Module::StackFrameEntry;
   866 +  stack_frame_entry_->address = addr;
   867 +  stack_frame_entry_->size = size;
   868 +  stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp");
   869 +  vsp_ = "sp";
   870 +}
   871 +
   872 +int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) {
   873 +  return TranslateCmd(edata, stack_frame_entry_, vsp_) ;
   874 +}
   875 +
   876 +void ARMExToModule::DeleteStackFrame() {
   877 +  delete stack_frame_entry_;
   878 +}
   879 +
   880 +void ARMExToModule::SubmitStackFrame() {
   881 +  // return address always winds up in pc
   882 +  stack_frame_entry_->initial_rules[ToUniqueString(kRA)]
   883 +    = stack_frame_entry_->initial_rules[ustr__pc()];
   884 +  // the final value of vsp is the new value of sp
   885 +  stack_frame_entry_->initial_rules[ustr__sp()] = vsp_;
   886 +  module_->AddStackFrameEntry(stack_frame_entry_);
   887 +}
   888 +
   889 +} // namespace arm_ex_to_module
   890 diff --git a/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h
   891 new file mode 100644
   892 --- /dev/null
   893 +++ b/src/common/arm_ex_to_module.h
   894 @@ -0,0 +1,129 @@
   895 +
   896 +/* libunwind - a platform-independent unwind library
   897 +   Copyright 2011 Linaro Limited
   898 +
   899 +This file is part of libunwind.
   900 +
   901 +Permission is hereby granted, free of charge, to any person obtaining
   902 +a copy of this software and associated documentation files (the
   903 +"Software"), to deal in the Software without restriction, including
   904 +without limitation the rights to use, copy, modify, merge, publish,
   905 +distribute, sublicense, and/or sell copies of the Software, and to
   906 +permit persons to whom the Software is furnished to do so, subject to
   907 +the following conditions:
   908 +
   909 +The above copyright notice and this permission notice shall be
   910 +included in all copies or substantial portions of the Software.
   911 +
   912 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   913 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   914 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   915 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   916 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   917 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   918 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
   919 +
   920 +// Copyright (c) 2010 Google Inc.
   921 +// All rights reserved.
   922 +//
   923 +// Redistribution and use in source and binary forms, with or without
   924 +// modification, are permitted provided that the following conditions are
   925 +// met:
   926 +//
   927 +//     * Redistributions of source code must retain the above copyright
   928 +// notice, this list of conditions and the following disclaimer.
   929 +//     * Redistributions in binary form must reproduce the above
   930 +// copyright notice, this list of conditions and the following disclaimer
   931 +// in the documentation and/or other materials provided with the
   932 +// distribution.
   933 +//     * Neither the name of Google Inc. nor the names of its
   934 +// contributors may be used to endorse or promote products derived from
   935 +// this software without specific prior written permission.
   936 +//
   937 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   938 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   939 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   940 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   941 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   942 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   943 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   944 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   945 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   946 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   947 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   948 +
   949 +
   950 +// Derived from libunwind, with extensive modifications.
   951 +
   952 +#ifndef COMMON_ARM_EX_TO_MODULE__
   953 +#define COMMON_ARM_EX_TO_MODULE__
   954 +
   955 +#include "common/module.h"
   956 +
   957 +#include <string.h>
   958 +
   959 +namespace arm_ex_to_module {
   960 +
   961 +using google_breakpad::Module;
   962 +
   963 +typedef enum extab_cmd {
   964 +  ARM_EXIDX_CMD_FINISH,
   965 +  ARM_EXIDX_CMD_SUB_FROM_VSP,
   966 +  ARM_EXIDX_CMD_ADD_TO_VSP,
   967 +  ARM_EXIDX_CMD_REG_POP,
   968 +  ARM_EXIDX_CMD_REG_TO_SP,
   969 +  ARM_EXIDX_CMD_VFP_POP,
   970 +  ARM_EXIDX_CMD_WREG_POP,
   971 +  ARM_EXIDX_CMD_WCGR_POP,
   972 +  ARM_EXIDX_CMD_RESERVED,
   973 +  ARM_EXIDX_CMD_REFUSED,
   974 +} extab_cmd_t;
   975 +
   976 +struct exidx_entry {
   977 +  uint32_t addr;
   978 +  uint32_t data;
   979 +};
   980 +
   981 +struct extab_data {
   982 +  extab_cmd_t cmd;
   983 +  uint32_t data;
   984 +};
   985 +
   986 +enum extab_cmd_flags {
   987 +  ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
   988 +  ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
   989 +};
   990 +
   991 +const string kRA = ".ra";
   992 +const string kCFA = ".cfa";
   993 +
   994 +static const char* const regnames[] = {
   995 + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
   996 + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
   997 + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
   998 + "fps", "cpsr"
   999 +};
  1001 +// Receives information from arm_ex_reader::ExceptionTableInfo
  1002 +// and adds it to the Module object
  1003 +class ARMExToModule {
  1004 + public:
  1005 +  ARMExToModule(Module* module)
  1006 +      : module_(module) { }
  1007 +  ~ARMExToModule() { }
  1008 +  void AddStackFrame(uintptr_t addr, size_t size);
  1009 +  int ImproveStackFrame(const struct extab_data* edata);
  1010 +  void DeleteStackFrame();
  1011 +  void SubmitStackFrame();
  1012 + private:
  1013 +  Module* module_;
  1014 +  Module::StackFrameEntry* stack_frame_entry_;
  1015 +  string vsp_;
  1016 +  int TranslateCmd(const struct extab_data* edata,
  1017 +                   Module::StackFrameEntry* entry,
  1018 +                   string& vsp);
  1019 +};
  1021 +} // namespace arm_ex_to_module
  1023 +#endif // COMMON_ARM_EX_TO_MODULE__
  1024 diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
  1025 --- a/src/common/linux/dump_symbols.cc
  1026 +++ b/src/common/linux/dump_symbols.cc
  1027 @@ -47,16 +47,17 @@
  1028  #include <unistd.h>
  1030  #include <iostream>
  1031  #include <set>
  1032  #include <string>
  1033  #include <utility>
  1034  #include <vector>
  1036 +#include "common/arm_ex_reader.h"
  1037  #include "common/dwarf/bytereader-inl.h"
  1038  #include "common/dwarf/dwarf2diehandler.h"
  1039  #include "common/dwarf_cfi_to_module.h"
  1040  #include "common/dwarf_cu_to_module.h"
  1041  #include "common/dwarf_line_to_module.h"
  1042  #include "common/linux/elfutils.h"
  1043  #include "common/linux/elfutils-inl.h"
  1044  #include "common/linux/elf_symbols_to_module.h"
  1045 @@ -65,16 +66,20 @@
  1046  #include "common/scoped_ptr.h"
  1047  #ifndef NO_STABS_SUPPORT
  1048  #include "common/stabs_reader.h"
  1049  #include "common/stabs_to_module.h"
  1050  #endif
  1051  #include "common/using_std_string.h"
  1052  #include "common/logging.h"
  1054 +#if defined(__ANDROID__) && !defined(SHT_ARM_EXIDX)
  1055 +# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
  1056 +#endif
  1058  // This namespace contains helper functions.
  1059  namespace {
  1061  using google_breakpad::DwarfCFIToModule;
  1062  using google_breakpad::DwarfCUToModule;
  1063  using google_breakpad::DwarfLineToModule;
  1064  using google_breakpad::ElfClass;
  1065  using google_breakpad::ElfClass32;
  1066 @@ -340,16 +345,62 @@ bool LoadDwarfCFI(const string& dwarf_fi
  1067                                                         section_name);
  1068    dwarf2reader::CallFrameInfo parser(cfi, cfi_size,
  1069                                       &byte_reader, &handler, &dwarf_reporter,
  1070                                       eh_frame);
  1071    parser.Start();
  1072    return true;
  1075 +template<typename ElfClass>
  1076 +bool LoadARMexidx(const typename ElfClass::Ehdr* elf_header,
  1077 +                  const typename ElfClass::Shdr* exidx_section,
  1078 +                  const typename ElfClass::Shdr* extab_section,
  1079 +                  uint32_t loading_addr,
  1080 +                  Module* module) {
  1081 +  // To do this properly we need to know:
  1082 +  // * the bounds of the .ARM.exidx section in the mapped image
  1083 +  // * the bounds of the .ARM.extab section in the mapped image
  1084 +  // * the vma of the last byte in the text section associated with the .exidx
  1085 +  // The first two are easy.  The third is a bit tricky.  If we can't
  1086 +  // figure out what it is, just pass in zero.
  1087 +  const char *exidx_img
  1088 +    = GetOffset<ElfClass, char>(elf_header, exidx_section->sh_offset);
  1089 +  size_t exidx_size = exidx_section->sh_size;
  1090 +  const char *extab_img
  1091 +    = GetOffset<ElfClass, char>(elf_header, extab_section->sh_offset);
  1092 +  size_t extab_size = extab_section->sh_size;
  1094 +  // The sh_link field of the exidx section gives the section number
  1095 +  // for the associated text section.
  1096 +  uint32_t exidx_text_last_svma = 0;
  1097 +  int exidx_text_sno = exidx_section->sh_link;
  1098 +  typedef typename ElfClass::Shdr Shdr;
  1099 +  // |sections| points to the section header table
  1100 +  const Shdr* sections
  1101 +    = GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
  1102 +  const int num_sections = elf_header->e_shnum;
  1103 +  if (exidx_text_sno >= 0 && exidx_text_sno < num_sections) {
  1104 +    const Shdr* exidx_text_shdr = &sections[exidx_text_sno];
  1105 +    if (exidx_text_shdr->sh_size > 0) {
  1106 +      exidx_text_last_svma
  1107 +        = exidx_text_shdr->sh_addr + exidx_text_shdr->sh_size - 1;
  1108 +    }
  1109 +  }
  1111 +  arm_ex_to_module::ARMExToModule handler(module);
  1112 +  arm_ex_reader::ExceptionTableInfo
  1113 +    parser(exidx_img, exidx_size, extab_img, extab_size, exidx_text_last_svma,
  1114 +           &handler,
  1115 +           reinterpret_cast<const char*>(elf_header),
  1116 +           loading_addr);
  1117 +  parser.Start();
  1118 +  return true;
  1119 +}
  1121  bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper,
  1122               void** elf_header) {
  1123    int obj_fd = open(obj_file.c_str(), O_RDONLY);
  1124    if (obj_fd < 0) {
  1125      fprintf(stderr, "Failed to open ELF file '%s': %s\n",
  1126              obj_file.c_str(), strerror(errno));
  1127      return false;
  1129 @@ -629,16 +680,39 @@ bool LoadSymbols(const string& obj_file,
  1130                                   eh_frame_section, true,
  1131                                   got_section, text_section, big_endian, module);
  1132        found_usable_info = found_usable_info || result;
  1133        if (result)
  1134          BPLOG(INFO) << "LoadSymbols:   read CFI from .eh_frame";
  1138 +  // ARM has special unwind tables that can be used.
  1139 +  const Shdr* arm_exidx_section =
  1140 +      FindElfSectionByName<ElfClass>(".ARM.exidx", SHT_ARM_EXIDX,
  1141 +                                     sections, names, names_end,
  1142 +                                     elf_header->e_shnum);
  1143 +  const Shdr* arm_extab_section =
  1144 +      FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS,
  1145 +                                     sections, names, names_end,
  1146 +                                     elf_header->e_shnum);
  1147 +  // Only load information from this section if there isn't a .debug_info
  1148 +  // section.
  1149 +  if (!found_debug_info_section
  1150 +      && arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
  1151 +    info->LoadedSection(".ARM.exidx");
  1152 +    info->LoadedSection(".ARM.extab");
  1153 +    bool result = LoadARMexidx<ElfClass>(elf_header,
  1154 +                                         arm_exidx_section, arm_extab_section,
  1155 +                                         loading_addr, module);
  1156 +    found_usable_info = found_usable_info || result;
  1157 +    if (result)
  1158 +      BPLOG(INFO) << "LoadSymbols:   read EXIDX from .ARM.{exidx,extab}";
  1159 +  }
  1161    if (!found_debug_info_section && symbol_data != ONLY_CFI) {
  1162      fprintf(stderr, "%s: file contains no debugging information"
  1163              " (no \".stab\" or \".debug_info\" sections)\n",
  1164              obj_file.c_str());
  1166      // Failed, but maybe there's a .gnu_debuglink section?
  1167      if (read_gnu_debug_link) {
  1168        const Shdr* gnu_debuglink_section
  1169 diff --git a/src/common/module.cc b/src/common/module.cc
  1170 --- a/src/common/module.cc
  1171 +++ b/src/common/module.cc
  1172 @@ -253,17 +253,17 @@ void Module::AssignSourceIds() {
  1174  bool Module::ReportError() {
  1175    fprintf(stderr, "error writing symbol file: %s\n",
  1176            strerror(errno));
  1177    return false;
  1180  std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) {
  1181 -  assert(!expr.invalid());
  1182 +  assert(!expr.isExprInvalid());
  1183    switch (expr.how_) {
  1184      case Module::kExprSimple:
  1185        stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " +";
  1186        break;
  1187      case Module::kExprSimpleMem:
  1188        stream << FromUniqueString(expr.ident_) << " " << expr.offset_ << " + ^";
  1189        break;
  1190      case Module::kExprPostfix:
  1191 diff --git a/src/common/module.h b/src/common/module.h
  1192 --- a/src/common/module.h
  1193 +++ b/src/common/module.h
  1194 @@ -160,17 +160,24 @@ class Module {
  1196      // Construct an invalid expression
  1197      Expr() {
  1198        postfix_ = "";
  1199        ident_ = NULL;
  1200        offset_ = 0;
  1201        how_ = kExprInvalid;
  1203 -    bool invalid() const { return how_ == kExprInvalid; }
  1204 +    bool isExprInvalid() const { return how_ == kExprInvalid; }
  1205 +    bool isExprPostfix() const { return how_ == kExprPostfix; }
  1207 +    // Return the postfix expression string.  This is only
  1208 +    // meaningful on Exprs for which isExprPostfix returns true.
  1209 +    // In all other cases it returns an empty string.
  1210 +    string getExprPostfix() const { return postfix_; }
  1212      bool operator==(const Expr& other) const {
  1213        return how_ == other.how_ &&
  1214            ident_ == other.ident_ &&
  1215            offset_ == other.offset_ &&
  1216            postfix_ == other.postfix_;
  1219      // The identifier that gives the starting value for simple expressions.
  1220 diff --git a/src/common/unique_string.h b/src/common/unique_string.h
  1221 --- a/src/common/unique_string.h
  1222 +++ b/src/common/unique_string.h
  1223 @@ -230,16 +230,37 @@ inline static const UniqueString* ustr__
  1225  // ".ra"
  1226  inline static const UniqueString* ustr__ZDra() {
  1227    static const UniqueString* us = NULL;
  1228    if (!us) us = ToUniqueString(".ra");
  1229    return us;
  1232 +// "pc"
  1233 +inline static const UniqueString* ustr__pc() {
  1234 +  static const UniqueString* us = NULL;
  1235 +  if (!us) us = ToUniqueString("pc");
  1236 +  return us;
  1237 +}
  1239 +// "lr"
  1240 +inline static const UniqueString* ustr__lr() {
  1241 +  static const UniqueString* us = NULL;
  1242 +  if (!us) us = ToUniqueString("lr");
  1243 +  return us;
  1244 +}
  1246 +// "sp"
  1247 +inline static const UniqueString* ustr__sp() {
  1248 +  static const UniqueString* us = NULL;
  1249 +  if (!us) us = ToUniqueString("sp");
  1250 +  return us;
  1251 +}
  1253  template <typename ValueType>
  1254  class UniqueStringMap
  1256   private:
  1257    static const int N_FIXED = 10;
  1259   public:
  1260    UniqueStringMap() : n_fixed_(0), n_sets_(0), n_gets_(0), n_clears_(0) {};
  1261 diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
  1262 --- a/src/processor/cfi_frame_info.cc
  1263 +++ b/src/processor/cfi_frame_info.cc
  1264 @@ -49,17 +49,17 @@ namespace google_breakpad {
  1265  #endif
  1267  template<typename V>
  1268  bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap<V> &registers,
  1269                                    const MemoryRegion &memory,
  1270                                    RegisterValueMap<V> *caller_registers) const {
  1271    // If there are not rules for both .ra and .cfa in effect at this address,
  1272    // don't use this CFI data for stack walking.
  1273 -  if (cfa_rule_.invalid() || ra_rule_.invalid())
  1274 +  if (cfa_rule_.isExprInvalid() || ra_rule_.isExprInvalid())
  1275      return false;
  1277    RegisterValueMap<V> working;
  1278    PostfixEvaluator<V> evaluator(&working, &memory);
  1280    caller_registers->clear();
  1282    // First, compute the CFA.
  1283 @@ -100,20 +100,20 @@ template bool CFIFrameInfo::FindCallerRe
  1284  template bool CFIFrameInfo::FindCallerRegs<uint64_t>(
  1285      const RegisterValueMap<uint64_t> &registers,
  1286      const MemoryRegion &memory,
  1287      RegisterValueMap<uint64_t> *caller_registers) const;
  1289  string CFIFrameInfo::Serialize() const {
  1290    std::ostringstream stream;
  1292 -  if (!cfa_rule_.invalid()) {
  1293 +  if (!cfa_rule_.isExprInvalid()) {
  1294      stream << ".cfa: " << cfa_rule_;
  1296 -  if (!ra_rule_.invalid()) {
  1297 +  if (!ra_rule_.isExprInvalid()) {
  1298      if (static_cast<std::streamoff>(stream.tellp()) != 0)
  1299        stream << " ";
  1300      stream << ".ra: " << ra_rule_;
  1303    // Visit the register rules in alphabetical order.  Because
  1304    // register_rules_ has the elements in some arbitrary order,
  1305    // get the names out into a vector, sort them, and visit in

mercurial