Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:30

0001 // Copyright Antony Polukhin, 2016-2023.
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP
0008 #define BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP
0009 
0010 #include <boost/config.hpp>
0011 #ifdef BOOST_HAS_PRAGMA_ONCE
0012 #   pragma once
0013 #endif
0014 
0015 #include <fstream>
0016 #include <sstream>
0017 #include <cstdint>
0018 #include <cstdlib>
0019 
0020 namespace boost { namespace stacktrace { namespace detail {
0021 
0022 struct mapping_entry_t {
0023     uintptr_t start = 0;
0024     uintptr_t end = 0;
0025     uintptr_t offset_from_base = 0;
0026 
0027     inline bool contains_addr(const void* addr) const {
0028         uintptr_t addr_uint = reinterpret_cast<uintptr_t>(addr);
0029         return addr_uint >= start && addr_uint < end;
0030     }
0031 };
0032 
0033 inline uintptr_t hex_str_to_int(const std::string& str) {
0034     uintptr_t out;
0035     std::stringstream ss;
0036     ss << std::hex << str;
0037     ss >> out;
0038     if(ss.eof() && !ss.fail()) { // whole stream read, with no errors
0039         return out;
0040     } else {
0041         throw std::invalid_argument(std::string("can't convert '") + str + "' to hex");
0042     }
0043 }
0044 
0045 // parse line from /proc/<id>/maps
0046 // format:
0047 // 7fb60d1ea000-7fb60d20c000 r--p 00000000 103:02 120327460                 /usr/lib/libc.so.6
0048 // only parts 0 and 2 are interesting, these are:
0049 //  0. mapping address range
0050 //  2. mapping offset from base
0051 inline mapping_entry_t parse_proc_maps_line(const std::string& line) {
0052     std::string mapping_range_str, permissions_str, offset_from_base_str;
0053     std::istringstream line_stream(line);
0054     if(!std::getline(line_stream, mapping_range_str, ' ') ||
0055         !std::getline(line_stream, permissions_str, ' ') ||
0056         !std::getline(line_stream, offset_from_base_str, ' ')) {
0057         return mapping_entry_t{};
0058     }
0059     std::string mapping_start_str, mapping_end_str;
0060     std::istringstream mapping_range_stream(mapping_range_str);
0061     if(!std::getline(mapping_range_stream, mapping_start_str, '-') ||
0062         !std::getline(mapping_range_stream, mapping_end_str)) {
0063         return mapping_entry_t{};
0064     }
0065     mapping_entry_t mapping{};
0066     try {
0067         mapping.start = hex_str_to_int(mapping_start_str);
0068         mapping.end = hex_str_to_int(mapping_end_str);
0069         mapping.offset_from_base = hex_str_to_int(offset_from_base_str);
0070         return mapping;
0071     } catch(std::invalid_argument& e) {
0072         return mapping_entry_t{};
0073     }
0074 }
0075 
0076 inline uintptr_t get_own_proc_addr_base(const void* addr) {
0077     std::ifstream maps_file("/proc/self/maps");
0078     for (std::string line; std::getline(maps_file, line); ) {
0079         const mapping_entry_t mapping = parse_proc_maps_line(line);
0080         if (mapping.contains_addr(addr)) {
0081             return mapping.start - mapping.offset_from_base;
0082         }
0083     }
0084     return 0;
0085 }
0086 
0087 }}} // namespace boost::stacktrace::detail
0088 
0089 #endif // BOOST_STACKTRACE_DETAIL_ADDR_BASE_HPP