1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2019, NTT DATA.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #ifndef _DWARF_HPP_
  27 #define _DWARF_HPP_
  28 
  29 #include "libproc_impl.h"
  30 
  31 /*
  32  * from System V Application Binary Interface
  33  *        AMD64 Architecture Processor Supplement
  34  *          Figure 3.38: DWARF Register Number Mapping
  35  * https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
  36  */
  37 enum DWARF_Register {
  38   RAX,
  39   RDX,
  40   RCX,
  41   RBX,
  42   RSI,
  43   RDI,
  44   RBP,
  45   RSP,
  46   R8,
  47   R9,
  48   R10,
  49   R11,
  50   R12,
  51   R13,
  52   R14,
  53   R15,
  54   RA,
  55   MAX_VALUE
  56 };
  57 
  58 class DwarfParser {
  59   private:
  60     const lib_info *_lib;
  61     unsigned char *_buf;
  62     unsigned char _encoding;
  63     enum DWARF_Register _cfa_reg;
  64     enum DWARF_Register _return_address_reg;
  65     unsigned int _code_factor;
  66     int _data_factor;
  67 
  68     uintptr_t _current_pc;
  69     int _cfa_offset;
  70     int _ra_cfa_offset;
  71     int _bp_cfa_offset;
  72     bool _bp_offset_available;
  73 
  74     uintptr_t read_leb(bool sign);
  75     uint64_t get_entry_length();
  76     void process_cie(unsigned char *start_of_entry, uint32_t id);
  77     void parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const unsigned char *end);
  78     uint32_t get_decoded_value();
  79     unsigned int get_pc_range();
  80 
  81   public:
  82     DwarfParser(lib_info *lib) : _lib(lib),
  83                                  _buf(NULL),
  84                                  _encoding(0),
  85                                  _cfa_reg(RSP),
  86                                  _return_address_reg(RA),
  87                                  _code_factor(0),
  88                                  _data_factor(0),
  89                                  _current_pc(0L),
  90                                  _cfa_offset(0),
  91                                  _ra_cfa_offset(0),
  92                                  _bp_cfa_offset(0),
  93                                  _bp_offset_available(false) {};
  94 
  95     ~DwarfParser() {}
  96     uintptr_t process_dwarf(const uintptr_t pc);
  97     enum DWARF_Register get_cfa_register() { return _cfa_reg; }
  98     int get_cfa_offset() { return _cfa_offset; }
  99     int get_ra_cfa_offset() { return _ra_cfa_offset; }
 100     int get_bp_cfa_offset() { return _bp_cfa_offset; }
 101     bool is_bp_offset_available() { return _bp_offset_available; }
 102 
 103     bool is_in(long pc) {
 104       return (_lib->exec_start <= pc) && (pc < _lib->exec_end);
 105     }
 106 
 107     bool can_parsable() {
 108       return _lib->eh_frame.data != NULL;
 109     }
 110 };
 111 
 112 #endif //_DWARF_HPP_