pstrace

Форк
0
/
context.c 
197 строк · 6.6 Кб
1
/*
2
 * context.cpp
3
 *
4
 *  Created on: Jan 28, 2020
5
 *      Author: nnosov
6
 */
7

8
#include <limits.h>
9
#include <dwarf.h>
10

11
#include "context.h"
12

13
#include "dwarf/dwarf_operations.h"
14
#include "arch/registers.h"
15

16

17
extern dwarf_reg_map    reg_map[];
18
extern int regnum;
19

20
pst_logger      pstlogger;  // logger for library
21
pst_allocator   allocator;  // custom allocator for PST library
22

23
static void clean_print(pst_context* ctx)
24
{
25
    ctx->buff[0] = 0;
26
    ctx->offset = 0;
27
}
28

29
static void print_stack(pst_context* ctx, int max, uint64_t next_cfa)
30
{
31
    pst_log(SEVERITY_DEBUG, "CFA = %#lX, NEXT_CFA = %#lX, SP = %#lX", ctx->cfa, next_cfa, ctx->sp);
32
    ctx->clean_print(ctx);
33
    int i = 0;
34
    if(ctx->cfa > ctx->sp) {
35
        ctx->print(ctx, "Args: ");
36
        for(; i < max && (ctx->cfa - i) > ctx->sp; ++i) {
37
            ctx->print(ctx, "#%d 0x%lX ", i, *(uint64_t*)(ctx->cfa - i));
38
        }
39
    }
40
    if((ctx->cfa - i) > next_cfa) {
41
        ctx->print(ctx, "Vars: ");
42
        for(; i < max && (ctx->cfa - i) > next_cfa; ++i) {
43
            ctx->print(ctx, "#%d 0x%lX ", i, *(uint64_t*)(ctx->cfa - i));
44
        }
45
    }
46
}
47

48
static void print_registers(pst_context* ctx, int from, int to)
49
{
50
    ctx->clean_print(ctx);
51
    for(int i = from; i < regnum && i <= to; ++i) {
52
        unw_word_t regval;
53
        if(!unw_get_reg(ctx->curr_frame, reg_map[i].regno, &regval)) {
54
            ctx->print(ctx, "%s: %#lX ", reg_map[i].regname, regval);
55
        } else {
56
            ctx->print(ctx, "%s: <undef>", reg_map[i].regname);
57
        }
58
    }
59
}
60

61
static bool print(pst_context* ctx, const char* fmt, ...)
62
{
63
    bool nret = true;
64

65
    va_list args;
66
    va_start(args, fmt);
67
    int size = sizeof(ctx->buff) - ctx->offset;
68
    int ret = vsnprintf(ctx->buff + ctx->offset, size, fmt, args);
69
    if(ret >= size || ret < 0) {
70
        nret = false;
71
    }
72
    ctx->offset += ret;
73
    va_end(args);
74

75
    return nret;
76
}
77

