pstrace

Форк
0
/
dwarf_operations.c 
840 строк · 32.2 Кб
1
/*
2
 * dwarf_operations.cpp
3
 *
4
 *  Created on: Jan 11, 2020
5
 *      Author: nnosov
6
 */
7

8

9
#include <dwarf.h>
10
#include <inttypes.h>
11

12
#include "common.h"
13
#include "registers.h"
14
#include "dwarf_operations.h"
15

16
// not implemented operations
17
static bool dw_op_notimpl(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
18
{
19
    pst_log(SEVERITY_WARNING, "Not implemented DWARF operation %s(0x%X)", map->op_name, map->op_num);
20
	return false;
21
}
22

23
// The DW_OP_addr operation has a single operand that encodes a machine
24
// address and whose size is the size of an address on the target machine.
25
static bool dw_op_addr(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
26
{
27
    pst_dwarf_stack_push(stack, &op1, sizeof(op1), DWARF_TYPE_GENERIC);
28
	return true;
29
}
30

31
// The DW_OP_deref_size operation behaves like the DW_OP_deref operation. In the DW_OP_deref_size operation, however, the size
32
// in bytes of the data retrieved from the dereferenced address is specified by the single operand. This operand is a 1-byte unsigned integral constant
33
// whose value may not be larger than the size of the generic type. The data
34
// retrieved is zero extended to the size of an address on the target machine
35
// before being pushed onto the expression stack.
36

37
static bool dw_op_deref_size(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
38
{
39
    pst_dwarf_value* value = pst_dwarf_stack_pop(stack);
40
    if(value) {
41
        uint64_t addr = value->value.uint64;
42
        uint64_t res = 0;
43
        switch(op1) {
44
            case 1:
45
                res = *((uint8_t*)addr);
46
                break;
47
            case 2:
48
                res = *((uint16_t*)addr);
49
                break;
50
            case 4:
51
                res = *((uint32_t*)addr);
52
                break;
53
            case 8:
54
                res = *((uint64_t*)addr);
55
                break;
56
            default:
57
                return false;
58
                break;
59
        }
60
        pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC);
61
        return true;
62
    }
63

64
    return false;
65
}
66

67
// The DW_ OP_deref operation pops the top stack entry and treats it as an address.
68
// The popped value must have an integral type. The value retrieved from that address is pushed, and has the generic type.
69
// The size of the data retrieved from the dereferenced address is the size of an address on the target machine.
70
static bool dw_op_deref(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
71
{
72
    return dw_op_deref_size(stack, map, 8, op2);
73
}
74

75
// DW_OP_const1u, DW_OP_const2u, DW_OP_const4u, DW_OP_const8u. The single operand of a DW_OP_const<n>u operation provides a 1, 2, 4, or  8-byte unsigned integer constant, respectively.
76
// These operations push a value with the generic type
77
static bool dw_op_const_x_u(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
78
{
79
	uint8_t size = 0;
80
	pst_dwarf_value_type type = DWARF_TYPE_UNSIGNED;
81
	switch (map->op_num) {
82
		case DW_OP_const1u:
83
			size = 1;
84
			type = DWARF_TYPE_CHAR;
85
			break;
86
		case DW_OP_const2u:
87
			size = 2;
88
			type = DWARF_TYPE_SHORT;
89
			break;
90
		case DW_OP_const4u:
91
			size = 4;
92
			type = DWARF_TYPE_INT;
93
			break;
94
		case DW_OP_const8u:
95
			size = 8;
96
			type = DWARF_TYPE_LONG;
97
			break;
98
		default:
99
			return false;
100
	}
101

102
	pst_dwarf_stack_push(stack, &op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
103

104
	return true;
105
}
106

107
// DW_OP_const1s, DW_OP_const2s, DW_OP_const4s, DW_OP_const8s. The single operand of a DW_OP_const<n>s operation provides a 1, 2, 4, or 8-byte signed integer constant, respectively.
108
// These operations push a value with the generic type
109
static bool dw_op_const_x_s(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
110
{
111
	uint8_t size; int64_t v;
112
	pst_dwarf_value_type type = DWARF_TYPE_SIGNED;
113
	switch (map->op_num) {
114
		case DW_OP_const1s:
115
			v = (int8_t)op1;
116
			size = sizeof(int8_t);
117
			type = DWARF_TYPE_CHAR;
118
			break;
119
		case DW_OP_const2s:
120
			v = (int16_t)op1;
121
			size = sizeof(int16_t);
122
			type = DWARF_TYPE_SHORT;
123
			break;
124
		case DW_OP_const4s:
125
			v = (int32_t)op1;
126
			size = sizeof(int32_t);
127
			type = DWARF_TYPE_INT;
128
			break;
129
		case DW_OP_const8s:
130
			v = (int64_t)op1;
131
			size = sizeof(int64_t);
132
			type = DWARF_TYPE_LONG;
133
			break;
134
		default:
135
			return false;
136
	}
137

138
	pst_dwarf_stack_push(stack, &v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
139

140
	return true;
141
}
142

143
// The single operand of the DW_OP_constu operation provides an unsigned LEB128 integer constant.
144
static bool dw_op_constu(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
145
{
146
	uint64_t value = decode_uleb128((unsigned char*)&op1);
147
	pst_dwarf_stack_push(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
148
	return true;
149
}
150

151
static bool dw_op_consts(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
152
{
153
	// The single operand of the DW_OP_consts operation provides a signed LEB128 integer constant.
154
	int64_t value = decode_sleb128((unsigned char*)&op1);
155
	pst_dwarf_stack_push(stack, &value, sizeof(value),  DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
156
	return true;
157
}
158

159
// The DW_OP_dup operation duplicates the value (including its type identifier) at the top of the stack.
160
static bool dw_op_dup(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
161
{
162
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0);
163
	pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type);
164

165
	return true;
166
}
167

168
// The DW_OP_drop operation pops the value (including its type identifier) at the top of the stack.
169
static bool dw_op_drop(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
170
{
171
	pst_dwarf_value* value = pst_dwarf_stack_pop(stack);
172
	pst_dwarf_value_fini(value);
173

174
	return true;
175
}
176

177
// The DW_OP_over operation duplicates the entry currently second in the stack at the top of the stack.
178
// This is equivalent to a DW_OP_pick operation, with index 1.
179
static bool dw_op_over(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
180
{
181
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 1);
182
	pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type);
183

184
	return true;
185
}
186

187
// The single operand of the DW_OP_pick operation provides a 1-byte index.
188
// A copy of the stack entry (including its type identifier) with the specified index (0 through 255, inclusive) is pushed onto the stack.
189
static bool dw_op_pick(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
190
{
191
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, op1);
192
	if(value) {
193
	    pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type);
194
		return true;
195
	}
196

197
	return false;
198
}
199

200
// The DW_OP_swap operation swaps the top two stack entries. The entry at the top of the stack (including its type identifier) becomes the second stack
201
// entry, and the second entry (including its type identifier) becomes the top of the stack.
202
static bool dw_op_swap(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
203
{
204
	pst_dwarf_value* value1 = pst_dwarf_stack_pop(stack);
205
	pst_dwarf_value* value2 = pst_dwarf_stack_pop(stack);
206
	if(value1 && value2) {
207
	    pst_dwarf_stack_push_value(stack, value1);
208
	    pst_dwarf_stack_push_value(stack, value2);
209
		return true;
210
	}
211

212
	if(value1) {
213
	    pst_dwarf_value_fini(value1);
214
	}
215
	if(value2) {
216
	    pst_dwarf_value_fini(value2);
217
	}
218

219
	return false;
220
}
221

222
// The DW_OP_rot operation rotates the first three stack entries.
223
// The entry at the top of the stack (including its type identifier) becomes the third stack entry,
224
// the second entry (including its type identifier) becomes the top of the stack,
225
// and the third entry (including its type identifier) becomes the second entry
226
static bool dw_op_rot(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
227
{
228
	pst_dwarf_value* value1 = pst_dwarf_stack_pop(stack);
229
	pst_dwarf_value* value2 = pst_dwarf_stack_pop(stack);
230
	pst_dwarf_value* value3 = pst_dwarf_stack_pop(stack);
231
	if(value1 && value2 && value3) {
232
	    pst_dwarf_stack_push_value(stack, value1);
233
	    pst_dwarf_stack_push_value(stack, value3);
234
	    pst_dwarf_stack_push_value(stack, value2);
235
		return true;
236
	}
237

238
    if(value1) {
239
        pst_dwarf_value_fini(value1);
240
    }
241
    if(value2) {
242
        pst_dwarf_value_fini(value2);
243
    }
244
    if(value3) {
245
        pst_dwarf_value_fini(value3);
246
    }
247

248
	return false;
249
}
250

251
// The DW_OP_abs operation pops the top stack entry, interprets it as a signed value and pushes its absolute value.
252
// If the absolute value cannot be represented, the result is undefined.
253
static bool dw_op_abs(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
254
{
255
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0);
256
	if(value) {
257
		uint64_t res = llabs(value->value.int64);
258
		pst_dwarf_value_set(value, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC | DWARF_TYPE_LONG);
259
	}
260

261
	return false;
262
}
263

264
// The DW_OP_and operation pops the top two stack values, performs a bitwise and operation on the two, and pushes the result.
265
static bool dw_op_and(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
266
{
267
	pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
268
	pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
269
	if(value1 && value2) {
270
		if(!(value1->type & value2->type)) {
271
			return false;
272
		}
273

274
		uint64_t res = value1->value.uint64 & value2->value.uint64;
275
		pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
276
		pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC);
277

278
		pst_dwarf_value_fini(value1);
279
		pst_dwarf_value_fini(value2);
280
		return true;
281
	}
282

283
	return false;
284
}
285

286
// The DW_OP_div operation pops the top two stack values, divides the former second entry by the former top of the stack using signed division, and pushes the result.
287
static bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
288
{
289
	pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
290
	pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
291
	if(value1 && value2) {
292
		if(!(value1->type & value2->type)) {
293
			return false;
294
		}
295

296
		if(value2->type & DWARF_TYPE_SIGNED) {
297
		    if(value1->type & DWARF_TYPE_SIGNED) {
298
		        if(value1->value.int64 == 0) {
299
		            return false;
300
		        }
301
		        uint64_t res = value2->value.int64 / value1->value.int64;
302
		        pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
303
		        pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
304
		        return true;
305
		    } else {
306
                if(value1->value.uint64 == 0) {
307
                    return false;
308
                }
309
                int64_t res = value2->value.int64 / value1->value.uint64;
310
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
311
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
312
                return true;
313
		    }
314
		} else {
315
            if(value1->type & DWARF_TYPE_SIGNED) {
316
                if(value1->value.int64 == 0) {
317
                    return false;
318
                }
319
                int64_t res = value2->value.uint64 / value1->value.int64;
320
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
321
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
322
                return true;
323
            } else {
324
                if(value1->value.uint64 == 0) {
325
                    return false;
326
                }
327
                uint64_t res = value2->value.uint64 / value1->value.uint64;
328
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
329
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
330
                return true;
331
            }
332
		}
333
	}
334

335
	return false;
336
}
337

338
// The DW_OP_minus operation pops the top two stack values, subtracts the former top of the stack from the former second entry, and pushes the result.
339
static bool dw_op_minus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
340
{
341
	pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
342
	pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
343
	if(value1 && value2) {
344
		if(!(value1->type & value2->type)) {
345
			return false;
346
		}
347

348
		int res_type = DWARF_TYPE_GENERIC;
349
		if(value2->type & DWARF_TYPE_MEMORY_LOC) {
350
		    res_type |= DWARF_TYPE_MEMORY_LOC;
351
		}
352
        // use arithmetic by modulo 1 plus
353
		uint64_t res = value2->value.uint64 - value1->value.uint64;
354
		pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
355
		pst_dwarf_stack_push(stack, &res, sizeof(res), res_type);
356

357
		return true;
358
	}
359

360
	return false;
361
}
362

363
// The DW_OP_mod operation pops the top two stack values and pushes the result of the calculation: former second stack entry modulo the former top of the stack.
364
static bool dw_op_mod(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
365
{
366
	pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
367
	pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
368
	if(value1 && value2) {
369
		if(!(value1->type & value2->type)) {
370
			return false;
371
		}
372

373
		if(value1->value.uint64 == 0) {
374
		    return false;
375
		}
376

377
		uint64_t res = value2->value.uint64 % value1->value.uint64;
378
		pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
379
		pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
380

381
		return true;
382
	}
383

384
	return false;
385
}
386

387
// The DW_OP_mul operation pops the top two stack entries, multiplies them together, and pushes the result.
388
static bool dw_op_mul(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
389
{
390
    pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
391
    pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
392
    if(value1 && value2) {
393
        if(!(value1->type & value2->type)) {
394
            pst_log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type);
395
            return false;
396
        }
397

398
        if(value2->type & DWARF_TYPE_SIGNED) {
399
            if(value1->type & DWARF_TYPE_SIGNED) {
400
                uint64_t res = value2->value.int64 * value1->value.int64;
401
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
402
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
403

404
                return true;
405
            } else {
406
                int64_t res = value2->value.int64 * value1->value.uint64;
407
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
408
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
409

410
                return true;
411
            }
412
        } else {
413
            if(value1->type & DWARF_TYPE_SIGNED) {
414
                int64_t res = value2->value.uint64 * value1->value.int64;
415
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
416
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
417

418
                return true;
419
            } else {
420
                uint64_t res = value2->value.uint64 * value1->value.uint64;
421
                pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
422
                pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
423

424
                return true;
425
            }
426
        }
427
    }
428

429
    return false;
430
}
431

432
// The DW_OP_neg operation pops the top stack entry, interprets it as a signed value and pushes its negation.
433
// If the negation cannot be represented, the result is undefined.
434
static bool dw_op_neg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
435
{
436
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0);
437
	if(value) {
438
	    if(value->type & DWARF_TYPE_CHAR) {
439
	        value->value.int8 *= -1;
440
	    } else if(value->type & DWARF_TYPE_SHORT) {
441
	        value->value.int16 *= -1;
442
	    } else if(value->type & DWARF_TYPE_INT) {
443
	        value->value.int32 *= -1;
444
	    } else {
445
	        value->value.int64 *= -1;
446
	    }
447
	    return true;
448
	}
449

450
	return false;
451
}
452

453
// The DW_OP_not operation pops the top stack entry, and pushes its bitwise complement.
454
static bool dw_op_not(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
455
{
456
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0);
457
	if(value) {
458
		value->value.uint64 = ~value->value.uint64;
459

460
		return true;
461
	}
462

463
	return false;
464
}
465

466
// The DW_OP_or operation pops the top two stack entries, performs a bitwise or operation on the two, and pushes the result.
467
static bool dw_op_or(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
468
{
469
    pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
470
    pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
471
	if(value1 && value2) {
472
		if(!(value1->type & value2->type)) {
473
			return false;
474
		}
475

476
		uint64_t res = value2->value.uint64 | value1->value.uint64;
477
        pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
478
		pst_dwarf_stack_push(stack, &res, sizeof(res), value1->type);
479

480
		pst_dwarf_value_fini(value1);
481
		pst_dwarf_value_fini(value2);
482

483
		return true;
484
	}
485

486
	return false;
487
}
488

489
// The DW_OP_plus operation pops the top two stack entries, adds them together, and pushes the result
490
static bool dw_op_plus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
491
{
492
	pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0);
493
	pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1);
494
	if(value1 && value2) {
495
		if(!(value1->type & value2->type)) {
496
			return false;
497
		}
498

499
		if((value1->type & DWARF_TYPE_SIGNED) && (value2->type & DWARF_TYPE_SIGNED)) {
500
		        int64_t res = value2->value.int64 + value1->value.int64;
501
		        pst_dwarf_stack_push(stack, &res, sizeof(res), value1->type);
502
		} else {
503
		    // if in arithmetic expression even one operand is unsigned then result is unsigned as well
504
		    int type = (value1->type & (~DWARF_TYPE_SIGNED)) | DWARF_TYPE_UNSIGNED;
505
		    uint64_t res = value2->value.uint64 + value1->value.uint64;
506
		    pst_dwarf_stack_push(stack, &res, sizeof(res), type);
507
		}
508

509
        pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack);
510
        pst_dwarf_value_fini(value1);
511
        pst_dwarf_value_fini(value2);
512

513
        return true;
514
	}
515

516
	return false;
517
}
518

519
// The DW_OP_plus_uconst operation pops the top stack entry, adds it to the unsigned LEB128 constant operand interpreted as the same type as the
520
// operand popped from the top of the stack and pushes the result.
521
// This operation is supplied specifically to be able to encode more field offsets in two
522
// bytes than can be done with “DW_OP_lit<n> DW_OP_plus.”
523
static bool dw_op_plus_uconst(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
524
{
525
	pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0);
526
	if(value) {
527
	    uint64_t op = decode_uleb128((unsigned char*)&op1);
528
	    value->value.uint64 += op;
529

530
		return true;
531
	}
532

533
	return false;
534
}
535

536
// Register location descriptions. Describe an object (or a piece of an object) that resides in a register.
537
// A register location description must stand alone as the entire description of an object or a piece of an object.
538
// The DW_OP_regx operation has a single unsigned LEB128 literal operand that encodes the name of a register
539
static bool dw_op_reg_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
540
{
541
	if(map->op_num != DW_OP_regx && (map->op_num < DW_OP_reg0 || map->op_num > DW_OP_reg31)) {
542
		return false;
543
	}
544

545
	uint64_t regno = 0;
546
	if(map->op_num == DW_OP_regx) {
547
		regno = decode_uleb128((unsigned char*)&op1);
548
	} else {
549
		regno = map->op_num - DW_OP_reg0;
550
	}
551

552
	pst_dwarf_stack_push(stack, &regno, sizeof(regno), DWARF_TYPE_REGISTER_LOC);
553

554
	return true;
555
}
556

557
// DWARF5, section 2.5.1.2  Register values are used to describe an object (or a piece of an object) that is located in memory at an address that is contained in a register (possibly offset by some constant)
558
// The DW_OP_bregx operation provides the sum of two values specified by its two operands.
559
// The first operand is a register number which is specified by an unsigned LEB128 number. The second operand is a signed LEB128 offset.
560
static bool dw_op_breg_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
561
{
562
	if(map->op_num != DW_OP_bregx && (map->op_num < DW_OP_breg0 || map->op_num > DW_OP_breg31)) {
563
		return false;
564
	}
565

566
	int regno = -1; int64_t off = 0;
567
	if(map->op_num == DW_OP_bregx) {
568
		regno = decode_uleb128((unsigned char*)&op1);
569
		off = decode_sleb128((unsigned char*)&op2);
570
	} else {
571
		regno = find_regnum(map->op_num);
572
		off = decode_sleb128((unsigned char*)&op1);
573
	}
574

575
	unw_word_t val = 0;
576
	int ret = unw_get_reg(stack->ctx->curr_frame, regno, &val);
577
	if(ret) {
578
	    return false;
579
	}
580

581
	val += off;
582
	pst_dwarf_stack_push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC);
583

584
	return true;
585
}
586

587
// The DW_OP_lit<n> operations encode the unsigned literal values from 0 through 31, inclusive.
588
// Operations other than DW_OP_const_type push a value with the generic type.
589
static bool dw_op_lit_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
590
{
591
	if(map->op_num < DW_OP_lit0 || map->op_num > DW_OP_lit31) {
592
		return false;
593
	}
594

595
	uint64_t val = map->op_num - DW_OP_lit0;
596
	pst_dwarf_stack_push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC);
597

598
	return true;
599
}
600

601
// The DW_OP_stack_value operation specifies that the object does not exist in memory but its value is nonetheless known and is at the top of the DWARF
602
// expression stack. In this form of location description, the DWARF expression represents the actual value of the object, rather than its location.
603
// The DW_OP_stack_value operation terminates the expression.
604
static bool dw_op_stack_value(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
605
{
606

607
    pst_dwarf_value* v = pst_dwarf_stack_get(stack, 0);
608
    if(v) {
609
        v->type  = DWARF_TYPE_GENERIC;
610
        return true;
611
    }
612

613
    return false;
614
}
615

616
// The DW_OP_call_frame_cfa operation pushes the value of the CFA, obtained from the Call Frame Information (see Section 6.4 on page 171).
617
static bool dw_op_call_frame_cfa(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
618
{
619
    // since we are already know SP value, just push it to DWARF stack
620
//    unw_word_t sp;
621
//    int ret = unw_get_reg(stack->ctx->curr_frame, UNW_REG_SP, &sp);
622
//    if(ret) {
623
//        pst_log(SEVERITY_ERROR, "%s: failed to get register 0x%X value. Error: %d", __PRETTY_FUNCTION__, UNW_REG_SP, ret);
624
//        return false;
625
//    }
626

627
    pst_dwarf_stack_push(stack, &stack->ctx->cfa, sizeof(stack->ctx->cfa), /*DWARF_TYPE_MEMORY_LOC | */DWARF_TYPE_GENERIC);
628

629
    return true;
630
}
631

632
// The DW_OP_fbreg operation provides a signed LEB128 offset from the address specified by the location description in the DW_AT_frame_base
633
// attribute of the current function. This is typically a stack pointer register plus or minus some offset
634
static bool dw_op_fbreg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
635
{
636
    // since in signal handler we are know SP value, just use it as DW_AT_frame_base
637
    unw_word_t sp;
638
//    int ret = unw_get_reg(stack->ctx->curr_frame, UNW_REG_SP, &sp);
639
//    if(ret) {
640
//        pst_log(SEVERITY_ERROR, "Failed to get register 0x%X value. Error: %d", __PRETTY_FUNCTION__, UNW_REG_SP, ret);
641
//        return false;
642
//    }
643

644
    sp = stack->ctx->cfa;
645
    int64_t off = decode_sleb128((unsigned char*)&op1);
646
    sp += off;
647

648
    pst_dwarf_stack_push(stack, &sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
649

650
    return true;
651
}
652

653
// DWARF Operations to code & name mapping
654
dwarf_op_map op_map[] = {
655
		{DW_OP_addr, 		"DW_OP_addr", 		dw_op_addr},
656
		{DW_OP_deref, 		"DW_OP_deref", 		dw_op_deref},
657
		// Constant operations
658
		{DW_OP_const1u, 	"DW_OP_const1u", 	dw_op_const_x_u},
659
		{DW_OP_const1s, 	"DW_OP_const1s", 	dw_op_const_x_s},
660
		{DW_OP_const2u, 	"DW_OP_const2u", 	dw_op_const_x_u},
661
		{DW_OP_const2s, 	"DW_OP_const2s", 	dw_op_const_x_s},
662
		{DW_OP_const4u, 	"DW_OP_const4u", 	dw_op_const_x_u},
663
		{DW_OP_const4s, 	"DW_OP_const4s", 	dw_op_const_x_s},
664
		{DW_OP_const8u, 	"DW_OP_const8u", 	dw_op_const_x_u},
665
		{DW_OP_const8s, 	"DW_OP_const8s", 	dw_op_const_x_s},
666
		{DW_OP_constu,  	"DW_OP_constu",  	dw_op_constu},
667
		{DW_OP_consts,  	"DW_OP_consts",  	dw_op_consts},
668
		// DWARF expression stack operations
669
		{DW_OP_dup,     	"DW_OP_dup",     	dw_op_dup},
670
		{DW_OP_drop,    	"DW_OP_drop",    	dw_op_drop},
671
		{DW_OP_over,    	"DW_OP_over",    	dw_op_over},
672
		{DW_OP_pick,		"DW_OP_pick",		dw_op_pick},
673
		{DW_OP_swap,		"DW_OP_swap",		dw_op_swap},
674
		{DW_OP_rot,			"DW_OP_rot",		dw_op_rot},
675
		{DW_OP_xderef, 		"DW_OP_xderef",		dw_op_notimpl},
676
		// Arithmetic and Logical Operations
677
		{DW_OP_abs,			"DW_OP_abs",		dw_op_abs},
678
		{DW_OP_and, 		"DW_OP_and",		dw_op_and},
679
		{DW_OP_div,			"DW_OP_div",		dw_op_div},
680
		{DW_OP_minus,		"DW_OP_minus",		dw_op_minus},
681
		{DW_OP_mod,			"DW_OP_mod",		dw_op_mod},
682
		{DW_OP_mul,			"DW_OP_mul",		dw_op_mul},
683
		{DW_OP_neg, 		"DW_OP_neg",		dw_op_neg},
684
		{DW_OP_not,			"DW_OP_not", 		dw_op_not},
685
		{DW_OP_or,			"DW_OP_or",			dw_op_or},
686
		{DW_OP_plus,		"DW_OP_plus",		dw_op_plus},
687
		{DW_OP_plus_uconst, "DW_OP_plus_uconst",dw_op_plus_uconst},
688
		// not implemented for now
689
		{DW_OP_shl,			"DW_OP_shl",		dw_op_notimpl},
690
		{DW_OP_shr,			"DW_OP_shr", 		dw_op_notimpl},
691
		{DW_OP_shra,		"DW_OP_shra",		dw_op_notimpl},
692
		{DW_OP_xor,			"DW_OP_xor",		dw_op_notimpl},
693
		{DW_OP_bra,			"DW_OP_bra",		dw_op_notimpl},
694
		{DW_OP_eq,			"DW_OP_eq",			dw_op_notimpl},
695
		{DW_OP_ge,			"DW_OP_ge",			dw_op_notimpl},
696
		{DW_OP_gt, 			"DW_OP_gt",			dw_op_notimpl},
697
		{DW_OP_le,			"DW_OP_le",			dw_op_notimpl},
698
		{DW_OP_lt,			"DW_OP_lt",			dw_op_notimpl},
699
		{DW_OP_ne,			"DW_OP_ne",			dw_op_notimpl},
700
		{DW_OP_skip,		"DW_OP_skip",		dw_op_notimpl},
701
		// DWARF5 2.5.1.1 Literal Encodings
702
		{DW_OP_lit0,		"DW_OP_lit0",		dw_op_lit_x},
703
		{DW_OP_lit1,		"DW_OP_lit1",		dw_op_lit_x},
704
		{DW_OP_lit2,		"DW_OP_lit2",		dw_op_lit_x},
705
		{DW_OP_lit3,		"DW_OP_lit3",		dw_op_lit_x},
706
		{DW_OP_lit4,		"DW_OP_lit4",		dw_op_lit_x},
707
		{DW_OP_lit5,		"DW_OP_lit5",		dw_op_lit_x},
708
		{DW_OP_lit6,		"DW_OP_lit6",		dw_op_lit_x},
709
		{DW_OP_lit7,		"DW_OP_lit7",		dw_op_lit_x},
710
		{DW_OP_lit8,		"DW_OP_lit8",		dw_op_lit_x},
711
		{DW_OP_lit9,		"DW_OP_lit9",		dw_op_lit_x},
712
		{DW_OP_lit10,		"DW_OP_lit10",		dw_op_lit_x},
713
		{DW_OP_lit11,		"DW_OP_lit11",		dw_op_lit_x},
714
		{DW_OP_lit12,		"DW_OP_lit12",		dw_op_lit_x},
715
		{DW_OP_lit13,		"DW_OP_lit13",		dw_op_lit_x},
716
		{DW_OP_lit14,		"DW_OP_lit14",		dw_op_lit_x},
717
		{DW_OP_lit15,		"DW_OP_lit15",		dw_op_lit_x},
718
		{DW_OP_lit16,		"DW_OP_lit16",		dw_op_lit_x},
719
		{DW_OP_lit17,		"DW_OP_lit17",		dw_op_lit_x},
720
		{DW_OP_lit18,		"DW_OP_lit18",		dw_op_lit_x},
721
		{DW_OP_lit19,		"DW_OP_lit19",		dw_op_lit_x},
722
		{DW_OP_lit20,		"DW_OP_lit20",		dw_op_lit_x},
723
		{DW_OP_lit21,		"DW_OP_lit21",		dw_op_lit_x},
724
		{DW_OP_lit22,		"DW_OP_lit22",		dw_op_lit_x},
725
		{DW_OP_lit23,		"DW_OP_lit23",		dw_op_lit_x},
726
		{DW_OP_lit24,		"DW_OP_lit24",		dw_op_lit_x},
727
		{DW_OP_lit25,		"DW_OP_lit25",		dw_op_lit_x},
728
		{DW_OP_lit26,		"DW_OP_lit26",		dw_op_lit_x},
729
		{DW_OP_lit27,		"DW_OP_lit27",		dw_op_lit_x},
730
		{DW_OP_lit28,		"DW_OP_lit28",		dw_op_lit_x},
731
		{DW_OP_lit29,		"DW_OP_lit29",		dw_op_lit_x},
732
		{DW_OP_lit30,		"DW_OP_lit30",		dw_op_lit_x},
733
		{DW_OP_lit31,		"DW_OP_lit31",		dw_op_lit_x},
734
		// Register location descriptions. I.e. register containing the value
735
		// GP Registers
736
		{DW_OP_reg0, 		"DW_OP_reg0",		dw_op_reg_x},
737
		{DW_OP_reg1, 		"DW_OP_reg1",		dw_op_reg_x},
738
		{DW_OP_reg2, 		"DW_OP_reg2",		dw_op_reg_x},
739
		{DW_OP_reg3, 		"DW_OP_reg3",		dw_op_reg_x},
740
		{DW_OP_reg4, 		"DW_OP_reg4",		dw_op_reg_x},
741
		{DW_OP_reg5, 		"DW_OP_reg5",		dw_op_reg_x},
742
		{DW_OP_reg6, 		"DW_OP_reg6",		dw_op_reg_x},
743
		{DW_OP_reg7, 		"DW_OP_reg7",		dw_op_reg_x},
744
		// Extended GP Registers
745
		{DW_OP_reg8, 		"DW_OP_reg8",		dw_op_reg_x},
746
		{DW_OP_reg9, 		"DW_OP_reg9",		dw_op_reg_x},
747
		{DW_OP_reg10, 		"DW_OP_reg10",		dw_op_reg_x},
748
		{DW_OP_reg11, 		"DW_OP_reg11",		dw_op_reg_x},
749
		{DW_OP_reg12, 		"DW_OP_reg12",		dw_op_reg_x},
750
		{DW_OP_reg13, 		"DW_OP_reg13",		dw_op_reg_x},
751
		{DW_OP_reg14, 		"DW_OP_reg14",		dw_op_reg_x},
752
		{DW_OP_reg15, 		"DW_OP_reg15",		dw_op_reg_x},
753
		{DW_OP_reg16, 		"DW_OP_reg16",		dw_op_reg_x}, // Return Address (RA) mapped to RIP
754
		// SSE Vector Registers
755
		{DW_OP_reg17, 		"DW_OP_reg17",		dw_op_reg_x},
756
		{DW_OP_reg18, 		"DW_OP_reg18",		dw_op_reg_x},
757
		{DW_OP_reg19, 		"DW_OP_reg19",		dw_op_reg_x},
758
		{DW_OP_reg20, 		"DW_OP_reg20",		dw_op_reg_x},
759
		{DW_OP_reg21, 		"DW_OP_reg21",		dw_op_reg_x},
760
		{DW_OP_reg22, 		"DW_OP_reg22",		dw_op_reg_x},
761
		{DW_OP_reg23, 		"DW_OP_reg23",		dw_op_reg_x},
762
		{DW_OP_reg24, 		"DW_OP_reg24",		dw_op_reg_x},
763
		{DW_OP_reg25, 		"DW_OP_reg25",		dw_op_reg_x},
764
		{DW_OP_reg26, 		"DW_OP_reg26",		dw_op_reg_x},
765
		{DW_OP_reg27, 		"DW_OP_reg27",		dw_op_reg_x},
766
		{DW_OP_reg28, 		"DW_OP_reg28",		dw_op_reg_x},
767
		{DW_OP_reg29, 		"DW_OP_reg29",		dw_op_reg_x},
768
		{DW_OP_reg30, 		"DW_OP_reg30",		dw_op_reg_x},
769
		{DW_OP_reg31, 		"DW_OP_reg31",		dw_op_reg_x},
770
		// Register values. I.e. appropriate register value + offset of operation is pushed onto the stack
771
		// GP Registers
772
		{DW_OP_breg0,		"DW_OP_breg0", 		dw_op_breg_x},
773
		{DW_OP_breg1,		"DW_OP_breg1", 		dw_op_breg_x},
774
		{DW_OP_breg2, 		"DW_OP_breg2", 		dw_op_breg_x},
775
		{DW_OP_breg3, 		"DW_OP_breg3", 		dw_op_breg_x},
776
		{DW_OP_breg4, 		"DW_OP_breg4", 		dw_op_breg_x},
777
		{DW_OP_breg5, 		"DW_OP_breg5", 		dw_op_breg_x},
778
		{DW_OP_breg6, 		"DW_OP_breg6", 		dw_op_breg_x},
779
		{DW_OP_breg7, 		"DW_OP_breg7", 		dw_op_breg_x},
780
		// Extended GP Registers
781
		{DW_OP_breg8, 		"DW_OP_breg8", 		dw_op_breg_x},
782
		{DW_OP_breg9, 		"DW_OP_breg9", 		dw_op_breg_x},
783
		{DW_OP_breg10, 		"DW_OP_breg10", 	dw_op_breg_x},
784
		{DW_OP_breg11, 		"DW_OP_breg11", 	dw_op_breg_x},
785
		{DW_OP_breg12, 		"DW_OP_breg12", 	dw_op_breg_x},
786
		{DW_OP_breg13, 		"DW_OP_breg13", 	dw_op_breg_x},
787
		{DW_OP_breg14, 		"DW_OP_breg14", 	dw_op_breg_x},
788
		{DW_OP_breg15, 		"DW_OP_breg15", 	dw_op_breg_x},
789
		{DW_OP_breg16, 		"DW_OP_breg16", 	dw_op_breg_x}, // Return Address (RA) mapped to RIP
790
		// SSE Vector Registers
791
		{DW_OP_breg17, 		"DW_OP_breg17", 	dw_op_breg_x},
792
		{DW_OP_breg18, 		"DW_OP_breg18", 	dw_op_breg_x},
793
		{DW_OP_breg19, 		"DW_OP_breg19", 	dw_op_breg_x},
794
		{DW_OP_breg20, 		"DW_OP_breg20", 	dw_op_breg_x},
795
		{DW_OP_breg21, 		"DW_OP_breg21", 	dw_op_breg_x},
796
		{DW_OP_breg22, 		"DW_OP_breg22", 	dw_op_breg_x},
797
		{DW_OP_breg23, 		"DW_OP_breg23", 	dw_op_breg_x},
798
		{DW_OP_breg24, 		"DW_OP_breg24", 	dw_op_breg_x},
799
		{DW_OP_breg25, 		"DW_OP_breg25", 	dw_op_breg_x},
800
		{DW_OP_breg26, 		"DW_OP_breg26", 	dw_op_breg_x},
801
		{DW_OP_breg27, 		"DW_OP_breg27", 	dw_op_breg_x},
802
		{DW_OP_breg28, 		"DW_OP_breg28", 	dw_op_breg_x},
803
		{DW_OP_breg29, 		"DW_OP_breg29", 	dw_op_breg_x},
804
		{DW_OP_breg30, 		"DW_OP_breg30", 	dw_op_breg_x},
805
		{DW_OP_breg31, 		"DW_OP_breg31", 	dw_op_breg_x},
806
		// special register-related commands
807
		{DW_OP_regx, 		"DW_OP_regx",		dw_op_reg_x},   // 1st operand register name
808
		{DW_OP_fbreg, 		"DW_OP_fbreg", 		dw_op_fbreg},   // base is Frame base register there
809
		{DW_OP_bregx,		"DW_OP_bregx", 		dw_op_breg_x},  // base is value of 1st operand's register
810

811
		// not implemented
812
		{DW_OP_piece,               "DW_OP_piece",              dw_op_notimpl},
813
		{DW_OP_deref_size,          "DW_OP_deref_size",         dw_op_deref_size},
814
		{DW_OP_xderef_size,         "DW_OP_xderef_size",        dw_op_notimpl},
815
		{DW_OP_nop,                 "DW_OP_nop",                dw_op_notimpl},
816
		{DW_OP_push_object_address, "DW_OP_push_object_address",dw_op_notimpl},
817
		{DW_OP_call2,               "DW_OP_call2",              dw_op_notimpl},
818
		{DW_OP_call4,               "DW_OP_call4",              dw_op_notimpl},
819
		{DW_OP_call_ref,            "DW_OP_call_ref",           dw_op_notimpl},
820
		{DW_OP_form_tls_address,    "DW_OP_form_tls_address",   dw_op_notimpl},
821
		{DW_OP_call_frame_cfa,      "DW_OP_call_frame_cfa",     dw_op_call_frame_cfa},
822
		{DW_OP_bit_piece,           "DW_OP_bit_piece",          dw_op_notimpl},
823
		{DW_OP_implicit_value,      "DW_OP_implicit_value",     dw_op_notimpl},
824
		{DW_OP_stack_value,         "DW_OP_stack_value",        dw_op_stack_value},
825

826
		// GNU extensions
827
		// in fact, implementation is at upper layer since this operation contains sub-expression
828
		{DW_OP_GNU_entry_value, "DW_OP_GNU_entry_value",        dw_op_notimpl}, // seems that it's equal to DW_OP_entry_value from DWARF 5
829
};
830

831
const dwarf_op_map* find_op_map(int op)
832
{
833
	for(uint32_t i = 0; i < sizeof(op_map) / sizeof(dwarf_op_map); ++i) {
834
		if(op_map[i].op_num == op) {
835
			return &op_map[i];
836
		}
837
	}
838

839
	return NULL;
840
}
841

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

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

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

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