Skip to content

Commit

Permalink
New MachRegister class: stackwalk-x86, parseDwarf, POWER IAPI integra…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
wrwilliams committed Feb 23, 2010
1 parent 88945a3 commit efa87d1
Show file tree
Hide file tree
Showing 8 changed files with 931 additions and 427 deletions.
3 changes: 2 additions & 1 deletion common/make.module.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ SRCS += ../../common/src/Ident.C \
../../common/src/Node.C \
../../common/src/Graph.C \
../../common/src/Edge.C \
../../common/src/DOT.C
../../common/src/DOT.C \
../../common/src/dyn_regs.C
# ../../common/src/Dictionary.C \
# ../../common/src/vectorSet.C \

Expand Down
237 changes: 237 additions & 0 deletions common/src/dyn_regs.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/*
* Copyright (c) 1996-2009 Barton P. Miller
*
* We provide the Paradyn Parallel Performance Tools (below
* described as "Paradyn") on an AS IS basis, and do not warrant its
* validity or performance. We reserve the right to update, modify,
* or discontinue this software at any time. We shall have no
* obligation to supply such updates or modifications or any other
* form of support to you.
*
* By your use of Paradyn, you understand and agree that we (or any
* other person or entity with proprietary rights in Paradyn) are
* under no obligation to provide either maintenance services,
* update services, notices of latent defects, or correction of
* defects for Paradyn.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#define DYN_DEFINE_REGS
#include "dynutil/h/dyn_regs.h"

namespace Dyninst {

std::map<signed int, const char *> *Dyninst::MachRegister::names;

MachRegister::MachRegister() :
reg(0)
{
}

MachRegister::MachRegister(signed int r) :
reg(r)
{
}

MachRegister::MachRegister(signed int r, const char *n) :
reg(r)
{
if (!names) {
names = new std::map<signed int, const char *>();
}
(*names)[r] = n;
}

MachRegister::~MachRegister() {
}

MachRegister MachRegister::getBaseRegister() const {
switch (getArchitecture()) {
case Arch_x86:
case Arch_x86_64:
return reg & 0xffff00ff;
case Arch_ppc32:
case Arch_ppc64:
return reg;
case Arch_none:
return reg;
}
return InvalidReg;
}

Architecture MachRegister::getArchitecture() const {
return (Architecture) (reg & 0xff000000);
}

bool MachRegister::isValid() const {
return (reg != InvalidReg.reg);
}

MachRegisterVal MachRegister::getSubRegValue(const MachRegister subreg,
MachRegisterVal &orig) const
{
if (subreg.reg == reg ||
getArchitecture() == Arch_ppc32 ||
getArchitecture() == Arch_ppc64)
return orig;

assert(subreg.getBaseRegister() == getBaseRegister());
switch ((subreg.reg & 0x0000ff00) >> 8) {
case 0x0: return orig;
case 0x1: return (orig & 0xff);
case 0x2: return (orig & 0xff00) >> 8;
case 0x3: return (orig & 0xffff);
case 0xf: return (orig & 0xffffffff);
default: assert(0);
}
}

const char *MachRegister::name() const {
return (*names)[reg];
}

unsigned int MachRegister::size() const {
switch (getArchitecture())
{
case Arch_x86:
switch (reg & 0x0000ff00) {
case 0x0100: //L_REG
case 0x0200: //H_REG
return 1;
case 0x0300: //W_REG
return 2;
case 0x0000: //FULL
return 4;
default:
assert(0);
}
case Arch_x86_64:
switch (reg & 0x0000ff00) {
case 0x0100: //L_REG
case 0x0200: //H_REG
return 1;
case 0x0300: //W_REG
return 2;
case 0x0f00: //D_REG
return 4;
case 0x0000: //FULL
return 8;
default:
assert(0);
}
case Arch_ppc32: {
int reg_class = reg & 0x00ff0000;
if (reg_class == ppc32::FPR || reg_class == ppc32::FSR)
return 8;
return 4;
}
case Arch_ppc64:
return 8;
case Arch_none:
return 0;
}
return 0; //Unreachable, but disable warnings
}

bool MachRegister::operator<(const MachRegister &a) const {
return (reg < a.reg);
}

bool MachRegister::operator==(const MachRegister &a) const {
return (reg == a.reg);
}

MachRegister::operator signed int() const {
return reg;
}

signed int MachRegister::val() const {
return reg;
}


MachRegister MachRegister::getPC(Dyninst::Architecture arch)
{
switch (arch)
{
case Arch_x86:
return x86::eip;
case Arch_x86_64:
return x86_64::rip;
case Arch_ppc32:
return ppc32::pc;
case Arch_ppc64:
return ppc64::pc;
case Arch_none:
return InvalidReg;
}
return InvalidReg;
}

MachRegister MachRegister::getFramePointer(Dyninst::Architecture arch)
{
switch (arch)
{
case Arch_x86:
return x86::ebp;
case Arch_x86_64:
return x86_64::rbp;
case Arch_ppc32:
case Arch_ppc64:
return FrameBase;
case Arch_none:
return InvalidReg;
}
return InvalidReg;
}

MachRegister MachRegister::getStackPointer(Dyninst::Architecture arch)
{
switch (arch)
{
case Arch_x86:
return x86::esp;
case Arch_x86_64:
return x86_64::rsp;
case Arch_ppc32:
return ppc32::r1;
case Arch_ppc64:
return ppc64::r1;
case Arch_none:
return InvalidReg;
}
return InvalidReg;
}

bool MachRegister::isPC() const
{
return (reg == x86_64::rip || reg == x86::eip ||
reg == ppc32::pc || reg == ppc64::pc);
}

bool MachRegister::isFramePointer() const
{
return (reg == x86_64::rbp || reg == x86::ebp ||
reg == FrameBase);
}

bool MachRegister::isStackPointer() const
{
return (reg == x86_64::rsp || reg == x86::esp ||
reg == ppc32::r1 || reg == ppc64::r1);
}

}
30 changes: 12 additions & 18 deletions dyninstAPI/src/stackwalk-x86.C
Original file line number Diff line number Diff line change
Expand Up @@ -273,16 +273,13 @@ class DyninstMemRegReader : public Dyninst::SymtabAPI::MemRegReader
virtual bool GetReg(MachRegister reg, MachRegisterVal &val) {
if (proc->getAddressWidth() == 4) {
switch (reg) {
case MachRegPC:
case MachRegReturn:
case x86::ieip:
val = orig_frame->getPC();
break;
case x86::ESP:
case MachRegStackBase:
case x86::iesp:
val = orig_frame->getSP();
break;
case x86::EBP:
case MachRegFrameBase:
case x86::iebp:
val = orig_frame->getFP();
break;
default:
Expand All @@ -291,16 +288,13 @@ class DyninstMemRegReader : public Dyninst::SymtabAPI::MemRegReader
}
else {
switch (reg) {
case MachRegPC:
case MachRegReturn:
case x86_64::irip:
val = orig_frame->getPC();
break;
case x86_64::RSP:
case MachRegStackBase:
case x86_64::irsp:
val = orig_frame->getSP();
break;
case x86_64::RBP:
case MachRegFrameBase:
case x86_64::irbp:
val = orig_frame->getFP();
break;
default:
Expand Down Expand Up @@ -403,21 +397,21 @@ Frame Frame::getCallerFrame()
stackwalk_printf("%s[%d]: vsyscall data is present, analyzing\n",
FILE__, __LINE__);
bool result;
result = vsys_obj->getRegValueAtFrame(pc_, MachRegReturn,
result = vsys_obj->getRegValueAtFrame(pc_, ReturnAddr,
newPC, &reader);
if (!result) {
//Linux in inconsistent about whether we should subtract the
// vys_start before using. So we try both, stick with what works
vsys_base = getProc()->getVsyscallStart();
result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, MachRegReturn,
result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, ReturnAddr,
newPC, &reader);
}
if (!result) {
//It gets worse, sometimes the vsyscall data is just plain wrong.
//FC-9 randomized the location of the vsyscall page, but didn't update
//the debug info. We'll try the non-updated address.
vsys_base = getProc()->getVsyscallStart() - 0xffffe000;
result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, MachRegReturn,
result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, ReturnAddr,
newPC, &reader);
}
if (!result) {
Expand All @@ -427,9 +421,9 @@ Frame Frame::getCallerFrame()
}
Dyninst::MachRegister frame_reg;
if (getProc()->getAddressWidth() == 4)
frame_reg = x86::EBP;
frame_reg = x86::ebp;
else
frame_reg = x86_64::RBP;
frame_reg = x86_64::rbp;

result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, frame_reg,
newFP, &reader);
Expand All @@ -439,7 +433,7 @@ Frame Frame::getCallerFrame()
return Frame();
}

result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, MachRegFrameBase,
result = vsys_obj->getRegValueAtFrame(pc_ - vsys_base, FrameBase,
newSP, &reader);
if (!result) {
stackwalk_printf("[%s:%u] - Couldn't get stack debug info at %lx\n",
Expand Down

0 comments on commit efa87d1

Please sign in to comment.