hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/tools/perf/util/dwarf-aux.c
....@@ -1,28 +1,15 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * dwarf-aux.c : libdw auxiliary interfaces
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License as published by
6
- * the Free Software Foundation; either version 2 of the License, or
7
- * (at your option) any later version.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program; if not, write to the Free Software
16
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
- *
184 */
195
206 #include <errno.h>
217 #include <inttypes.h>
228 #include <stdbool.h>
23
-#include "util.h"
9
+#include <stdlib.h>
2410 #include "debug.h"
2511 #include "dwarf-aux.h"
12
+#include "strbuf.h"
2613 #include "string2.h"
2714
2815 /**
....@@ -72,6 +59,51 @@
7259 return dwarf_formstring(&attr);
7360 }
7461
62
+/* Unlike dwarf_getsrc_die(), cu_getsrc_die() only returns statement line */
63
+static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
64
+{
65
+ Dwarf_Addr laddr;
66
+ Dwarf_Lines *lines;
67
+ Dwarf_Line *line;
68
+ size_t nlines, l, u, n;
69
+ bool flag;
70
+
71
+ if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
72
+ nlines == 0)
73
+ return NULL;
74
+
75
+ /* Lines are sorted by address, use binary search */
76
+ l = 0; u = nlines - 1;
77
+ while (l < u) {
78
+ n = u - (u - l) / 2;
79
+ line = dwarf_onesrcline(lines, n);
80
+ if (!line || dwarf_lineaddr(line, &laddr) != 0)
81
+ return NULL;
82
+ if (addr < laddr)
83
+ u = n - 1;
84
+ else
85
+ l = n;
86
+ }
87
+ /* Going backward to find the lowest line */
88
+ do {
89
+ line = dwarf_onesrcline(lines, --l);
90
+ if (!line || dwarf_lineaddr(line, &laddr) != 0)
91
+ return NULL;
92
+ } while (laddr == addr);
93
+ l++;
94
+ /* Going foward to find the statement line */
95
+ do {
96
+ line = dwarf_onesrcline(lines, l++);
97
+ if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
98
+ dwarf_linebeginstatement(line, &flag) != 0)
99
+ return NULL;
100
+ if (laddr > addr)
101
+ return NULL;
102
+ } while (!flag);
103
+
104
+ return line;
105
+}
106
+
75107 /**
76108 * cu_find_lineinfo - Get a line number and file name for given address
77109 * @cu_die: a CU DIE
....@@ -85,17 +117,26 @@
85117 const char **fname, int *lineno)
86118 {
87119 Dwarf_Line *line;
88
- Dwarf_Addr laddr;
120
+ Dwarf_Die die_mem;
121
+ Dwarf_Addr faddr;
89122
90
- line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
91
- if (line && dwarf_lineaddr(line, &laddr) == 0 &&
92
- addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
123
+ if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
124
+ && die_entrypc(&die_mem, &faddr) == 0 &&
125
+ faddr == addr) {
126
+ *fname = dwarf_decl_file(&die_mem);
127
+ dwarf_decl_line(&die_mem, lineno);
128
+ goto out;
129
+ }
130
+
131
+ line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
132
+ if (line && dwarf_lineno(line, lineno) == 0) {
93133 *fname = dwarf_linesrc(line, NULL, NULL);
94134 if (!*fname)
95135 /* line number is useless without filename */
96136 *lineno = 0;
97137 }
98138
139
+out:
99140 return *lineno ?: -ENOENT;
100141 }
101142
....@@ -267,21 +308,8 @@
267308 {
268309 Dwarf_Attribute attr;
269310
270
- if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
311
+ if (dwarf_attr_integrate(tp_die, attr_name, &attr) == NULL ||
271312 dwarf_formudata(&attr, result) != 0)
272
- return -ENOENT;
273
-
274
- return 0;
275
-}
276
-
277
-/* Get attribute and translate it as a sdata */
278
-static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
279
- Dwarf_Sword *result)
280
-{
281
- Dwarf_Attribute attr;
282
-
283
- if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
284
- dwarf_formsdata(&attr, result) != 0)
285313 return -ENOENT;
286314
287315 return 0;
....@@ -315,9 +343,25 @@
315343 bool die_is_func_def(Dwarf_Die *dw_die)
316344 {
317345 Dwarf_Attribute attr;
346
+ Dwarf_Addr addr = 0;
318347
319
- return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
320
- dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
348
+ if (dwarf_tag(dw_die) != DW_TAG_subprogram)
349
+ return false;
350
+
351
+ if (dwarf_attr(dw_die, DW_AT_declaration, &attr))
352
+ return false;
353
+
354
+ /*
355
+ * DW_AT_declaration can be lost from function declaration
356
+ * by gcc's bug #97060.
357
+ * So we need to check this subprogram DIE has DW_AT_inline
358
+ * or an entry address.
359
+ */
360
+ if (!dwarf_attr(dw_die, DW_AT_inline, &attr) &&
361
+ die_entrypc(dw_die, &addr) < 0)
362
+ return false;
363
+
364
+ return true;
321365 }
322366
323367 /**
....@@ -410,9 +454,9 @@
410454 /* Get the call file index number in CU DIE */
411455 static int die_get_call_fileno(Dwarf_Die *in_die)
412456 {
413
- Dwarf_Sword idx;
457
+ Dwarf_Word idx;
414458
415
- if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
459
+ if (die_get_attr_udata(in_die, DW_AT_call_file, &idx) == 0)
416460 return (int)idx;
417461 else
418462 return -ENOENT;
....@@ -421,9 +465,9 @@
421465 /* Get the declared file index number in CU DIE */
422466 static int die_get_decl_fileno(Dwarf_Die *pdie)
423467 {
424
- Dwarf_Sword idx;
468
+ Dwarf_Word idx;
425469
426
- if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
470
+ if (die_get_attr_udata(pdie, DW_AT_decl_file, &idx) == 0)
427471 return (int)idx;
428472 else
429473 return -ENOENT;
....@@ -918,9 +962,13 @@
918962 if ((tag == DW_TAG_formal_parameter ||
919963 tag == DW_TAG_variable) &&
920964 die_compare_name(die_mem, fvp->name) &&
921
- /* Does the DIE have location information or external instance? */
965
+ /*
966
+ * Does the DIE have location information or const value
967
+ * or external instance?
968
+ */
922969 (dwarf_attr(die_mem, DW_AT_external, &attr) ||
923
- dwarf_attr(die_mem, DW_AT_location, &attr)))
970
+ dwarf_attr(die_mem, DW_AT_location, &attr) ||
971
+ dwarf_attr(die_mem, DW_AT_const_value, &attr)))
924972 return DIE_FIND_CB_END;
925973 if (dwarf_haspc(die_mem, fvp->addr))
926974 return DIE_FIND_CB_CONTINUE;
....@@ -1033,7 +1081,7 @@
10331081 ret = die_get_typename(vr_die, buf);
10341082 if (ret < 0) {
10351083 pr_debug("Failed to get type, make it unknown.\n");
1036
- ret = strbuf_add(buf, " (unknown_type)", 14);
1084
+ ret = strbuf_add(buf, "(unknown_type)", 14);
10371085 }
10381086
10391087 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));