1 // SPDX-License-Identifier: GPL-2.0 2 #include "addr2line.h" 3 #include "debug.h" 4 #include "dso.h" 5 #include "string2.h" 6 #include "srcline.h" 7 #include "symbol.h" 8 #include "symbol_conf.h" 9 10 #include <api/io.h> 11 #include <linux/zalloc.h> 12 #include <subcmd/run-command.h> 13 14 #include <inttypes.h> 15 #include <signal.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #define MAX_INLINE_NEST 1024 20 21 static int filename_split(char *filename, unsigned int *line_nr) 22 { 23 char *sep; 24 25 sep = strchr(filename, '\n'); 26 if (sep) 27 *sep = '\0'; 28 29 if (!strcmp(filename, "??:0")) 30 return 0; 31 32 sep = strchr(filename, ':'); 33 if (sep) { 34 *sep++ = '\0'; 35 *line_nr = strtoul(sep, NULL, 0); 36 return 1; 37 } 38 pr_debug("addr2line missing ':' in filename split\n"); 39 return 0; 40 } 41 42 static void addr2line_subprocess_cleanup(struct child_process *a2l) 43 { 44 if (a2l->pid != -1) { 45 kill(a2l->pid, SIGKILL); 46 finish_command(a2l); /* ignore result, we don't care */ 47 a2l->pid = -1; 48 close(a2l->in); 49 close(a2l->out); 50 } 51 52 free(a2l); 53 } 54 55 static struct child_process *addr2line_subprocess_init(const char *addr2line_path, 56 const char *binary_path) 57 { 58 const char *argv[] = { 59 addr2line_path ?: "addr2line", 60 "-e", binary_path, 61 "-a", "-i", "-f", NULL 62 }; 63 struct child_process *a2l = zalloc(sizeof(*a2l)); 64 int start_command_status = 0; 65 66 if (a2l == NULL) { 67 pr_err("Failed to allocate memory for addr2line"); 68 return NULL; 69 } 70 71 a2l->pid = -1; 72 a2l->in = -1; 73 a2l->out = -1; 74 a2l->no_stderr = 1; 75 76 a2l->argv = argv; 77 start_command_status = start_command(a2l); 78 a2l->argv = NULL; /* it's not used after start_command; avoid dangling pointers */ 79 80 if (start_command_status != 0) { 81 pr_warning("could not start addr2line (%s) for %s: start_command return code %d\n", 82 addr2line_path, binary_path, start_command_status); 83 addr2line_subprocess_cleanup(a2l); 84 return NULL; 85 } 86 87 return a2l; 88 } 89 90 enum cmd_a2l_style { 91 BROKEN, 92 GNU_BINUTILS, 93 LLVM, 94 }; 95 96 static enum cmd_a2l_style cmd_addr2line_configure(struct child_process *a2l, const char *dso_name) 97 { 98 static bool cached; 99 static enum cmd_a2l_style style; 100 101 if (!cached) { 102 char buf[128]; 103 struct io io; 104 int ch; 105 int lines; 106 107 if (write(a2l->in, ",\n", 2) != 2) 108 return BROKEN; 109 110 io__init(&io, a2l->out, buf, sizeof(buf)); 111 ch = io__get_char(&io); 112 if (ch == ',') { 113 style = LLVM; 114 cached = true; 115 lines = 1; 116 pr_debug3("Detected LLVM addr2line style\n"); 117 } else if (ch == '0') { 118 style = GNU_BINUTILS; 119 cached = true; 120 lines = 3; 121 pr_debug3("Detected binutils addr2line style\n"); 122 } else { 123 if (!symbol_conf.addr2line_disable_warn) { 124 char *output = NULL; 125 size_t output_len; 126 127 io__getline(&io, &output, &output_len); 128 pr_warning("%s %s: addr2line configuration failed\n", 129 __func__, dso_name); 130 pr_warning("\t%c%s", ch, output); 131 } 132 pr_debug("Unknown/broken addr2line style\n"); 133 return BROKEN; 134 } 135 while (lines) { 136 ch = io__get_char(&io); 137 if (ch <= 0) 138 break; 139 if (ch == '\n') 140 lines--; 141 } 142 /* Ignore SIGPIPE in the event addr2line exits. */ 143 signal(SIGPIPE, SIG_IGN); 144 } 145 return style; 146 } 147 148 static int read_addr2line_record(struct io *io, 149 enum cmd_a2l_style style, 150 const char *dso_name, 151 u64 addr, 152 bool first, 153 char **function, 154 char **filename, 155 unsigned int *line_nr) 156 { 157 /* 158 * Returns: 159 * -1 ==> error 160 * 0 ==> sentinel (or other ill-formed) record read 161 * 1 ==> a genuine record read 162 */ 163 char *line = NULL; 164 size_t line_len = 0; 165 unsigned int dummy_line_nr = 0; 166 int ret = -1; 167 168 if (function != NULL) 169 zfree(function); 170 171 if (filename != NULL) 172 zfree(filename); 173 174 if (line_nr != NULL) 175 *line_nr = 0; 176 177 /* 178 * Read the first line. Without an error this will be: 179 * - for the first line an address like 0x1234, 180 * - the binutils sentinel 0x0000000000000000, 181 * - the llvm-addr2line the sentinel ',' character, 182 * - the function name line for an inlined function. 183 */ 184 if (io__getline(io, &line, &line_len) < 0 || !line_len) 185 goto error; 186 187 pr_debug3("%s %s: addr2line read address for sentinel: %s", __func__, dso_name, line); 188 if (style == LLVM && line_len == 2 && line[0] == ',') { 189 /* Found the llvm-addr2line sentinel character. */ 190 zfree(&line); 191 return 0; 192 } else if (style == GNU_BINUTILS && (!first || addr != 0)) { 193 int zero_count = 0, non_zero_count = 0; 194 /* 195 * Check for binutils sentinel ignoring it for the case the 196 * requested address is 0. 197 */ 198 199 /* A given address should always start 0x. */ 200 if (line_len >= 2 || line[0] != '0' || line[1] != 'x') { 201 for (size_t i = 2; i < line_len; i++) { 202 if (line[i] == '0') 203 zero_count++; 204 else if (line[i] != '\n') 205 non_zero_count++; 206 } 207 if (!non_zero_count) { 208 int ch; 209 210 if (first && !zero_count) { 211 /* Line was erroneous just '0x'. */ 212 goto error; 213 } 214 /* 215 * Line was 0x0..0, the sentinel for binutils. Remove 216 * the function and filename lines. 217 */ 218 zfree(&line); 219 do { 220 ch = io__get_char(io); 221 } while (ch > 0 && ch != '\n'); 222 do { 223 ch = io__get_char(io); 224 } while (ch > 0 && ch != '\n'); 225 return 0; 226 } 227 } 228 } 229 /* Read the second function name line (if inline data then this is the first line). */ 230 if (first && (io__getline(io, &line, &line_len) < 0 || !line_len)) 231 goto error; 232 233 pr_debug3("%s %s: addr2line read line: %s", __func__, dso_name, line); 234 if (function != NULL) 235 *function = strdup(strim(line)); 236 237 zfree(&line); 238 line_len = 0; 239 240 /* Read the third filename and line number line. */ 241 if (io__getline(io, &line, &line_len) < 0 || !line_len) 242 goto error; 243 244 pr_debug3("%s %s: addr2line filename:number : %s", __func__, dso_name, line); 245 if (filename_split(line, line_nr == NULL ? &dummy_line_nr : line_nr) == 0 && 246 style == GNU_BINUTILS) { 247 ret = 0; 248 goto error; 249 } 250 251 if (filename != NULL) 252 *filename = strdup(line); 253 254 zfree(&line); 255 line_len = 0; 256 257 return 1; 258 259 error: 260 free(line); 261 if (function != NULL) 262 zfree(function); 263 if (filename != NULL) 264 zfree(filename); 265 return ret; 266 } 267 268 static int inline_list__append_record(struct dso *dso, 269 struct inline_node *node, 270 struct symbol *sym, 271 const char *function, 272 const char *filename, 273 unsigned int line_nr) 274 { 275 struct symbol *inline_sym = new_inline_sym(dso, sym, function); 276 277 return inline_list__append(inline_sym, srcline_from_fileline(filename, line_nr), node); 278 } 279 280 int cmd__addr2line(const char *dso_name, u64 addr, 281 char **file, unsigned int *line_nr, 282 struct dso *dso, 283 bool unwind_inlines, 284 struct inline_node *node, 285 struct symbol *sym __maybe_unused) 286 { 287 struct child_process *a2l = dso__a2l(dso); 288 char *record_function = NULL; 289 char *record_filename = NULL; 290 unsigned int record_line_nr = 0; 291 int record_status = -1; 292 int ret = 0; 293 size_t inline_count = 0; 294 int len; 295 char buf[128]; 296 ssize_t written; 297 struct io io = { .eof = false }; 298 enum cmd_a2l_style cmd_a2l_style; 299 300 if (!a2l) { 301 if (!filename__has_section(dso_name, ".debug_line")) 302 goto out; 303 304 dso__set_a2l(dso, 305 addr2line_subprocess_init(symbol_conf.addr2line_path, dso_name)); 306 a2l = dso__a2l(dso); 307 } 308 309 if (a2l == NULL) { 310 if (!symbol_conf.addr2line_disable_warn) 311 pr_warning("%s %s: addr2line_subprocess_init failed\n", __func__, dso_name); 312 goto out; 313 } 314 cmd_a2l_style = cmd_addr2line_configure(a2l, dso_name); 315 if (cmd_a2l_style == BROKEN) 316 goto out; 317 318 /* 319 * Send our request and then *deliberately* send something that can't be 320 * interpreted as a valid address to ask addr2line about (namely, 321 * ","). This causes addr2line to first write out the answer to our 322 * request, in an unbounded/unknown number of records, and then to write 323 * out the lines "0x0...0", "??" and "??:0", for GNU binutils, or "," 324 * for llvm-addr2line, so that we can detect when it has finished giving 325 * us anything useful. 326 */ 327 len = snprintf(buf, sizeof(buf), "%016"PRIx64"\n,\n", addr); 328 written = len > 0 ? write(a2l->in, buf, len) : -1; 329 if (written != len) { 330 if (!symbol_conf.addr2line_disable_warn) 331 pr_warning("%s %s: could not send request\n", __func__, dso_name); 332 goto out; 333 } 334 io__init(&io, a2l->out, buf, sizeof(buf)); 335 io.timeout_ms = symbol_conf.addr2line_timeout_ms; 336 switch (read_addr2line_record(&io, cmd_a2l_style, dso_name, addr, /*first=*/true, 337 &record_function, &record_filename, &record_line_nr)) { 338 case -1: 339 if (!symbol_conf.addr2line_disable_warn) 340 pr_warning("%s %s: could not read first record\n", __func__, dso_name); 341 goto out; 342 case 0: 343 /* 344 * The first record was invalid, so return failure, but first 345 * read another record, since we sent a sentinel ',' for the 346 * sake of detected the last inlined function. Treat this as the 347 * first of a record as the ',' generates a new start with GNU 348 * binutils, also force a non-zero address as we're no longer 349 * reading that record. 350 */ 351 switch (read_addr2line_record(&io, cmd_a2l_style, dso_name, 352 /*addr=*/1, /*first=*/true, 353 NULL, NULL, NULL)) { 354 case -1: 355 if (!symbol_conf.addr2line_disable_warn) 356 pr_warning("%s %s: could not read sentinel record\n", 357 __func__, dso_name); 358 break; 359 case 0: 360 /* The sentinel as expected. */ 361 break; 362 default: 363 if (!symbol_conf.addr2line_disable_warn) 364 pr_warning("%s %s: unexpected record instead of sentinel", 365 __func__, dso_name); 366 break; 367 } 368 goto out; 369 default: 370 /* First record as expected. */ 371 break; 372 } 373 374 if (file) { 375 *file = strdup(record_filename); 376 ret = 1; 377 } 378 if (line_nr) 379 *line_nr = record_line_nr; 380 381 if (unwind_inlines) { 382 if (node && inline_list__append_record(dso, node, sym, 383 record_function, 384 record_filename, 385 record_line_nr)) { 386 ret = 0; 387 goto out; 388 } 389 } 390 391 /* 392 * We have to read the records even if we don't care about the inline 393 * info. This isn't the first record and force the address to non-zero 394 * as we're reading records beyond the first. 395 */ 396 while ((record_status = read_addr2line_record(&io, 397 cmd_a2l_style, 398 dso_name, 399 /*addr=*/1, 400 /*first=*/false, 401 &record_function, 402 &record_filename, 403 &record_line_nr)) == 1) { 404 if (unwind_inlines && node && inline_count++ < MAX_INLINE_NEST) { 405 if (inline_list__append_record(dso, node, sym, 406 record_function, 407 record_filename, 408 record_line_nr)) { 409 ret = 0; 410 goto out; 411 } 412 ret = 1; /* found at least one inline frame */ 413 } 414 } 415 416 out: 417 free(record_function); 418 free(record_filename); 419 if (io.eof) { 420 dso__set_a2l(dso, NULL); 421 addr2line_subprocess_cleanup(a2l); 422 } 423 return ret; 424 } 425 426 void dso__free_a2l(struct dso *dso) 427 { 428 struct child_process *a2l = dso__a2l(dso); 429 430 if (!a2l) 431 return; 432 433 addr2line_subprocess_cleanup(a2l); 434 435 dso__set_a2l(dso, NULL); 436 } 437