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