Home | History | Annotate | Download | only in libunwindstack
      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 _LIBUNWINDSTACK_DWARF_CFA_H
     18 #define _LIBUNWINDSTACK_DWARF_CFA_H
     19 
     20 #include <stdint.h>
     21 
     22 #include <stack>
     23 #include <string>
     24 #include <type_traits>
     25 #include <vector>
     26 
     27 #include <unwindstack/DwarfLocation.h>
     28 #include <unwindstack/DwarfMemory.h>
     29 #include <unwindstack/DwarfStructs.h>
     30 
     31 #include "DwarfError.h"
     32 
     33 namespace unwindstack {
     34 
     35 // DWARF Standard home: http://dwarfstd.org/
     36 // This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf
     37 // See section 6.4.2.1 for a description of the DW_CFA_xxx values.
     38 
     39 class DwarfCfaInfo {
     40  public:
     41   enum DisplayType : uint8_t {
     42     DWARF_DISPLAY_NONE = 0,
     43     DWARF_DISPLAY_REGISTER,
     44     DWARF_DISPLAY_NUMBER,
     45     DWARF_DISPLAY_SIGNED_NUMBER,
     46     DWARF_DISPLAY_EVAL_BLOCK,
     47     DWARF_DISPLAY_ADDRESS,
     48     DWARF_DISPLAY_SET_LOC,
     49     DWARF_DISPLAY_ADVANCE_LOC,
     50   };
     51 
     52   struct Info {
     53     const char* name;
     54     uint8_t supported_version;
     55     uint8_t num_operands;
     56     uint8_t operands[2];
     57     uint8_t display_operands[2];
     58   };
     59 
     60   const static Info kTable[64];
     61 };
     62 
     63 template <typename AddressType>
     64 class DwarfCfa {
     65   // Signed version of AddressType
     66   typedef typename std::make_signed<AddressType>::type SignedType;
     67 
     68  public:
     69   DwarfCfa(DwarfMemory* memory, const DwarfFde* fde) : memory_(memory), fde_(fde) {}
     70   virtual ~DwarfCfa() = default;
     71 
     72   bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset,
     73                        dwarf_loc_regs_t* loc_regs);
     74 
     75   bool Log(uint32_t indent, uint64_t pc, uint64_t load_bias, uint64_t start_offset,
     76            uint64_t end_offset);
     77 
     78   DwarfError last_error() { return last_error_; }
     79 
     80   AddressType cur_pc() { return cur_pc_; }
     81 
     82   void set_cie_loc_regs(const dwarf_loc_regs_t* cie_loc_regs) { cie_loc_regs_ = cie_loc_regs; }
     83 
     84  protected:
     85   std::string GetOperandString(uint8_t operand, uint64_t value, uint64_t* cur_pc);
     86 
     87   bool LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, uint8_t reg);
     88 
     89   bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc);
     90 
     91  private:
     92   DwarfError last_error_;
     93   DwarfMemory* memory_;
     94   const DwarfFde* fde_;
     95 
     96   AddressType cur_pc_;
     97   const dwarf_loc_regs_t* cie_loc_regs_ = nullptr;
     98   std::vector<AddressType> operands_;
     99   std::stack<dwarf_loc_regs_t> loc_reg_state_;
    100 
    101   // CFA processing functions.
    102   bool cfa_nop(dwarf_loc_regs_t*);
    103   bool cfa_set_loc(dwarf_loc_regs_t*);
    104   bool cfa_advance_loc(dwarf_loc_regs_t*);
    105   bool cfa_offset(dwarf_loc_regs_t*);
    106   bool cfa_restore(dwarf_loc_regs_t*);
    107   bool cfa_undefined(dwarf_loc_regs_t*);
    108   bool cfa_same_value(dwarf_loc_regs_t*);
    109   bool cfa_register(dwarf_loc_regs_t*);
    110   bool cfa_remember_state(dwarf_loc_regs_t*);
    111   bool cfa_restore_state(dwarf_loc_regs_t*);
    112   bool cfa_def_cfa(dwarf_loc_regs_t*);
    113   bool cfa_def_cfa_register(dwarf_loc_regs_t*);
    114   bool cfa_def_cfa_offset(dwarf_loc_regs_t*);
    115   bool cfa_def_cfa_expression(dwarf_loc_regs_t*);
    116   bool cfa_expression(dwarf_loc_regs_t*);
    117   bool cfa_offset_extended_sf(dwarf_loc_regs_t*);
    118   bool cfa_def_cfa_sf(dwarf_loc_regs_t*);
    119   bool cfa_def_cfa_offset_sf(dwarf_loc_regs_t*);
    120   bool cfa_val_offset(dwarf_loc_regs_t*);
    121   bool cfa_val_offset_sf(dwarf_loc_regs_t*);
    122   bool cfa_val_expression(dwarf_loc_regs_t*);
    123   bool cfa_gnu_negative_offset_extended(dwarf_loc_regs_t*);
    124 
    125   using process_func = bool (DwarfCfa::*)(dwarf_loc_regs_t*);
    126   constexpr static process_func kCallbackTable[64] = {
    127       // 0x00 DW_CFA_nop
    128       &DwarfCfa::cfa_nop,
    129       // 0x01 DW_CFA_set_loc
    130       &DwarfCfa::cfa_set_loc,
    131       // 0x02 DW_CFA_advance_loc1
    132       &DwarfCfa::cfa_advance_loc,
    133       // 0x03 DW_CFA_advance_loc2
    134       &DwarfCfa::cfa_advance_loc,
    135       // 0x04 DW_CFA_advance_loc4
    136       &DwarfCfa::cfa_advance_loc,
    137       // 0x05 DW_CFA_offset_extended
    138       &DwarfCfa::cfa_offset,
    139       // 0x06 DW_CFA_restore_extended
    140       &DwarfCfa::cfa_restore,
    141       // 0x07 DW_CFA_undefined
    142       &DwarfCfa::cfa_undefined,
    143       // 0x08 DW_CFA_same_value
    144       &DwarfCfa::cfa_same_value,
    145       // 0x09 DW_CFA_register
    146       &DwarfCfa::cfa_register,
    147       // 0x0a DW_CFA_remember_state
    148       &DwarfCfa::cfa_remember_state,
    149       // 0x0b DW_CFA_restore_state
    150       &DwarfCfa::cfa_restore_state,
    151       // 0x0c DW_CFA_def_cfa
    152       &DwarfCfa::cfa_def_cfa,
    153       // 0x0d DW_CFA_def_cfa_register
    154       &DwarfCfa::cfa_def_cfa_register,
    155       // 0x0e DW_CFA_def_cfa_offset
    156       &DwarfCfa::cfa_def_cfa_offset,
    157       // 0x0f DW_CFA_def_cfa_expression
    158       &DwarfCfa::cfa_def_cfa_expression,
    159       // 0x10 DW_CFA_expression
    160       &DwarfCfa::cfa_expression,
    161       // 0x11 DW_CFA_offset_extended_sf
    162       &DwarfCfa::cfa_offset_extended_sf,
    163       // 0x12 DW_CFA_def_cfa_sf
    164       &DwarfCfa::cfa_def_cfa_sf,
    165       // 0x13 DW_CFA_def_cfa_offset_sf
    166       &DwarfCfa::cfa_def_cfa_offset_sf,
    167       // 0x14 DW_CFA_val_offset
    168       &DwarfCfa::cfa_val_offset,
    169       // 0x15 DW_CFA_val_offset_sf
    170       &DwarfCfa::cfa_val_offset_sf,
    171       // 0x16 DW_CFA_val_expression
    172       &DwarfCfa::cfa_val_expression,
    173       // 0x17 illegal cfa
    174       nullptr,
    175       // 0x18 illegal cfa
    176       nullptr,
    177       // 0x19 illegal cfa
    178       nullptr,
    179       // 0x1a illegal cfa
    180       nullptr,
    181       // 0x1b illegal cfa
    182       nullptr,
    183       // 0x1c DW_CFA_lo_user (Treat this as illegal)
    184       nullptr,
    185       // 0x1d illegal cfa
    186       nullptr,
    187       // 0x1e illegal cfa
    188       nullptr,
    189       // 0x1f illegal cfa
    190       nullptr,
    191       // 0x20 illegal cfa
    192       nullptr,
    193       // 0x21 illegal cfa
    194       nullptr,
    195       // 0x22 illegal cfa
    196       nullptr,
    197       // 0x23 illegal cfa
    198       nullptr,
    199       // 0x24 illegal cfa
    200       nullptr,
    201       // 0x25 illegal cfa
    202       nullptr,
    203       // 0x26 illegal cfa
    204       nullptr,
    205       // 0x27 illegal cfa
    206       nullptr,
    207       // 0x28 illegal cfa
    208       nullptr,
    209       // 0x29 illegal cfa
    210       nullptr,
    211       // 0x2a illegal cfa
    212       nullptr,
    213       // 0x2b illegal cfa
    214       nullptr,
    215       // 0x2c illegal cfa
    216       nullptr,
    217       // 0x2d DW_CFA_GNU_window_save (Treat this as illegal)
    218       nullptr,
    219       // 0x2e DW_CFA_GNU_args_size
    220       &DwarfCfa::cfa_nop,
    221       // 0x2f DW_CFA_GNU_negative_offset_extended
    222       &DwarfCfa::cfa_gnu_negative_offset_extended,
    223       // 0x30 illegal cfa
    224       nullptr,
    225       // 0x31 illegal cfa
    226       nullptr,
    227       // 0x32 illegal cfa
    228       nullptr,
    229       // 0x33 illegal cfa
    230       nullptr,
    231       // 0x34 illegal cfa
    232       nullptr,
    233       // 0x35 illegal cfa
    234       nullptr,
    235       // 0x36 illegal cfa
    236       nullptr,
    237       // 0x37 illegal cfa
    238       nullptr,
    239       // 0x38 illegal cfa
    240       nullptr,
    241       // 0x39 illegal cfa
    242       nullptr,
    243       // 0x3a illegal cfa
    244       nullptr,
    245       // 0x3b illegal cfa
    246       nullptr,
    247       // 0x3c illegal cfa
    248       nullptr,
    249       // 0x3d illegal cfa
    250       nullptr,
    251       // 0x3e illegal cfa
    252       nullptr,
    253       // 0x3f DW_CFA_hi_user (Treat this as illegal)
    254       nullptr,
    255   };
    256 };
    257 
    258 }  // namespace unwindstack
    259 
    260 #endif  // _LIBUNWINDSTACK_DWARF_CFA_H
    261