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