Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Concatenate nested namespaces (sonar).
[simgrid.git] / src / mc / inspect / DwarfExpression.cpp
1 /* Copyright (c) 2014-2022. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <cstddef>
7 #include <cstdint>
8 #include <unordered_set>
9
10 #include "src/mc/AddressSpace.hpp"
11 #include "src/mc/inspect/DwarfExpression.hpp"
12 #include "src/mc/inspect/Frame.hpp"
13 #include "src/mc/inspect/LocationList.hpp"
14 #include "src/mc/inspect/ObjectInformation.hpp"
15 #include "src/mc/inspect/mc_dwarf.hpp"
16 #include "src/mc/mc_private.hpp"
17
18 namespace simgrid::dwarf {
19
20 void execute(const Dwarf_Op* ops, std::size_t n, const ExpressionContext& context, ExpressionStack& stack)
21 {
22   for (size_t i = 0; i != n; ++i) {
23     const Dwarf_Op* op = ops + i;
24     std::uint8_t atom  = op->atom;
25     intptr_t first;
26     intptr_t second;
27
28     switch (atom) {
29         // Push the CFA (Canonical Frame Address):
30       case DW_OP_call_frame_cfa:
31         /* See 6.4 of DWARF4 (http://dwarfstd.org/doc/DWARF4.pdf#page=140):
32          *
33          * > Typically, the CFA is defined to be the value of the stack
34          * > pointer at the call site in the previous frame (which may be
35          * > different from its value on entry to the current frame).
36          *
37          * We need to unwind the frame in order to get the SP of the parent
38          * frame.
39          *
40          * Warning: the CFA returned by libunwind (UNW_X86_64_RSP, etc.)
41          * is the SP of the *current* frame. */
42         if (context.cursor) {
43           // Get frame:
44           unw_cursor_t cursor = *(context.cursor);
45           unw_step(&cursor);
46
47           unw_word_t res;
48           unw_get_reg(&cursor, UNW_REG_SP, &res);
49           stack.push(res);
50           break;
51         }
52         throw evaluation_error("Missing cursor");
53
54         // Frame base:
55       case DW_OP_fbreg:
56         stack.push((std::uintptr_t)context.frame_base + op->number);
57         break;
58
59         // Address from the base address of this ELF object.
60         // Push the address on the stack (base_address + argument).
61       case DW_OP_addr:
62         if (context.object_info) {
63           Dwarf_Off addr = (Dwarf_Off)(std::uintptr_t)context.object_info->base_address() + op->number;
64           stack.push(addr);
65           break;
66         }
67         throw evaluation_error("No base address");
68
69         // ***** Stack manipulation:
70
71         // Push another copy/duplicate the value at the top of the stack:
72       case DW_OP_dup:
73         stack.dup();
74         break;
75
76         // Pop/drop the top of the stack:
77       case DW_OP_drop:
78         (void)stack.pop();
79         break;
80
81       case DW_OP_swap:
82         stack.swap();
83         break;
84
85         // Duplicate the value under the top of the stack:
86       case DW_OP_over:
87         stack.push(stack.top(1));
88         break;
89
90         // ***** Operations:
91         // Those usually take the top of the stack and the next value as argument
92         // and replace the top of the stack with the computed value
93         // (stack.top() += stack.before_top()).
94
95       case DW_OP_plus:
96         first  = stack.pop();
97         second = stack.pop();
98         stack.push(first + second);
99         break;
100
101       case DW_OP_mul:
102         first  = stack.pop();
103         second = stack.pop();
104         stack.push(first * second);
105         break;
106
107       case DW_OP_plus_uconst:
108         stack.top() += op->number;
109         break;
110
111       case DW_OP_not:
112         stack.top() = ~stack.top();
113         break;
114
115       case DW_OP_neg:
116         stack.top() = -(intptr_t)stack.top();
117         break;
118
119       case DW_OP_minus:
120         first  = stack.pop();
121         second = stack.pop();
122         stack.push(second - first);
123         break;
124
125       case DW_OP_and:
126         first  = stack.pop();
127         second = stack.pop();
128         stack.push(first & second);
129         break;
130
131       case DW_OP_or:
132         first  = stack.pop();
133         second = stack.pop();
134         stack.push(first | second);
135         break;
136
137       case DW_OP_xor:
138         first  = stack.pop();
139         second = stack.pop();
140         stack.push(first ^ second);
141         break;
142
143       case DW_OP_nop:
144         break;
145
146         // ***** Deference (memory fetch)
147
148       case DW_OP_deref_size:
149         throw evaluation_error("Unsupported operation");
150
151       case DW_OP_deref:
152         // Computed address:
153         if (not context.address_space)
154           throw evaluation_error("Missing address space");
155         context.address_space->read_bytes(&stack.top(), sizeof(uintptr_t), mc::remote(stack.top()));
156         break;
157
158       default:
159
160         // Registers:
161         if (static const std::unordered_set<uint8_t> registers =
162                 {DW_OP_breg0,  DW_OP_breg1,  DW_OP_breg2,  DW_OP_breg3,  DW_OP_breg4,  DW_OP_breg5,  DW_OP_breg6,
163                  DW_OP_breg7,  DW_OP_breg8,  DW_OP_breg9,  DW_OP_breg10, DW_OP_breg11, DW_OP_breg12, DW_OP_breg13,
164                  DW_OP_breg14, DW_OP_breg15, DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20,
165                  DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25, DW_OP_breg26, DW_OP_breg27,
166                  DW_OP_breg28, DW_OP_breg29, DW_OP_breg30, DW_OP_breg31};
167             registers.count(atom) > 0) {
168           // Push register + constant:
169           int register_id = dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
170           unw_word_t res;
171           if (not context.cursor)
172             throw evaluation_error("Missing stack context");
173           unw_get_reg(context.cursor, register_id, &res);
174           stack.push(res + op->number);
175           break;
176         }
177
178         // ***** Constants:
179
180         // Short constant literals:
181         if (static const std::unordered_set<uint8_t> literals = {DW_OP_lit0,  DW_OP_lit1,  DW_OP_lit2,  DW_OP_lit3,
182                                                                  DW_OP_lit4,  DW_OP_lit5,  DW_OP_lit6,  DW_OP_lit7,
183                                                                  DW_OP_lit8,  DW_OP_lit9,  DW_OP_lit10, DW_OP_lit11,
184                                                                  DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15,
185                                                                  DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19,
186                                                                  DW_OP_lit20, DW_OP_lit21, DW_OP_lit22, DW_OP_lit23,
187                                                                  DW_OP_lit24, DW_OP_lit25, DW_OP_lit26, DW_OP_lit27,
188                                                                  DW_OP_lit28, DW_OP_lit29, DW_OP_lit30, DW_OP_lit31};
189             literals.count(atom) > 0) {
190           // Push a literal/constant on the stack:
191           stack.push(atom - DW_OP_lit0);
192           break;
193         }
194
195         // General constants:
196         if (static const std::unordered_set<uint8_t> constants = {DW_OP_const1u, DW_OP_const2u, DW_OP_const4u,
197                                                                   DW_OP_const8u, DW_OP_const1s, DW_OP_const2s,
198                                                                   DW_OP_const4s, DW_OP_const8s, DW_OP_constu,
199                                                                   DW_OP_consts};
200             constants.count(atom) > 0) {
201           // Push the constant argument on the stack.
202           stack.push(op->number);
203           break;
204         }
205
206         // Not handled:
207         throw evaluation_error("Unsupported operation");
208     }
209   }
210 }
211
212 } // namespace simgrid::dwarf