xref: /aosp_15_r20/art/libelffile/dwarf/expression.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBELFFILE_DWARF_EXPRESSION_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBELFFILE_DWARF_EXPRESSION_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <cstddef>
21*795d594fSAndroid Build Coastguard Worker #include <cstdint>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include "dwarf/dwarf_constants.h"
24*795d594fSAndroid Build Coastguard Worker #include "dwarf/writer.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art {
27*795d594fSAndroid Build Coastguard Worker namespace dwarf {
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker // Writer for DWARF expressions which are used in .debug_info and .debug_loc sections.
30*795d594fSAndroid Build Coastguard Worker // See the DWARF specification for the precise meaning of the opcodes.
31*795d594fSAndroid Build Coastguard Worker // If multiple equivalent encodings are possible, it will choose the most compact one.
32*795d594fSAndroid Build Coastguard Worker // The writer is not exhaustive - it only implements opcodes we have needed so far.
33*795d594fSAndroid Build Coastguard Worker class Expression : private Writer<> {
34*795d594fSAndroid Build Coastguard Worker  public:
35*795d594fSAndroid Build Coastguard Worker   using Writer<>::data;
36*795d594fSAndroid Build Coastguard Worker   using Writer<>::size;
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker   // Push signed integer on the stack.
WriteOpConsts(int32_t value)39*795d594fSAndroid Build Coastguard Worker   void WriteOpConsts(int32_t value) {
40*795d594fSAndroid Build Coastguard Worker     if (0 <= value && value < 32) {
41*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_lit0 + value);
42*795d594fSAndroid Build Coastguard Worker     } else {
43*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_consts);
44*795d594fSAndroid Build Coastguard Worker       PushSleb128(value);
45*795d594fSAndroid Build Coastguard Worker     }
46*795d594fSAndroid Build Coastguard Worker   }
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker   // Push unsigned integer on the stack.
WriteOpConstu(uint32_t value)49*795d594fSAndroid Build Coastguard Worker   void WriteOpConstu(uint32_t value) {
50*795d594fSAndroid Build Coastguard Worker     if (value < 32) {
51*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_lit0 + value);
52*795d594fSAndroid Build Coastguard Worker     } else {
53*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_constu);
54*795d594fSAndroid Build Coastguard Worker       PushUleb128(value);
55*795d594fSAndroid Build Coastguard Worker     }
56*795d594fSAndroid Build Coastguard Worker   }
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker   // Variable is stored in given register.
WriteOpReg(uint32_t dwarf_reg_num)59*795d594fSAndroid Build Coastguard Worker   void WriteOpReg(uint32_t dwarf_reg_num) {
60*795d594fSAndroid Build Coastguard Worker     if (dwarf_reg_num < 32) {
61*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_reg0 + dwarf_reg_num);
62*795d594fSAndroid Build Coastguard Worker     } else {
63*795d594fSAndroid Build Coastguard Worker       PushUint8(DW_OP_regx);
64*795d594fSAndroid Build Coastguard Worker       PushUleb128(dwarf_reg_num);
65*795d594fSAndroid Build Coastguard Worker     }
66*795d594fSAndroid Build Coastguard Worker   }
67*795d594fSAndroid Build Coastguard Worker 
68*795d594fSAndroid Build Coastguard Worker   // Variable is stored on stack.  Also see DW_AT_frame_base.
WriteOpFbreg(int32_t stack_offset)69*795d594fSAndroid Build Coastguard Worker   void WriteOpFbreg(int32_t stack_offset) {
70*795d594fSAndroid Build Coastguard Worker     PushUint8(DW_OP_fbreg);
71*795d594fSAndroid Build Coastguard Worker     PushSleb128(stack_offset);
72*795d594fSAndroid Build Coastguard Worker   }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker   // The variable is stored in multiple locations (pieces).
WriteOpPiece(uint32_t num_bytes)75*795d594fSAndroid Build Coastguard Worker   void WriteOpPiece(uint32_t num_bytes) {
76*795d594fSAndroid Build Coastguard Worker     PushUint8(DW_OP_piece);
77*795d594fSAndroid Build Coastguard Worker     PushUleb128(num_bytes);
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   // Loads 32-bit or 64-bit value depending on architecture.
WriteOpDeref()81*795d594fSAndroid Build Coastguard Worker   void WriteOpDeref() { PushUint8(DW_OP_deref); }
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker   // Loads value of given byte size.
WriteOpDerefSize(uint8_t num_bytes)84*795d594fSAndroid Build Coastguard Worker   void WriteOpDerefSize(uint8_t num_bytes) {
85*795d594fSAndroid Build Coastguard Worker     PushUint8(DW_OP_deref_size);
86*795d594fSAndroid Build Coastguard Worker     PushUint8(num_bytes);
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker   // Pop two values and push their sum.
WriteOpPlus()90*795d594fSAndroid Build Coastguard Worker   void WriteOpPlus() { PushUint8(DW_OP_plus); }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   // Add constant value to value on top of stack.
WriteOpPlusUconst(uint32_t offset)93*795d594fSAndroid Build Coastguard Worker   void WriteOpPlusUconst(uint32_t offset) {
94*795d594fSAndroid Build Coastguard Worker     PushUint8(DW_OP_plus_uconst);
95*795d594fSAndroid Build Coastguard Worker     PushUleb128(offset);
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   // Negate top of stack.
WriteOpNeg()99*795d594fSAndroid Build Coastguard Worker   void WriteOpNeg() { PushUint8(DW_OP_neg); }
100*795d594fSAndroid Build Coastguard Worker 
101*795d594fSAndroid Build Coastguard Worker   // Pop two values and push their bitwise-AND.
WriteOpAnd()102*795d594fSAndroid Build Coastguard Worker   void WriteOpAnd() { PushUint8(DW_OP_and); }
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker   // Push stack base pointer as determined from .debug_frame.
WriteOpCallFrameCfa()105*795d594fSAndroid Build Coastguard Worker   void WriteOpCallFrameCfa() { PushUint8(DW_OP_call_frame_cfa); }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker   // Push address of the variable we are working with.
WriteOpPushObjectAddress()108*795d594fSAndroid Build Coastguard Worker   void WriteOpPushObjectAddress() { PushUint8(DW_OP_push_object_address); }
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   // Return the top stack as the value of the variable.
111*795d594fSAndroid Build Coastguard Worker   // Otherwise, the top of stack is the variable's location.
WriteOpStackValue()112*795d594fSAndroid Build Coastguard Worker   void WriteOpStackValue() { PushUint8(DW_OP_stack_value); }
113*795d594fSAndroid Build Coastguard Worker 
Expression(std::vector<uint8_t> * buffer)114*795d594fSAndroid Build Coastguard Worker   explicit Expression(std::vector<uint8_t>* buffer) : Writer<>(buffer) {
115*795d594fSAndroid Build Coastguard Worker     buffer->clear();
116*795d594fSAndroid Build Coastguard Worker   }
117*795d594fSAndroid Build Coastguard Worker };
118*795d594fSAndroid Build Coastguard Worker }  // namespace dwarf
119*795d594fSAndroid Build Coastguard Worker }  // namespace art
120*795d594fSAndroid Build Coastguard Worker 
121*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBELFFILE_DWARF_EXPRESSION_H_
122