0001
0002
0003
0004
0005
0006
0007
0008 #include <inttypes.h>
0009 #include <dwarf.h>
0010 #include <elfutils/libdwfl.h>
0011
0012 #include "util/thread.h"
0013 #include "util/callchain.h"
0014 #include "util/debug.h"
0015 #include "util/dso.h"
0016 #include "util/event.h" // struct ip_callchain
0017 #include "util/map.h"
0018 #include "util/symbol.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 static char *debuginfo_path;
0034
0035 static const Dwfl_Callbacks offline_callbacks = {
0036 .debuginfo_path = &debuginfo_path,
0037 .find_debuginfo = dwfl_standard_find_debuginfo,
0038 .section_address = dwfl_offline_section_address,
0039 };
0040
0041
0042
0043
0044
0045
0046 static int check_return_reg(int ra_regno, Dwarf_Frame *frame)
0047 {
0048 Dwarf_Op ops_mem[3];
0049 Dwarf_Op dummy;
0050 Dwarf_Op *ops = &dummy;
0051 size_t nops;
0052 int result;
0053
0054 result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops);
0055 if (result < 0) {
0056 pr_debug("dwarf_frame_register() %s\n", dwarf_errmsg(-1));
0057 return -1;
0058 }
0059
0060
0061
0062
0063
0064
0065 if ((nops != 0 || ops != NULL) &&
0066 !(nops == 1 && ops[0].atom == DW_OP_regx &&
0067 ops[0].number2 == 0 && ops[0].offset == 0))
0068 return 0;
0069
0070
0071
0072
0073
0074 result = dwarf_frame_cfa(frame, &ops, &nops);
0075 if (result < 0) {
0076 pr_debug("dwarf_frame_cfa() returns %d, %s\n", result,
0077 dwarf_errmsg(-1));
0078 return -1;
0079 }
0080
0081
0082
0083
0084 if (nops == 1 && ops[0].atom == DW_OP_bregx && ops[0].number == 1 &&
0085 ops[0].number2 == 0)
0086 return 1;
0087
0088
0089
0090
0091 return 2;
0092 }
0093
0094
0095
0096
0097 static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc)
0098 {
0099 int result;
0100 Dwarf_Addr bias;
0101 Dwarf_CFI *cfi;
0102 Dwarf_Frame *frame;
0103
0104 cfi = dwfl_module_eh_cfi(mod, &bias);
0105 if (!cfi) {
0106 pr_debug("%s(): no CFI - %s\n", __func__, dwfl_errmsg(-1));
0107 return NULL;
0108 }
0109
0110 result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
0111 if (result) {
0112 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
0113 return NULL;
0114 }
0115
0116 return frame;
0117 }
0118
0119
0120
0121
0122 static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
0123 {
0124 Dwarf_CFI *cfi;
0125 Dwarf_Addr bias;
0126 Dwarf_Frame *frame;
0127 int result;
0128
0129 cfi = dwfl_module_dwarf_cfi(mod, &bias);
0130 if (!cfi) {
0131 pr_debug("%s(): no CFI - %s\n", __func__, dwfl_errmsg(-1));
0132 return NULL;
0133 }
0134
0135 result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
0136 if (result) {
0137 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
0138 return NULL;
0139 }
0140
0141 return frame;
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152 static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
0153 {
0154 int rc = -1;
0155 Dwfl *dwfl;
0156 Dwfl_Module *mod;
0157 Dwarf_Frame *frame;
0158 int ra_regno;
0159 Dwarf_Addr start = pc;
0160 Dwarf_Addr end = pc;
0161 bool signalp;
0162 const char *exec_file = dso->long_name;
0163
0164 dwfl = dso->dwfl;
0165
0166 if (!dwfl) {
0167 dwfl = dwfl_begin(&offline_callbacks);
0168 if (!dwfl) {
0169 pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
0170 return -1;
0171 }
0172
0173 mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
0174 map_start, false);
0175 if (!mod) {
0176 pr_debug("dwfl_report_elf() failed %s\n",
0177 dwarf_errmsg(-1));
0178
0179
0180
0181
0182
0183 dwfl_end(dwfl);
0184 goto out;
0185 }
0186 dso->dwfl = dwfl;
0187 }
0188
0189 mod = dwfl_addrmodule(dwfl, pc);
0190 if (!mod) {
0191 pr_debug("dwfl_addrmodule() failed, %s\n", dwarf_errmsg(-1));
0192 goto out;
0193 }
0194
0195
0196
0197
0198
0199 frame = get_eh_frame(mod, pc);
0200 if (!frame) {
0201 frame = get_dwarf_frame(mod, pc);
0202 if (!frame)
0203 goto out;
0204 }
0205
0206 ra_regno = dwarf_frame_info(frame, &start, &end, &signalp);
0207 if (ra_regno < 0) {
0208 pr_debug("Return address register unavailable: %s\n",
0209 dwarf_errmsg(-1));
0210 goto out;
0211 }
0212
0213 rc = check_return_reg(ra_regno, frame);
0214
0215 out:
0216 return rc;
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
0243 {
0244 struct addr_location al;
0245 struct dso *dso = NULL;
0246 int rc;
0247 u64 ip;
0248 u64 skip_slot = -1;
0249
0250 if (!chain || chain->nr < 3)
0251 return skip_slot;
0252
0253 ip = chain->ips[1];
0254
0255 thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
0256
0257 if (al.map)
0258 dso = al.map->dso;
0259
0260 if (!dso) {
0261 pr_debug("%" PRIx64 " dso is NULL\n", ip);
0262 return skip_slot;
0263 }
0264
0265 rc = check_return_addr(dso, al.map->start, ip);
0266
0267 pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
0268 dso->long_name, al.sym->name, ip, rc);
0269
0270 if (rc == 0) {
0271
0272
0273
0274 skip_slot = 2;
0275 } else if (rc == 2) {
0276
0277
0278
0279
0280 skip_slot = 3;
0281 }
0282 return skip_slot;
0283 }