1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2020, 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 /*
  59  * DwarfParser finds out CFA (Canonical Frame Address) from DWARF in ELF binary.
  60  * Also Return Address (RA) and Base Pointer (BP) are calculated from CFA.
  61  */
  62 class DwarfParser {
  63   private:
  64     const lib_info *_lib;
  65     unsigned char *_buf;
  66     unsigned char _encoding;
  67     enum DWARF_Register _cfa_reg;
  68     enum DWARF_Register _return_address_reg;
  69     unsigned int _code_factor;
  70     int _data_factor;
  71 
  72     uintptr_t _current_pc;
  73     int _cfa_offset;
  74     int _ra_cfa_offset;
  75     int _bp_cfa_offset;
  76     bool _bp_offset_available;
  77 
  78     uintptr_t read_leb(bool sign);
  79     uint64_t get_entry_length();
  80     void process_cie(unsigned char *start_of_entry, uint32_t id);
  81     void parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const unsigned char *end);
  82     uint32_t get_decoded_value();
  83     unsigned int get_pc_range();
  84 
  85   public:
  86     DwarfParser(lib_info *lib) : _lib(lib),
  87                                  _buf(NULL),
  88                                  _encoding(0),
  89                                  _cfa_reg(RSP),
  90                                  _return_address_reg(RA),
  91                                  _code_factor(0),
  92                                  _data_factor(0),
  93                                  _current_pc(0L),
  94                                  _cfa_offset(0),
  95                                  _ra_cfa_offset(0),
  96                                  _bp_cfa_offset(0),
  97                                  _bp_offset_available(false) {};
  98 
  99     ~DwarfParser() {}
 100     uintptr_t process_dwarf(const uintptr_t pc);
 101     enum DWARF_Register get_cfa_register() { return _cfa_reg; }
 102     int get_cfa_offset() { return _cfa_offset; }
 103     int get_ra_cfa_offset() { return _ra_cfa_offset; }
 104     int get_bp_cfa_offset() { return _bp_cfa_offset; }
 105     bool is_bp_offset_available() { return _bp_offset_available; }
 106 
 107     bool is_in(long pc) {
 108       return (_lib->exec_start <= pc) && (pc < _lib->exec_end);
 109     }
 110 
 111     bool is_parseable() {
 112       return _lib->eh_frame.data != NULL;
 113     }
 114 };
 115 
 116 #endif //_DWARF_HPP_