19e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura/* libunwind - a platform-independent unwind library
23b9fd99cb78383e0ce8cd1a31e3b824a30ef965eLassi Tuura   Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY
39e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
49e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraThis file is part of libunwind.
59e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
69e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraPermission is hereby granted, free of charge, to any person obtaining
79e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraa copy of this software and associated documentation files (the
89e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura"Software"), to deal in the Software without restriction, including
99e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurawithout limitation the rights to use, copy, modify, merge, publish,
109e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuradistribute, sublicense, and/or sell copies of the Software, and to
119e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurapermit persons to whom the Software is furnished to do so, subject to
129e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuurathe following conditions:
139e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
149e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraThe above copyright notice and this permission notice shall be
159e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraincluded in all copies or substantial portions of the Software.
169e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
179e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
189e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
199e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
209e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
219e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
229e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
239e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
249e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
259e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include "unwind_i.h"
269e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura#include "ucontext_i.h"
279e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
289e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi TuuraHIDDEN void
299e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuratdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs)
309e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura{
319e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  struct cursor *c = (struct cursor *) dwarf_to_cursor (d);
329e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  unw_tdep_frame_t *f = &c->frame_info;
339e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
349e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld"
359e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n",
369e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 d->ip, d->cfa, f->frame_type,
379e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 rs->reg[DWARF_CFA_REG_COLUMN].where,
389e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 rs->reg[DWARF_CFA_REG_COLUMN].val,
399e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 rs->reg[DWARF_CFA_OFF_COLUMN].val,
409e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 DWARF_GET_LOC(d->loc[d->ret_addr_column]),
419e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 rs->reg[RBP].where, rs->reg[RBP].val, DWARF_GET_LOC(d->loc[RBP]),
429e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	 rs->reg[RSP].where, rs->reg[RSP].val, DWARF_GET_LOC(d->loc[RSP]));
439e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
449e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  /* A standard frame is defined as:
459e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      - CFA is register-relative offset off RBP or RSP;
469e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      - Return address is saved at CFA-8;
479e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      - RBP is unsaved or saved at CFA+offset, offset != -1;
489e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      - RSP is unsaved or saved at CFA+offset, offset != -1.  */
499e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  if (f->frame_type == UNW_X86_64_FRAME_OTHER
509e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
519e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && (rs->reg[DWARF_CFA_REG_COLUMN].val == RBP
529e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	  || rs->reg[DWARF_CFA_REG_COLUMN].val == RSP)
539e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && labs(rs->reg[DWARF_CFA_OFF_COLUMN].val) < (1 << 29)
549e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && DWARF_GET_LOC(d->loc[d->ret_addr_column]) == d->cfa-8
559e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && (rs->reg[RBP].where == DWARF_WHERE_UNDEF
569e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	  || rs->reg[RBP].where == DWARF_WHERE_SAME
579e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	  || (rs->reg[RBP].where == DWARF_WHERE_CFAREL
589e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      && labs(rs->reg[RBP].val) < (1 << 14)
599e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      && rs->reg[RBP].val+1 != 0))
609e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      && (rs->reg[RSP].where == DWARF_WHERE_UNDEF
619e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	  || rs->reg[RSP].where == DWARF_WHERE_SAME
629e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	  || (rs->reg[RSP].where == DWARF_WHERE_CFAREL
639e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      && labs(rs->reg[RSP].val) < (1 << 14)
649e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura	      && rs->reg[RSP].val+1 != 0)))
659e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  {
669e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    /* Save information for a standard frame. */
679e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    f->frame_type = UNW_X86_64_FRAME_STANDARD;
689e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    f->cfa_reg_rsp = (rs->reg[DWARF_CFA_REG_COLUMN].val == RSP);
699e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    f->cfa_reg_offset = rs->reg[DWARF_CFA_OFF_COLUMN].val;
709e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    if (rs->reg[RBP].where == DWARF_WHERE_CFAREL)
719e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      f->rbp_cfa_offset = rs->reg[RBP].val;
729e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    if (rs->reg[RSP].where == DWARF_WHERE_CFAREL)
739e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura      f->rsp_cfa_offset = rs->reg[RSP].val;
749e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura    Debug (4, " standard frame\n");
759e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  }
769e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
771010880548589685a27b8f63ef54a3ea78e052fcArun Sharma  /* Signal frame was detected via augmentation in tdep_fetch_frame()  */
789e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN)
799e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  {
801010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via
811010880548589685a27b8f63ef54a3ea78e052fcArun Sharma       their ucontext_t offsets.  Confirm DWARF info agrees with the
821010880548589685a27b8f63ef54a3ea78e052fcArun Sharma       offsets we expect.  */
831010880548589685a27b8f63ef54a3ea78e052fcArun Sharma
84cf2f3d3b755d3374cc2f77973339c44c18057130Arun Sharma#ifndef NDEBUG
851010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    const unw_word_t uc = c->sigcontext_addr;
861010880548589685a27b8f63ef54a3ea78e052fcArun Sharma
871010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    assert (DWARF_GET_LOC(d->loc[RIP]) - uc == UC_MCONTEXT_GREGS_RIP);
881010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    assert (DWARF_GET_LOC(d->loc[RBP]) - uc == UC_MCONTEXT_GREGS_RBP);
891010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    assert (DWARF_GET_LOC(d->loc[RSP]) - uc == UC_MCONTEXT_GREGS_RSP);
902f328202ee19a68f4fc99d2cea169407026a70edArun Sharma#endif
911010880548589685a27b8f63ef54a3ea78e052fcArun Sharma
921010880548589685a27b8f63ef54a3ea78e052fcArun Sharma    Debug (4, " sigreturn frame\n");
939e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  }
949e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura
959e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  /* PLT and guessed RBP-walked frames are handled in unw_step(). */
969e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura  else
97d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris    /* ANDROID support update. */
98d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris    {
99d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris      Debug (4, " unusual frame\n");
100d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris    }
101d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris    /* End of ANDROID update. */
1029e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura}
103