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