Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Use DWARF Debug information to skip unnecessary callchain entries.
0004  *
0005  * Copyright (C) 2014 Sukadev Bhattiprolu, IBM Corporation.
0006  * Copyright (C) 2014 Ulrich Weigand, IBM Corporation.
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  * When saving the callchain on Power, the kernel conservatively saves
0022  * excess entries in the callchain. A few of these entries are needed
0023  * in some cases but not others. If the unnecessary entries are not
0024  * ignored, we end up with duplicate arcs in the call-graphs. Use
0025  * DWARF debug information to skip over any unnecessary callchain
0026  * entries.
0027  *
0028  * See function header for arch_adjust_callchain() below for more details.
0029  *
0030  * The libdwfl code in this file is based on code from elfutils
0031  * (libdwfl/argp-std.c, libdwfl/tests/addrcfi.c, etc).
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  * Use the DWARF expression for the Call-frame-address and determine
0044  * if return address is in LR and if a new frame was allocated.
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      * Check if return address is on the stack. If return address
0062      * is in a register (typically R0), it is yet to be saved on
0063      * the stack.
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      * Return address is in LR. Check if a frame was allocated
0072      * but not-yet used.
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      * If call frame address is in r1, no new frame was allocated.
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      * A new frame was allocated but has not yet been used.
0090      */
0091     return 2;
0092 }
0093 
0094 /*
0095  * Get the DWARF frame from the .eh_frame section.
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  * Get the DWARF frame from the .debug_frame section.
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  * Return:
0146  *  0 if return address for the program counter @pc is on stack
0147  *  1 if return address is in LR and no new stack frame was allocated
0148  *  2 if return address is in LR and a new frame was allocated (but not
0149  *      yet used)
0150  *  -1 in case of errors
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              * We normally cache the DWARF debug info and never
0180              * call dwfl_end(). But to prevent fd leak, free in
0181              * case of error.
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      * To work with split debug info files (eg: glibc), check both
0197      * .eh_frame and .debug_frame sections of the ELF header.
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  * The callchain saved by the kernel always includes the link register (LR).
0221  *
0222  *  0:  PERF_CONTEXT_USER
0223  *  1:  Program counter (Next instruction pointer)
0224  *  2:  LR value
0225  *  3:  Caller's caller
0226  *  4:  ...
0227  *
0228  * The value in LR is only needed when it holds a return address. If the
0229  * return address is on the stack, we should ignore the LR value.
0230  *
0231  * Further, when the return address is in the LR, if a new frame was just
0232  * allocated but the LR was not saved into it, then the LR contains the
0233  * caller, slot 4: contains the caller's caller and the contents of slot 3:
0234  * (chain->ips[3]) is undefined and must be ignored.
0235  *
0236  * Use DWARF debug information to determine if any entries need to be skipped.
0237  *
0238  * Return:
0239  *  index:  of callchain entry that needs to be ignored (if any)
0240  *  -1  if no entry needs to be ignored or in case of errors
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          * Return address on stack. Ignore LR value in callchain
0273          */
0274         skip_slot = 2;
0275     } else if (rc == 2) {
0276         /*
0277          * New frame allocated but return address still in LR.
0278          * Ignore the caller's caller entry in callchain.
0279          */
0280         skip_slot = 3;
0281     }
0282     return skip_slot;
0283 }