aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>2016-08-30 04:39:37 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-09-01 11:42:26 -0400
commit6243b9dc4c991fe8bdc53a0e029908aef3ddb101 (patch)
tree2a658a69aeb5f1f82fa4240dff00283c05ba7ef4
parente47392bf9c0613a058cd20ee89d8ce9d957d4b24 (diff)
perf probe: Move dwarf specific functions to dwarf-aux.c
Move generic dwarf related functions from util/probe-finder.c to util/dwarf-aux.c. Functions name and their prototype are also changed accordingly. No functionality changes. Suggested-and-Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1472546377-25612-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/dwarf-aux.c179
-rw-r--r--tools/perf/util/dwarf-aux.h8
-rw-r--r--tools/perf/util/probe-finder.c136
3 files changed, 189 insertions, 134 deletions
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index a347b19c961a..faec899435f2 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1085,3 +1085,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1085 return -ENOTSUP; 1085 return -ENOTSUP;
1086} 1086}
1087#endif 1087#endif
1088
1089/*
1090 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1091 * @vr_die: a variable DIE
1092 */
1093static bool die_has_loclist(Dwarf_Die *vr_die)
1094{
1095 Dwarf_Attribute loc;
1096 int tag = dwarf_tag(vr_die);
1097
1098 if (tag != DW_TAG_formal_parameter &&
1099 tag != DW_TAG_variable)
1100 return false;
1101
1102 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1103 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1104}
1105
1106/*
1107 * die_is_optimized_target - Check if target program is compiled with
1108 * optimization
1109 * @cu_die: a CU DIE
1110 *
1111 * For any object in given CU whose DW_AT_location is a location list,
1112 * target program is compiled with optimization. This is applicable to
1113 * clang as well.
1114 */
1115bool die_is_optimized_target(Dwarf_Die *cu_die)
1116{
1117 Dwarf_Die tmp_die;
1118
1119 if (die_has_loclist(cu_die))
1120 return true;
1121
1122 if (!dwarf_child(cu_die, &tmp_die) &&
1123 die_is_optimized_target(&tmp_die))
1124 return true;
1125
1126 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1127 die_is_optimized_target(&tmp_die))
1128 return true;
1129
1130 return false;
1131}
1132
1133/*
1134 * die_search_idx - Search index of given line address
1135 * @lines: Line records of single CU
1136 * @nr_lines: Number of @lines
1137 * @addr: address we are looking for
1138 * @idx: index to be set by this function (return value)
1139 *
1140 * Search for @addr by looping over every lines of CU. If address
1141 * matches, set index of that line in @idx. Note that single source
1142 * line can have multiple line records. i.e. single source line can
1143 * have multiple index.
1144 */
1145static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1146 Dwarf_Addr addr, unsigned long *idx)
1147{
1148 unsigned long i;
1149 Dwarf_Addr tmp;
1150
1151 for (i = 0; i < nr_lines; i++) {
1152 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1153 return false;
1154
1155 if (tmp == addr) {
1156 *idx = i;
1157 return true;
1158 }
1159 }
1160 return false;
1161}
1162
1163/*
1164 * die_get_postprologue_addr - Search next address after function prologue
1165 * @entrypc_idx: entrypc index
1166 * @lines: Line records of single CU
1167 * @nr_lines: Number of @lines
1168 * @hignpc: high PC address of function
1169 * @postprologue_addr: Next address after function prologue (return value)
1170 *
1171 * Look for prologue-end marker. If there is no explicit marker, return
1172 * address of next line record or next source line.
1173 */
1174static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1175 Dwarf_Lines *lines,
1176 unsigned long nr_lines,
1177 Dwarf_Addr highpc,
1178 Dwarf_Addr *postprologue_addr)
1179{
1180 unsigned long i;
1181 int entrypc_lno, lno;
1182 Dwarf_Line *line;
1183 Dwarf_Addr addr;
1184 bool p_end;
1185
1186 /* entrypc_lno is actual source line number */
1187 line = dwarf_onesrcline(lines, entrypc_idx);
1188 if (dwarf_lineno(line, &entrypc_lno))
1189 return false;
1190
1191 for (i = entrypc_idx; i < nr_lines; i++) {
1192 line = dwarf_onesrcline(lines, i);
1193
1194 if (dwarf_lineaddr(line, &addr) ||
1195 dwarf_lineno(line, &lno) ||
1196 dwarf_lineprologueend(line, &p_end))
1197 return false;
1198
1199 /* highpc is exclusive. [entrypc,highpc) */
1200 if (addr >= highpc)
1201 break;
1202
1203 /* clang supports prologue-end marker */
1204 if (p_end)
1205 break;
1206
1207 /* Actual next line in source */
1208 if (lno != entrypc_lno)
1209 break;
1210
1211 /*
1212 * Single source line can have multiple line records.
1213 * For Example,
1214 * void foo() { printf("hello\n"); }
1215 * contains two line records. One points to declaration and
1216 * other points to printf() line. Variable 'lno' won't get
1217 * incremented in this case but 'i' will.
1218 */
1219 if (i != entrypc_idx)
1220 break;
1221 }
1222
1223 dwarf_lineaddr(line, postprologue_addr);
1224 if (*postprologue_addr >= highpc)
1225 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1226 postprologue_addr);
1227
1228 return true;
1229}
1230
1231/*
1232 * die_skip_prologue - Use next address after prologue as probe location
1233 * @sp_die: a subprogram DIE
1234 * @cu_die: a CU DIE
1235 * @entrypc: entrypc of the function
1236 *
1237 * Function prologue prepares stack and registers before executing function
1238 * logic. When target program is compiled without optimization, function
1239 * parameter information is only valid after prologue. When we probe entrypc
1240 * of the function, and try to record function parameter, it contains
1241 * garbage value.
1242 */
1243void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1244 Dwarf_Addr *entrypc)
1245{
1246 size_t nr_lines = 0;
1247 unsigned long entrypc_idx = 0;
1248 Dwarf_Lines *lines = NULL;
1249 Dwarf_Addr postprologue_addr;
1250 Dwarf_Addr highpc;
1251
1252 if (dwarf_highpc(sp_die, &highpc))
1253 return;
1254
1255 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1256 return;
1257
1258 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1259 return;
1260
1261 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1262 highpc, &postprologue_addr))
1263 return;
1264
1265 *entrypc = postprologue_addr;
1266}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1adb075..8b6d2f83af02 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -125,4 +125,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
125/* Get the name and type of given variable DIE, stored as "type\tname" */ 125/* Get the name and type of given variable DIE, stored as "type\tname" */
126int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); 126int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
127int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); 127int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
128
129/* Check if target program is compiled with optimization */
130bool die_is_optimized_target(Dwarf_Die *cu_die);
131
132/* Use next address after prologue as probe location */
133void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
134 Dwarf_Addr *entrypc);
135
128#endif 136#endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 003ecadae35d..8daca4fc1f8d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -907,138 +907,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
907 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 907 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
908} 908}
909 909
910static bool var_has_loclist(Dwarf_Die *cu_die)
911{
912 Dwarf_Attribute loc;
913 int tag = dwarf_tag(cu_die);
914
915 if (tag != DW_TAG_formal_parameter &&
916 tag != DW_TAG_variable)
917 return false;
918
919 return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
920 dwarf_whatform(&loc) == DW_FORM_sec_offset);
921}
922
923/*
924 * For any object in given CU whose DW_AT_location is a location list,
925 * target program is compiled with optimization.
926 */
927static bool optimized_target(Dwarf_Die *cu_die)
928{
929 Dwarf_Die tmp_die;
930
931 if (var_has_loclist(cu_die))
932 return true;
933
934 if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
935 return true;
936
937 if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
938 return true;
939
940 return false;
941}
942
943static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
944 Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
945{
946 unsigned long i;
947 Dwarf_Addr addr;
948
949 for (i = 0; i < nr_lines; i++) {
950 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
951 return false;
952
953 if (addr == pf_addr) {
954 *entrypc_idx = i;
955 return true;
956 }
957 }
958 return false;
959}
960
961static bool get_postprologue_addr(unsigned long entrypc_idx,
962 Dwarf_Lines *lines,
963 unsigned long nr_lines,
964 Dwarf_Addr highpc,
965 Dwarf_Addr *postprologue_addr)
966{
967 unsigned long i;
968 int entrypc_lno, lno;
969 Dwarf_Line *line;
970 Dwarf_Addr addr;
971 bool p_end;
972
973 /* entrypc_lno is actual source line number */
974 line = dwarf_onesrcline(lines, entrypc_idx);
975 if (dwarf_lineno(line, &entrypc_lno))
976 return false;
977
978 for (i = entrypc_idx; i < nr_lines; i++) {
979 line = dwarf_onesrcline(lines, i);
980
981 if (dwarf_lineaddr(line, &addr) ||
982 dwarf_lineno(line, &lno) ||
983 dwarf_lineprologueend(line, &p_end))
984 return false;
985
986 /* highpc is exclusive. [entrypc,highpc) */
987 if (addr >= highpc)
988 break;
989
990 /* clang supports prologue-end marker */
991 if (p_end)
992 break;
993
994 /* Actual next line in source */
995 if (lno != entrypc_lno)
996 break;
997
998 /*
999 * Single source line can have multiple line records.
1000 * For Example,
1001 * void foo() { printf("hello\n"); }
1002 * contains two line records. One points to declaration and
1003 * other points to printf() line. Variable 'lno' won't get
1004 * incremented in this case but 'i' will.
1005 */
1006 if (i != entrypc_idx)
1007 break;
1008 }
1009
1010 dwarf_lineaddr(line, postprologue_addr);
1011 if (*postprologue_addr >= highpc)
1012 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1013 postprologue_addr);
1014
1015 return true;
1016}
1017
1018static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
1019{
1020 size_t nr_lines = 0;
1021 unsigned long entrypc_idx = 0;
1022 Dwarf_Lines *lines = NULL;
1023 Dwarf_Addr postprologue_addr;
1024 Dwarf_Addr highpc;
1025
1026 if (dwarf_highpc(sp_die, &highpc))
1027 return;
1028
1029 if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
1030 return;
1031
1032 if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
1033 return;
1034
1035 if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
1036 highpc, &postprologue_addr))
1037 return;
1038
1039 pf->addr = postprologue_addr;
1040}
1041
1042static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf) 910static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
1043{ 911{
1044 struct perf_probe_point *pp = &pf->pev->point; 912 struct perf_probe_point *pp = &pf->pev->point;
@@ -1048,7 +916,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
1048 return; 916 return;
1049 917
1050 /* Compiled with optimization? */ 918 /* Compiled with optimization? */
1051 if (optimized_target(&pf->cu_die)) 919 if (die_is_optimized_target(&pf->cu_die))
1052 return; 920 return;
1053 921
1054 /* Don't know entrypc? */ 922 /* Don't know entrypc? */
@@ -1068,7 +936,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
1068 "Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n", 936 "Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
1069 pf->addr); 937 pf->addr);
1070 938
1071 __skip_prologue(sp_die, pf); 939 die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
1072} 940}
1073 941
1074static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 942static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)