78
static bool print_expr_block (pst_context* ctx, Dwarf_Op *exprs, int exprlen, Dwarf_Attribute* attr)
79
{
80
    ctx->clean_print(ctx);
81
    for (int i = 0; i < exprlen; i++) {
82
        const dwarf_op_map* map = find_op_map(exprs[i].atom);
83
        if(map) {
84
            if(map->op_num >= DW_OP_breg0 && map->op_num <= DW_OP_breg16) {
85
                int32_t off = decode_sleb128((unsigned char*)&exprs[i].number);
86
                int regno = map->op_num - DW_OP_breg0;
87
                unw_word_t ptr = 0;
88
                unw_get_reg(ctx->curr_frame, regno, &ptr);
89

90
                ctx->print(ctx, "%s(*%s%s%d) reg_value: 0x%lX", map->op_name, unw_regname(regno), off >=0 ? "+" : "", off, ptr);
91
            } else if(map->op_num >= DW_OP_reg0 && map->op_num <= DW_OP_reg16) {
92
                unw_word_t value = 0;
93
                int regno = map->op_num - DW_OP_reg0;
94
                unw_get_reg(ctx->curr_frame, regno, &value);
95
                ctx->print(ctx, "%s(*%s) value: 0x%lX", map->op_name, unw_regname(regno), value);
96
            } else if(map->op_num == DW_OP_GNU_entry_value) {
97
                if(!attr) {
98
                    pst_log(SEVERITY_ERROR, "No attribute of DW_OP_GNU_entry_value provided");
99
                    return false;
100
                }
101
                uint32_t value = decode_uleb128((unsigned char*)&exprs[i].number);
102
                ctx->print(ctx, "%s(%u, ", map->op_name, value);
103
                Dwarf_Attribute attr_mem;
104
                if(!dwarf_getlocation_attr(attr, exprs, &attr_mem)) {
105
                    Dwarf_Op *expr;
106
                    size_t exprlen;
107
                    if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
108
                        ctx->print_expr(ctx, expr, exprlen, &attr_mem);
109
                        ctx->print(ctx, ") ");
110
                    } else {
111
                        pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location");
112
                        return false;
113
                    }
114
                } else {
115
                    pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression");
116
                    return false;
117
                }
118
            } else if(map->op_num == DW_OP_stack_value) {
119
                ctx->print(ctx, "%s", map->op_name);
120
            } else if(map->op_num == DW_OP_plus_uconst) {
121
                uint32_t value = decode_uleb128((unsigned char*)&exprs[i].number);
122
                ctx->print(ctx, "%s(+%u) ", map->op_name, value);
123
            } else if(map->op_num == DW_OP_bregx) {
124
                uint32_t regno = decode_uleb128((unsigned char*)&exprs[i].number);
125
                int32_t off = decode_sleb128((unsigned char*)&exprs[i].number2);
126
                unw_word_t ptr = 0;
127
                unw_get_reg(ctx->curr_frame, regno, &ptr);
128
                //ptr += off;
129
                ctx->print(ctx, "%s(%s%s%d) reg_value = 0x%lX", map->op_name, unw_regname(regno), off >= 0 ? "+" : "", off, ptr);
130
            } else if(map->op_num == DW_OP_regx) {
131
                int32_t reg = decode_sleb128((unsigned char*)&exprs[i].number);
132

133
                unw_word_t value = 0;
134
                unw_get_reg(ctx->curr_frame, reg, &value);
135

136
                ctx->print(ctx, "%s(%s) value = 0x%lX", map->op_name, unw_regname(reg), value);
137
            } else if(map->op_num == DW_OP_addr) {
138
                ctx->print(ctx, "%s value = %p", map->op_name, (void*)exprs[i].number);
139
            } else if(map->op_num == DW_OP_fbreg) {
140
                int32_t off = decode_sleb128((unsigned char*)&exprs[i].number);
141
                ctx->print(ctx, "%s(SP%s%d) ", map->op_name, off >=0 ? "+" : "", off);
142
            } else {
143
                ctx->print(ctx, "%s(0x%lX, 0x%lx) ", map->op_name, exprs[i].number, exprs[i].number2);
144
            }
145
        } else {
146
            ctx->print(ctx, "0x%hhX(0x%lX, 0x%lx)", exprs[i].atom, exprs[i].number, exprs[i].number2);
147
        }
148
    }
149

150
    return true;
151
}
152

153
void pst_context_init(pst_context* ctx, ucontext_t* hctx)
154
{
155
    // methods
156
    ctx->clean_print = clean_print;
157
    ctx->print = print;
158
    ctx->print_expr = print_expr_block;
159
    ctx->print_registers = print_registers;
160
    ctx->print_stack = print_stack;
161

162
    // fields
163
    ctx->hcontext = hctx;
164
    ctx->base_addr = 0;
165
    ctx->sp = 0;
166
    ctx->cfa = 0;
167
    ctx->curr_frame = NULL;
168
    ctx->frame = NULL;
169
    ctx->dwfl = NULL;
170
    ctx->module = NULL;
171
}
172

173
void pst_context_fini(pst_context* ctx)
174
{
175
    ctx->hcontext = NULL;
176
    ctx->clean_print(ctx);
177
    ctx->base_addr = 0;
178
    ctx->sp = 0;
179
    ctx->cfa = 0;
180
    ctx->curr_frame = NULL;
181
    ctx->frame = NULL;
182
    ctx->dwfl = NULL;
183
    ctx->module = NULL;
184
}
185

186

187
char* pst_strdup(const char* str)
188
{
189
    pst_assert(str);
190

191
    uint32_t len = strlen(str);
192
    char* dst = (char*)allocator.alloc(&allocator, len + 1);
193
    memcpy(dst, str, len);
194
    dst[len] = 0;
195

196
    return dst;
197
}
198

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.