addr2line must be available. Returns the code lines [lineno - context, lineno + context] */
| 236 | // addr2line must be available. |
| 237 | // Returns the code lines [lineno - context, lineno + context] */ |
| 238 | static std::string PrintCode(std::string symbol, int context) { |
| 239 | std::ostringstream ret; |
| 240 | char objfile[PATH_MAX]; |
| 241 | char addr[1024]; |
| 242 | |
| 243 | // Symbol examples: |
| 244 | // ./bessd(run_worker+0x8e) [0x419d0e] |
| 245 | // ./bessd() [0x4149d8] |
| 246 | // /home/foo/.../source.so(_ZN6Source7RunTaskEPv+0x55) [0x7f09e912c7b5] |
| 247 | Parse(symbol, "%[^(](%*s [%[^]]]", objfile, addr); |
| 248 | |
| 249 | uintptr_t sym_addr = std::strtoull(addr, nullptr, 16); |
| 250 | uintptr_t obj_addr = GetRelativeAddress(sym_addr); |
| 251 | |
| 252 | std::string cmd = |
| 253 | Format("addr2line -C -i -f -p -e %s 0x%" PRIxPTR " 2> /dev/null", objfile, |
| 254 | obj_addr); |
| 255 | |
| 256 | std::istringstream result(RunCommand(cmd)); |
| 257 | std::string line; |
| 258 | |
| 259 | while (std::getline(result, line)) { |
| 260 | // addr2line examples: |
| 261 | // sched_free at /home/sangjin/.../tc.c:277 (discriminator 2) |
| 262 | // run_worker at /home/sangjin/bess/core/module.c:653 |
| 263 | |
| 264 | ret << " " << line << std::endl; |
| 265 | |
| 266 | auto pos = line.find(" at "); |
| 267 | if (pos == std::string::npos) { |
| 268 | // failed to parse the line |
| 269 | continue; |
| 270 | } |
| 271 | |
| 272 | // Remove unnecessary characters (up to " at ", including itself) |
| 273 | line.erase(0, pos + 4); |
| 274 | |
| 275 | char filename[PATH_MAX]; |
| 276 | int lineno; |
| 277 | |
| 278 | if (Parse(line, "%[^:]:%d", filename, &lineno) == 2) { |
| 279 | if (std::string(filename) != "??" && lineno != 0) { |
| 280 | ret << FetchLine(filename, lineno, context); |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | return ret.str(); |
| 286 | } |
| 287 | |
| 288 | static void *trap_ip; |
| 289 | static std::string oops_msg; |
no test coverage detected