| 114 | }; |
| 115 | |
| 116 | inline std::string addr2line(const char* flag, const void* addr) { |
| 117 | std::string res; |
| 118 | |
| 119 | boost::stacktrace::detail::location_from_symbol loc(addr); |
| 120 | // For programs started through $PATH loc.name() is not absolute and |
| 121 | // addr2line will fail. |
| 122 | if (!loc.empty() && std::strchr(loc.name(), '/') != nullptr) { |
| 123 | res = loc.name(); |
| 124 | } else { |
| 125 | res.resize(16); |
| 126 | ssize_t rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1); |
| 127 | while (rlin_size == static_cast<ssize_t>(res.size() - 1)) { |
| 128 | res.resize(res.size() * 4); |
| 129 | rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1); |
| 130 | } |
| 131 | if (rlin_size == -1) { |
| 132 | res.clear(); |
| 133 | return res; |
| 134 | } |
| 135 | res.resize(static_cast<std::size_t>(rlin_size)); |
| 136 | } |
| 137 | |
| 138 | addr2line_pipe p(flag, res.c_str(), to_hex_array(addr).data()); |
| 139 | res.clear(); |
| 140 | |
| 141 | if (!p) { |
| 142 | return res; |
| 143 | } |
| 144 | |
| 145 | char data[32]; |
| 146 | while (!::feof(p)) { |
| 147 | if (::fgets(data, sizeof(data), p)) { |
| 148 | res += data; |
| 149 | } else { |
| 150 | break; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Trimming |
| 155 | while (!res.empty() && (res[res.size() - 1] == '\n' || res[res.size() - 1] == '\r')) { |
| 156 | res.erase(res.size() - 1); |
| 157 | } |
| 158 | |
| 159 | return res; |
| 160 | } |
| 161 | |
| 162 | inline std::string source_location(const void* addr, bool position_independent) { |
| 163 | uintptr_t addr_base = 0; |
no test coverage detected