github.com/searKing/golang/go@v1.2.117/os/signal/cgo/include/boost/stacktrace/detail/addr_base.hpp (about)

     1  // Copyright Antony Polukhin, 2016-2023.
     2  //
     3  // Distributed under the Boost Software License, Version 1.0. (See
     4  // accompanying file LICENSE_1_0.txt or copy at
     5  // http://www.boost.org/LICENSE_1_0.txt)
     6  
     7  #ifndef BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP
     8  #define BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP
     9  
    10  #include <boost/config.hpp>
    11  #ifdef BOOST_HAS_PRAGMA_ONCE
    12  #   pragma once
    13  #endif
    14  
    15  #include <fstream>
    16  #include <sstream>
    17  #include <cstdint>
    18  #include <cstdlib>
    19  
    20  namespace boost { namespace stacktrace { namespace detail {
    21  
    22  struct mapping_entry_t {
    23      uintptr_t start = 0;
    24      uintptr_t end = 0;
    25      uintptr_t offset_from_base = 0;
    26  
    27      inline bool contains_addr(const void* addr) const {
    28          uintptr_t addr_uint = reinterpret_cast<uintptr_t>(addr);
    29          return addr_uint >= start && addr_uint < end;
    30      }
    31  };
    32  
    33  inline uintptr_t hex_str_to_int(const std::string& str) {
    34      uintptr_t out;
    35      std::stringstream ss;
    36      ss << std::hex << str;
    37      ss >> out;
    38      if(ss.eof() && !ss.fail()) { // whole stream read, with no errors
    39          return out;
    40      } else {
    41          throw std::invalid_argument(std::string("can't convert '") + str + "' to hex");
    42      }
    43  }
    44  
    45  // parse line from /proc/<id>/maps
    46  // format:
    47  // 7fb60d1ea000-7fb60d20c000 r--p 00000000 103:02 120327460                 /usr/lib/libc.so.6
    48  // only parts 0 and 2 are interesting, these are:
    49  //  0. mapping address range
    50  //  2. mapping offset from base
    51  inline mapping_entry_t parse_proc_maps_line(const std::string& line) {
    52      std::string mapping_range_str, permissions_str, offset_from_base_str;
    53      std::istringstream line_stream(line);
    54      if(!std::getline(line_stream, mapping_range_str, ' ') ||
    55          !std::getline(line_stream, permissions_str, ' ') ||
    56          !std::getline(line_stream, offset_from_base_str, ' ')) {
    57          return mapping_entry_t{};
    58      }
    59      std::string mapping_start_str, mapping_end_str;
    60      std::istringstream mapping_range_stream(mapping_range_str);
    61      if(!std::getline(mapping_range_stream, mapping_start_str, '-') ||
    62          !std::getline(mapping_range_stream, mapping_end_str)) {
    63          return mapping_entry_t{};
    64      }
    65      mapping_entry_t mapping{};
    66      try {
    67          mapping.start = hex_str_to_int(mapping_start_str);
    68          mapping.end = hex_str_to_int(mapping_end_str);
    69          mapping.offset_from_base = hex_str_to_int(offset_from_base_str);
    70          return mapping;
    71      } catch(std::invalid_argument& e) {
    72          return mapping_entry_t{};
    73      }
    74  }
    75  
    76  inline uintptr_t get_own_proc_addr_base(const void* addr) {
    77      std::ifstream maps_file("/proc/self/maps");
    78      for (std::string line; std::getline(maps_file, line); ) {
    79          const mapping_entry_t mapping = parse_proc_maps_line(line);
    80          if (mapping.contains_addr(addr)) {
    81              return mapping.start - mapping.offset_from_base;
    82          }
    83      }
    84      return 0;
    85  }
    86  
    87  }}} // namespace boost::stacktrace::detail
    88  
    89  #endif // BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP