Initialize thrd in a new FrameNode ctor
[dyninst.git] / stackwalk / src / callchecker.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "stackwalk/h/swk_errors.h"
32 #include "stackwalk/src/sw.h"
33
34 using namespace Dyninst;
35 using namespace Stackwalker;
36 using namespace std;
37
38 CallChecker::CallChecker(ProcessState * proc_) : proc(proc_) {}
39 CallChecker::~CallChecker() {}
40
41 bool CallChecker::isPrevInstrACall(Address addr, Address & target)
42 {
43     const unsigned max_call_length = 5;
44    bool result;
45    unsigned char buffer[max_call_length];
46
47    sw_printf("[%s:%u] - isPrevInstrACall on %lx\n", __FILE__, __LINE__, addr);
48    Address start = addr - max_call_length;
49    result = proc->readMem(buffer, start, max_call_length);
50    if (!result)
51    {
52       sw_printf("[%s:%u] - Address 0x%lx is not a call--unreadable\n",
53                 __FILE__, __LINE__, addr);
54       return false;
55    }
56
57    if (buffer[max_call_length - 5] == 0xe8) {
58       int32_t disp = *((int32_t *) (buffer+1));
59       target = addr + disp;
60       sw_printf("[%s:%u] - Found call encoded by %x to %lx (addr = %lx, disp = %lx)\n",
61                 __FILE__, __LINE__, (int) buffer[0], target, addr, disp);
62                 
63       return true;
64    }
65
66    target = 0x0;
67    for (unsigned i=0; i<max_call_length-1; i++)
68    {
69       if (buffer[i] != 0xff) 
70          continue;
71       int modrm_reg = buffer[i+1] >> 3 & 7;
72       if (modrm_reg != 2)
73          continue;
74
75       /**
76        * Compute the size of the x86 instruction.
77        **/
78       int modrm_mod = buffer[i+1] >> 6;
79       int modrm_rm = buffer[i+1] & 7;
80       unsigned size = 2; //Opcode + MOD/RM
81       switch (modrm_mod)
82       {
83          case 0:
84             if (modrm_rm == 5)
85                size += 4; //disp32
86             if (modrm_rm == 4)
87                size += 1; //SIB
88             break;
89          case 1:
90             size += 1; //disp8
91             if (modrm_rm == 4)
92                size += 1; //SIB
93             break;
94          case 2:
95             size += 4; //disp32
96             if (modrm_rm == 4)
97                size += 1; //SIB
98             break;
99          case 3:
100             break;
101       }
102
103       if (i + size == max_call_length)
104       {
105          sw_printf("[%s:%u] - Found call of size %d encoded by: ",
106                    __FILE__, __LINE__, size);
107          for (unsigned j=i; j<i+size; j++) {
108             sw_printf("%x ", buffer[j]);
109          }
110          sw_printf("\n");
111
112          return true;
113       }
114    }
115
116    return false;
117 }