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