File: analy_arm.cc

package info (click to toggle)
ht 2.0.14-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 6,296 kB
  • ctags: 17,147
  • sloc: cpp: 97,008; ansic: 16,159; sh: 3,455; lex: 226; makefile: 213; yacc: 127
file content (67 lines) | stat: -rw-r--r-- 1,944 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "analy_arm.h"
#include "analy_register.h"
#include "armdis.h"

void AnalyArmDisassembler::init(Analyser *A)
{
    disasm = new ArmDisassembler();
    AnalyDisassembler::init(A);
}

ObjectID AnalyArmDisassembler::getObjectID() const
{
    return ATOM_ANALY_ARM;
}

Address *AnalyArmDisassembler::branchAddr(OPCODE *opcode, branch_enum_t branchtype, bool examine)
{
    ArmDisInsn *insn = static_cast<ArmDisInsn *>(opcode);
    if (insn->offset != ~0u)
        return new AddressFlat32(insn->offset);
    return new InvalidAddress();
}

void AnalyArmDisassembler::examineOpcode(OPCODE *opcode)
{
    ArmDisInsn *insn = static_cast<ArmDisInsn *>(opcode);
    if (insn->offset == ~0u)
        return;

    if (insn->opstr[0] == 'b')
        return;

    AddressFlat32 addr(insn->offset);
    if (!analy->validAddress(&addr, scvalid))
        return;

    analy->data->setIntAddressType(&addr, dst_idword, 4);
    analy->addXRef(&addr, analy->addr, xrefread);
}

branch_enum_t AnalyArmDisassembler::isBranch(OPCODE *opcode)
{
    ArmDisInsn *dis_insn = static_cast<ArmDisInsn *>(opcode);
    if (dis_insn->opstr[0] != 'b')
    {
        if (strstr(dis_insn->opstr, "pc, lr") != NULL)
            return dis_insn->iscond ? br_nobranch : br_return;
        if (strstr(dis_insn->opstr, "pc}") != NULL
            && dis_insn->opstr[0] == 'l')
            return dis_insn->iscond ? br_nobranch : br_return;
        if (strstr(dis_insn->opstr, "  pc,") != NULL
            || strstr(dis_insn->opstr, "\tpc,") != NULL)
            return dis_insn->iscond ? br_jXX : br_jump;
        return br_nobranch;
    }
    if (dis_insn->opstr[1] <= ' ')
        return br_jump;
    if (dis_insn->opstr[1] == 'l' && !dis_insn->iscond)
        return br_call;
    if (dis_insn->opstr[1] == 'x' && !dis_insn->iscond)
    {
        if (strstr(dis_insn->opstr + 2, "lr") != NULL)
            return br_return;
        return br_jump;
    }
    return br_jXX;
}