1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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_DEBUG_FRAME_OPCODE_WRITER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBELFFILE_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h" 21*795d594fSAndroid Build Coastguard Worker #include "dwarf/dwarf_constants.h" 22*795d594fSAndroid Build Coastguard Worker #include "dwarf/register.h" 23*795d594fSAndroid Build Coastguard Worker #include "dwarf/writer.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker namespace art { 26*795d594fSAndroid Build Coastguard Worker namespace dwarf { 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker // Writer for .debug_frame opcodes (DWARF-3). 29*795d594fSAndroid Build Coastguard Worker // See the DWARF specification for the precise meaning of the opcodes. 30*795d594fSAndroid Build Coastguard Worker // The writer is very light-weight, however it will do the following for you: 31*795d594fSAndroid Build Coastguard Worker // * Choose the most compact encoding of a given opcode. 32*795d594fSAndroid Build Coastguard Worker // * Keep track of current state and convert absolute values to deltas. 33*795d594fSAndroid Build Coastguard Worker // * Divide by header-defined factors as appropriate. 34*795d594fSAndroid Build Coastguard Worker template<typename Vector = std::vector<uint8_t> > 35*795d594fSAndroid Build Coastguard Worker class DebugFrameOpCodeWriter : private Writer<Vector> { 36*795d594fSAndroid Build Coastguard Worker static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type"); 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker public: 39*795d594fSAndroid Build Coastguard Worker // To save space, DWARF divides most offsets by header-defined factors. 40*795d594fSAndroid Build Coastguard Worker // They are used in integer divisions, so we make them constants. 41*795d594fSAndroid Build Coastguard Worker // We usually subtract from stack base pointer, so making the factor 42*795d594fSAndroid Build Coastguard Worker // negative makes the encoded values positive and thus easier to encode. 43*795d594fSAndroid Build Coastguard Worker static constexpr int kDataAlignmentFactor = -4; 44*795d594fSAndroid Build Coastguard Worker static constexpr int kCodeAlignmentFactor = 1; 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker // Explicitely advance the program counter to given location. AdvancePC(int absolute_pc)47*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE AdvancePC(int absolute_pc) { 48*795d594fSAndroid Build Coastguard Worker DCHECK_GE(absolute_pc, current_pc_); 49*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 50*795d594fSAndroid Build Coastguard Worker int delta = FactorCodeOffset(absolute_pc - current_pc_); 51*795d594fSAndroid Build Coastguard Worker if (delta != 0) { 52*795d594fSAndroid Build Coastguard Worker if (delta <= 0x3F) { 53*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_advance_loc | delta); 54*795d594fSAndroid Build Coastguard Worker } else if (delta <= UINT8_MAX) { 55*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_advance_loc1); 56*795d594fSAndroid Build Coastguard Worker this->PushUint8(delta); 57*795d594fSAndroid Build Coastguard Worker } else if (delta <= UINT16_MAX) { 58*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_advance_loc2); 59*795d594fSAndroid Build Coastguard Worker this->PushUint16(delta); 60*795d594fSAndroid Build Coastguard Worker } else { 61*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_advance_loc4); 62*795d594fSAndroid Build Coastguard Worker this->PushUint32(delta); 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker } 65*795d594fSAndroid Build Coastguard Worker current_pc_ = absolute_pc; 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker // Override this method to automatically advance the PC before each opcode. ImplicitlyAdvancePC()70*795d594fSAndroid Build Coastguard Worker virtual void ImplicitlyAdvancePC() { } 71*795d594fSAndroid Build Coastguard Worker 72*795d594fSAndroid Build Coastguard Worker // Common alias in assemblers - spill relative to current stack pointer. RelOffset(Reg reg,int offset)73*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE RelOffset(Reg reg, int offset) { 74*795d594fSAndroid Build Coastguard Worker Offset(reg, offset - current_cfa_offset_); 75*795d594fSAndroid Build Coastguard Worker } 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker // Common alias in assemblers - increase stack frame size. AdjustCFAOffset(int delta)78*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE AdjustCFAOffset(int delta) { 79*795d594fSAndroid Build Coastguard Worker DefCFAOffset(current_cfa_offset_ + delta); 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker // Custom alias - spill many registers based on bitmask. RelOffsetForMany(Reg reg_base,int32_t offset,uint32_t reg_mask,int32_t reg_size)83*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE RelOffsetForMany(Reg reg_base, 84*795d594fSAndroid Build Coastguard Worker int32_t offset, 85*795d594fSAndroid Build Coastguard Worker uint32_t reg_mask, 86*795d594fSAndroid Build Coastguard Worker int32_t reg_size) { 87*795d594fSAndroid Build Coastguard Worker DCHECK(reg_size == 4 || reg_size == 8); 88*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 89*795d594fSAndroid Build Coastguard Worker for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { 90*795d594fSAndroid Build Coastguard Worker // Skip zero bits and go to the set bit. 91*795d594fSAndroid Build Coastguard Worker int num_zeros = CTZ(reg_mask); 92*795d594fSAndroid Build Coastguard Worker i += num_zeros; 93*795d594fSAndroid Build Coastguard Worker reg_mask >>= num_zeros; 94*795d594fSAndroid Build Coastguard Worker RelOffset(Reg(reg_base.num() + i), offset); 95*795d594fSAndroid Build Coastguard Worker offset += reg_size; 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker } 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker // Custom alias - unspill many registers based on bitmask. RestoreMany(Reg reg_base,uint32_t reg_mask)101*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE RestoreMany(Reg reg_base, uint32_t reg_mask) { 102*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 103*795d594fSAndroid Build Coastguard Worker for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { 104*795d594fSAndroid Build Coastguard Worker // Skip zero bits and go to the set bit. 105*795d594fSAndroid Build Coastguard Worker int num_zeros = CTZ(reg_mask); 106*795d594fSAndroid Build Coastguard Worker i += num_zeros; 107*795d594fSAndroid Build Coastguard Worker reg_mask >>= num_zeros; 108*795d594fSAndroid Build Coastguard Worker Restore(Reg(reg_base.num() + i)); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker } 111*795d594fSAndroid Build Coastguard Worker } 112*795d594fSAndroid Build Coastguard Worker Nop()113*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Nop() { 114*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 115*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_nop); 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker Offset(Reg reg,int offset)119*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Offset(Reg reg, int offset) { 120*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 121*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 122*795d594fSAndroid Build Coastguard Worker int factored_offset = FactorDataOffset(offset); // May change sign. 123*795d594fSAndroid Build Coastguard Worker if (factored_offset >= 0) { 124*795d594fSAndroid Build Coastguard Worker if (0 <= reg.num() && reg.num() <= 0x3F) { 125*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_offset | reg.num()); 126*795d594fSAndroid Build Coastguard Worker this->PushUleb128(factored_offset); 127*795d594fSAndroid Build Coastguard Worker } else { 128*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_offset_extended); 129*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 130*795d594fSAndroid Build Coastguard Worker this->PushUleb128(factored_offset); 131*795d594fSAndroid Build Coastguard Worker } 132*795d594fSAndroid Build Coastguard Worker } else { 133*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 134*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_offset_extended_sf); 135*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 136*795d594fSAndroid Build Coastguard Worker this->PushSleb128(factored_offset); 137*795d594fSAndroid Build Coastguard Worker } 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker Restore(Reg reg)141*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Restore(Reg reg) { 142*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 143*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 144*795d594fSAndroid Build Coastguard Worker if (0 <= reg.num() && reg.num() <= 0x3F) { 145*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_restore | reg.num()); 146*795d594fSAndroid Build Coastguard Worker } else { 147*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_restore_extended); 148*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 149*795d594fSAndroid Build Coastguard Worker } 150*795d594fSAndroid Build Coastguard Worker } 151*795d594fSAndroid Build Coastguard Worker } 152*795d594fSAndroid Build Coastguard Worker Undefined(Reg reg)153*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Undefined(Reg reg) { 154*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 155*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 156*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_undefined); 157*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 158*795d594fSAndroid Build Coastguard Worker } 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker SameValue(Reg reg)161*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE SameValue(Reg reg) { 162*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 163*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 164*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_same_value); 165*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker // The previous value of "reg" is stored in register "new_reg". Register(Reg reg,Reg new_reg)170*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Register(Reg reg, Reg new_reg) { 171*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 172*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 173*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_register); 174*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 175*795d594fSAndroid Build Coastguard Worker this->PushUleb128(new_reg.num()); 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker } 178*795d594fSAndroid Build Coastguard Worker RememberState()179*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE RememberState() { 180*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 181*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 182*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_remember_state); 183*795d594fSAndroid Build Coastguard Worker } 184*795d594fSAndroid Build Coastguard Worker } 185*795d594fSAndroid Build Coastguard Worker RestoreState()186*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE RestoreState() { 187*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 188*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 189*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_restore_state); 190*795d594fSAndroid Build Coastguard Worker } 191*795d594fSAndroid Build Coastguard Worker } 192*795d594fSAndroid Build Coastguard Worker DefCFA(Reg reg,int offset)193*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE DefCFA(Reg reg, int offset) { 194*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 195*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 196*795d594fSAndroid Build Coastguard Worker if (offset >= 0) { 197*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa); 198*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 199*795d594fSAndroid Build Coastguard Worker this->PushUleb128(offset); // Non-factored. 200*795d594fSAndroid Build Coastguard Worker } else { 201*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 202*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa_sf); 203*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 204*795d594fSAndroid Build Coastguard Worker this->PushSleb128(FactorDataOffset(offset)); 205*795d594fSAndroid Build Coastguard Worker } 206*795d594fSAndroid Build Coastguard Worker } 207*795d594fSAndroid Build Coastguard Worker current_cfa_offset_ = offset; 208*795d594fSAndroid Build Coastguard Worker } 209*795d594fSAndroid Build Coastguard Worker DefCFARegister(Reg reg)210*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE DefCFARegister(Reg reg) { 211*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 212*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 213*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa_register); 214*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 215*795d594fSAndroid Build Coastguard Worker } 216*795d594fSAndroid Build Coastguard Worker } 217*795d594fSAndroid Build Coastguard Worker DefCFAOffset(int offset)218*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE DefCFAOffset(int offset) { 219*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 220*795d594fSAndroid Build Coastguard Worker if (current_cfa_offset_ != offset) { 221*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 222*795d594fSAndroid Build Coastguard Worker if (offset >= 0) { 223*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa_offset); 224*795d594fSAndroid Build Coastguard Worker this->PushUleb128(offset); // Non-factored. 225*795d594fSAndroid Build Coastguard Worker } else { 226*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 227*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa_offset_sf); 228*795d594fSAndroid Build Coastguard Worker this->PushSleb128(FactorDataOffset(offset)); 229*795d594fSAndroid Build Coastguard Worker } 230*795d594fSAndroid Build Coastguard Worker } 231*795d594fSAndroid Build Coastguard Worker } 232*795d594fSAndroid Build Coastguard Worker // Uncoditional so that the user can still get and check the value. 233*795d594fSAndroid Build Coastguard Worker current_cfa_offset_ = offset; 234*795d594fSAndroid Build Coastguard Worker } 235*795d594fSAndroid Build Coastguard Worker ValOffset(Reg reg,int offset)236*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE ValOffset(Reg reg, int offset) { 237*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 238*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 239*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 240*795d594fSAndroid Build Coastguard Worker int factored_offset = FactorDataOffset(offset); // May change sign. 241*795d594fSAndroid Build Coastguard Worker if (factored_offset >= 0) { 242*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_val_offset); 243*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 244*795d594fSAndroid Build Coastguard Worker this->PushUleb128(factored_offset); 245*795d594fSAndroid Build Coastguard Worker } else { 246*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_val_offset_sf); 247*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 248*795d594fSAndroid Build Coastguard Worker this->PushSleb128(factored_offset); 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker } 251*795d594fSAndroid Build Coastguard Worker } 252*795d594fSAndroid Build Coastguard Worker DefCFAExpression(uint8_t * expr,int expr_size)253*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE DefCFAExpression(uint8_t* expr, int expr_size) { 254*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 255*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 256*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 257*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_def_cfa_expression); 258*795d594fSAndroid Build Coastguard Worker this->PushUleb128(expr_size); 259*795d594fSAndroid Build Coastguard Worker this->PushData(expr, expr_size); 260*795d594fSAndroid Build Coastguard Worker } 261*795d594fSAndroid Build Coastguard Worker } 262*795d594fSAndroid Build Coastguard Worker Expression(Reg reg,uint8_t * expr,int expr_size)263*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE Expression(Reg reg, uint8_t* expr, int expr_size) { 264*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 265*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 266*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 267*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_expression); 268*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 269*795d594fSAndroid Build Coastguard Worker this->PushUleb128(expr_size); 270*795d594fSAndroid Build Coastguard Worker this->PushData(expr, expr_size); 271*795d594fSAndroid Build Coastguard Worker } 272*795d594fSAndroid Build Coastguard Worker } 273*795d594fSAndroid Build Coastguard Worker ValExpression(Reg reg,uint8_t * expr,int expr_size)274*795d594fSAndroid Build Coastguard Worker void ALWAYS_INLINE ValExpression(Reg reg, uint8_t* expr, int expr_size) { 275*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(enabled_)) { 276*795d594fSAndroid Build Coastguard Worker ImplicitlyAdvancePC(); 277*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_ = true; 278*795d594fSAndroid Build Coastguard Worker this->PushUint8(DW_CFA_val_expression); 279*795d594fSAndroid Build Coastguard Worker this->PushUleb128(reg.num()); 280*795d594fSAndroid Build Coastguard Worker this->PushUleb128(expr_size); 281*795d594fSAndroid Build Coastguard Worker this->PushData(expr, expr_size); 282*795d594fSAndroid Build Coastguard Worker } 283*795d594fSAndroid Build Coastguard Worker } 284*795d594fSAndroid Build Coastguard Worker IsEnabled()285*795d594fSAndroid Build Coastguard Worker bool IsEnabled() const { return enabled_; } 286*795d594fSAndroid Build Coastguard Worker SetEnabled(bool value)287*795d594fSAndroid Build Coastguard Worker void SetEnabled(bool value) { 288*795d594fSAndroid Build Coastguard Worker enabled_ = value; 289*795d594fSAndroid Build Coastguard Worker if (enabled_ && opcodes_.capacity() == 0u) { 290*795d594fSAndroid Build Coastguard Worker opcodes_.reserve(kDefaultCapacity); 291*795d594fSAndroid Build Coastguard Worker } 292*795d594fSAndroid Build Coastguard Worker } 293*795d594fSAndroid Build Coastguard Worker GetCurrentPC()294*795d594fSAndroid Build Coastguard Worker int GetCurrentPC() const { return current_pc_; } 295*795d594fSAndroid Build Coastguard Worker GetCurrentCFAOffset()296*795d594fSAndroid Build Coastguard Worker int GetCurrentCFAOffset() const { return current_cfa_offset_; } 297*795d594fSAndroid Build Coastguard Worker SetCurrentCFAOffset(int offset)298*795d594fSAndroid Build Coastguard Worker void SetCurrentCFAOffset(int offset) { current_cfa_offset_ = offset; } 299*795d594fSAndroid Build Coastguard Worker 300*795d594fSAndroid Build Coastguard Worker using Writer<Vector>::data; 301*795d594fSAndroid Build Coastguard Worker 302*795d594fSAndroid Build Coastguard Worker explicit DebugFrameOpCodeWriter(bool enabled = true, 303*795d594fSAndroid Build Coastguard Worker const typename Vector::allocator_type& alloc = 304*795d594fSAndroid Build Coastguard Worker typename Vector::allocator_type()) 305*795d594fSAndroid Build Coastguard Worker : Writer<Vector>(&opcodes_), 306*795d594fSAndroid Build Coastguard Worker enabled_(false), 307*795d594fSAndroid Build Coastguard Worker opcodes_(alloc), 308*795d594fSAndroid Build Coastguard Worker current_cfa_offset_(0), 309*795d594fSAndroid Build Coastguard Worker current_pc_(0), 310*795d594fSAndroid Build Coastguard Worker uses_dwarf3_features_(false) { 311*795d594fSAndroid Build Coastguard Worker SetEnabled(enabled); 312*795d594fSAndroid Build Coastguard Worker } 313*795d594fSAndroid Build Coastguard Worker ~DebugFrameOpCodeWriter()314*795d594fSAndroid Build Coastguard Worker virtual ~DebugFrameOpCodeWriter() { } 315*795d594fSAndroid Build Coastguard Worker 316*795d594fSAndroid Build Coastguard Worker protected: 317*795d594fSAndroid Build Coastguard Worker // Best guess based on couple of observed outputs. 318*795d594fSAndroid Build Coastguard Worker static constexpr size_t kDefaultCapacity = 32u; 319*795d594fSAndroid Build Coastguard Worker FactorDataOffset(int offset)320*795d594fSAndroid Build Coastguard Worker int FactorDataOffset(int offset) const { 321*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(offset % kDataAlignmentFactor, 0); 322*795d594fSAndroid Build Coastguard Worker return offset / kDataAlignmentFactor; 323*795d594fSAndroid Build Coastguard Worker } 324*795d594fSAndroid Build Coastguard Worker FactorCodeOffset(int offset)325*795d594fSAndroid Build Coastguard Worker int FactorCodeOffset(int offset) const { 326*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(offset % kCodeAlignmentFactor, 0); 327*795d594fSAndroid Build Coastguard Worker return offset / kCodeAlignmentFactor; 328*795d594fSAndroid Build Coastguard Worker } 329*795d594fSAndroid Build Coastguard Worker 330*795d594fSAndroid Build Coastguard Worker bool enabled_; // If disabled all writes are no-ops. 331*795d594fSAndroid Build Coastguard Worker Vector opcodes_; 332*795d594fSAndroid Build Coastguard Worker int current_cfa_offset_; 333*795d594fSAndroid Build Coastguard Worker int current_pc_; 334*795d594fSAndroid Build Coastguard Worker bool uses_dwarf3_features_; 335*795d594fSAndroid Build Coastguard Worker 336*795d594fSAndroid Build Coastguard Worker private: 337*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(DebugFrameOpCodeWriter); 338*795d594fSAndroid Build Coastguard Worker }; 339*795d594fSAndroid Build Coastguard Worker 340*795d594fSAndroid Build Coastguard Worker } // namespace dwarf 341*795d594fSAndroid Build Coastguard Worker } // namespace art 342*795d594fSAndroid Build Coastguard Worker 343*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBELFFILE_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ 344