linux/tools/perf/util/probe-finder.c
<<
>>
Prefs
   1/*
   2 * probe-finder.c : C expression to kprobe event converter
   3 *
   4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19 *
  20 */
  21
  22#include <inttypes.h>
  23#include <sys/utsname.h>
  24#include <sys/types.h>
  25#include <sys/stat.h>
  26#include <fcntl.h>
  27#include <errno.h>
  28#include <stdio.h>
  29#include <unistd.h>
  30#include <stdlib.h>
  31#include <string.h>
  32#include <stdarg.h>
  33#include <dwarf-regs.h>
  34
  35#include <linux/bitops.h>
  36#include "event.h"
  37#include "dso.h"
  38#include "debug.h"
  39#include "intlist.h"
  40#include "util.h"
  41#include "strlist.h"
  42#include "symbol.h"
  43#include "probe-finder.h"
  44#include "probe-file.h"
  45#include "string2.h"
  46
  47/* Kprobe tracer basic type is up to u64 */
  48#define MAX_BASIC_TYPE_BITS     64
  49
  50/* Dwarf FL wrappers */
  51static char *debuginfo_path;    /* Currently dummy */
  52
  53static const Dwfl_Callbacks offline_callbacks = {
  54        .find_debuginfo = dwfl_standard_find_debuginfo,
  55        .debuginfo_path = &debuginfo_path,
  56
  57        .section_address = dwfl_offline_section_address,
  58
  59        /* We use this table for core files too.  */
  60        .find_elf = dwfl_build_id_find_elf,
  61};
  62
  63/* Get a Dwarf from offline image */
  64static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
  65                                         const char *path)
  66{
  67        int fd;
  68
  69        fd = open(path, O_RDONLY);
  70        if (fd < 0)
  71                return fd;
  72
  73        dbg->dwfl = dwfl_begin(&offline_callbacks);
  74        if (!dbg->dwfl)
  75                goto error;
  76
  77        dwfl_report_begin(dbg->dwfl);
  78        dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
  79        if (!dbg->mod)
  80                goto error;
  81
  82        dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
  83        if (!dbg->dbg)
  84                goto error;
  85
  86        dwfl_report_end(dbg->dwfl, NULL, NULL);
  87
  88        return 0;
  89error:
  90        if (dbg->dwfl)
  91                dwfl_end(dbg->dwfl);
  92        else
  93                close(fd);
  94        memset(dbg, 0, sizeof(*dbg));
  95
  96        return -ENOENT;
  97}
  98
  99static struct debuginfo *__debuginfo__new(const char *path)
 100{
 101        struct debuginfo *dbg = zalloc(sizeof(*dbg));
 102        if (!dbg)
 103                return NULL;
 104
 105        if (debuginfo__init_offline_dwarf(dbg, path) < 0)
 106                zfree(&dbg);
 107        if (dbg)
 108                pr_debug("Open Debuginfo file: %s\n", path);
 109        return dbg;
 110}
 111
 112enum dso_binary_type distro_dwarf_types[] = {
 113        DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
 114        DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
 115        DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
 116        DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
 117        DSO_BINARY_TYPE__NOT_FOUND,
 118};
 119
 120struct debuginfo *debuginfo__new(const char *path)
 121{
 122        enum dso_binary_type *type;
 123        char buf[PATH_MAX], nil = '\0';
 124        struct dso *dso;
 125        struct debuginfo *dinfo = NULL;
 126
 127        /* Try to open distro debuginfo files */
 128        dso = dso__new(path);
 129        if (!dso)
 130                goto out;
 131
 132        for (type = distro_dwarf_types;
 133             !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
 134             type++) {
 135                if (dso__read_binary_type_filename(dso, *type, &nil,
 136                                                   buf, PATH_MAX) < 0)
 137                        continue;
 138                dinfo = __debuginfo__new(buf);
 139        }
 140        dso__put(dso);
 141
 142out:
 143        /* if failed to open all distro debuginfo, open given binary */
 144        return dinfo ? : __debuginfo__new(path);
 145}
 146
 147void debuginfo__delete(struct debuginfo *dbg)
 148{
 149        if (dbg) {
 150                if (dbg->dwfl)
 151                        dwfl_end(dbg->dwfl);
 152                free(dbg);
 153        }
 154}
 155
 156/*
 157 * Probe finder related functions
 158 */
 159
 160static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
 161{
 162        struct probe_trace_arg_ref *ref;
 163        ref = zalloc(sizeof(struct probe_trace_arg_ref));
 164        if (ref != NULL)
 165                ref->offset = offs;
 166        return ref;
 167}
 168
 169/*
 170 * Convert a location into trace_arg.
 171 * If tvar == NULL, this just checks variable can be converted.
 172 * If fentry == true and vr_die is a parameter, do huristic search
 173 * for the location fuzzed by function entry mcount.
 174 */
 175static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
 176                                     Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
 177                                     unsigned int machine,
 178                                     struct probe_trace_arg *tvar)
 179{
 180        Dwarf_Attribute attr;
 181        Dwarf_Addr tmp = 0;
 182        Dwarf_Op *op;
 183        size_t nops;
 184        unsigned int regn;
 185        Dwarf_Word offs = 0;
 186        bool ref = false;
 187        const char *regs;
 188        int ret, ret2 = 0;
 189
 190        if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
 191                goto static_var;
 192
 193        /* TODO: handle more than 1 exprs */
 194        if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
 195                return -EINVAL; /* Broken DIE ? */
 196        if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
 197                ret = dwarf_entrypc(sp_die, &tmp);
 198                if (ret)
 199                        return -ENOENT;
 200
 201                if (probe_conf.show_location_range &&
 202                        (dwarf_tag(vr_die) == DW_TAG_variable)) {
 203                        ret2 = -ERANGE;
 204                } else if (addr != tmp ||
 205                        dwarf_tag(vr_die) != DW_TAG_formal_parameter) {
 206                        return -ENOENT;
 207                }
 208
 209                ret = dwarf_highpc(sp_die, &tmp);
 210                if (ret)
 211                        return -ENOENT;
 212                /*
 213                 * This is fuzzed by fentry mcount. We try to find the
 214                 * parameter location at the earliest address.
 215                 */
 216                for (addr += 1; addr <= tmp; addr++) {
 217                        if (dwarf_getlocation_addr(&attr, addr, &op,
 218                                                   &nops, 1) > 0)
 219                                goto found;
 220                }
 221                return -ENOENT;
 222        }
 223found:
 224        if (nops == 0)
 225                /* TODO: Support const_value */
 226                return -ENOENT;
 227
 228        if (op->atom == DW_OP_addr) {
 229static_var:
 230                if (!tvar)
 231                        return ret2;
 232                /* Static variables on memory (not stack), make @varname */
 233                ret = strlen(dwarf_diename(vr_die));
 234                tvar->value = zalloc(ret + 2);
 235                if (tvar->value == NULL)
 236                        return -ENOMEM;
 237                snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
 238                tvar->ref = alloc_trace_arg_ref((long)offs);
 239                if (tvar->ref == NULL)
 240                        return -ENOMEM;
 241                return ret2;
 242        }
 243
 244        /* If this is based on frame buffer, set the offset */
 245        if (op->atom == DW_OP_fbreg) {
 246                if (fb_ops == NULL)
 247                        return -ENOTSUP;
 248                ref = true;
 249                offs = op->number;
 250                op = &fb_ops[0];
 251        }
 252
 253        if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
 254                regn = op->atom - DW_OP_breg0;
 255                offs += op->number;
 256                ref = true;
 257        } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
 258                regn = op->atom - DW_OP_reg0;
 259        } else if (op->atom == DW_OP_bregx) {
 260                regn = op->number;
 261                offs += op->number2;
 262                ref = true;
 263        } else if (op->atom == DW_OP_regx) {
 264                regn = op->number;
 265        } else {
 266                pr_debug("DW_OP %x is not supported.\n", op->atom);
 267                return -ENOTSUP;
 268        }
 269
 270        if (!tvar)
 271                return ret2;
 272
 273        regs = get_dwarf_regstr(regn, machine);
 274        if (!regs) {
 275                /* This should be a bug in DWARF or this tool */
 276                pr_warning("Mapping for the register number %u "
 277                           "missing on this architecture.\n", regn);
 278                return -ENOTSUP;
 279        }
 280
 281        tvar->value = strdup(regs);
 282        if (tvar->value == NULL)
 283                return -ENOMEM;
 284
 285        if (ref) {
 286                tvar->ref = alloc_trace_arg_ref((long)offs);
 287                if (tvar->ref == NULL)
 288                        return -ENOMEM;
 289        }
 290        return ret2;
 291}
 292
 293#define BYTES_TO_BITS(nb)       ((nb) * BITS_PER_LONG / sizeof(long))
 294
 295static int convert_variable_type(Dwarf_Die *vr_die,
 296                                 struct probe_trace_arg *tvar,
 297                                 const char *cast)
 298{
 299        struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
 300        Dwarf_Die type;
 301        char buf[16];
 302        char sbuf[STRERR_BUFSIZE];
 303        int bsize, boffs, total;
 304        int ret;
 305        char prefix;
 306
 307        /* TODO: check all types */
 308        if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
 309            strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
 310                /* Non string type is OK */
 311                /* and respect signedness/hexadecimal cast */
 312                tvar->type = strdup(cast);
 313                return (tvar->type == NULL) ? -ENOMEM : 0;
 314        }
 315
 316        bsize = dwarf_bitsize(vr_die);
 317        if (bsize > 0) {
 318                /* This is a bitfield */
 319                boffs = dwarf_bitoffset(vr_die);
 320                total = dwarf_bytesize(vr_die);
 321                if (boffs < 0 || total < 0)
 322                        return -ENOENT;
 323                ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
 324                                BYTES_TO_BITS(total));
 325                goto formatted;
 326        }
 327
 328        if (die_get_real_type(vr_die, &type) == NULL) {
 329                pr_warning("Failed to get a type information of %s.\n",
 330                           dwarf_diename(vr_die));
 331                return -ENOENT;
 332        }
 333
 334        pr_debug("%s type is %s.\n",
 335                 dwarf_diename(vr_die), dwarf_diename(&type));
 336
 337        if (cast && strcmp(cast, "string") == 0) {      /* String type */
 338                ret = dwarf_tag(&type);
 339                if (ret != DW_TAG_pointer_type &&
 340                    ret != DW_TAG_array_type) {
 341                        pr_warning("Failed to cast into string: "
 342                                   "%s(%s) is not a pointer nor array.\n",
 343                                   dwarf_diename(vr_die), dwarf_diename(&type));
 344                        return -EINVAL;
 345                }
 346                if (die_get_real_type(&type, &type) == NULL) {
 347                        pr_warning("Failed to get a type"
 348                                   " information.\n");
 349                        return -ENOENT;
 350                }
 351                if (ret == DW_TAG_pointer_type) {
 352                        while (*ref_ptr)
 353                                ref_ptr = &(*ref_ptr)->next;
 354                        /* Add new reference with offset +0 */
 355                        *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
 356                        if (*ref_ptr == NULL) {
 357                                pr_warning("Out of memory error\n");
 358                                return -ENOMEM;
 359                        }
 360                }
 361                if (!die_compare_name(&type, "char") &&
 362                    !die_compare_name(&type, "unsigned char")) {
 363                        pr_warning("Failed to cast into string: "
 364                                   "%s is not (unsigned) char *.\n",
 365                                   dwarf_diename(vr_die));
 366                        return -EINVAL;
 367                }
 368                tvar->type = strdup(cast);
 369                return (tvar->type == NULL) ? -ENOMEM : 0;
 370        }
 371
 372        if (cast && (strcmp(cast, "u") == 0))
 373                prefix = 'u';
 374        else if (cast && (strcmp(cast, "s") == 0))
 375                prefix = 's';
 376        else if (cast && (strcmp(cast, "x") == 0) &&
 377                 probe_type_is_available(PROBE_TYPE_X))
 378                prefix = 'x';
 379        else
 380                prefix = die_is_signed_type(&type) ? 's' :
 381                         probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
 382
 383        ret = dwarf_bytesize(&type);
 384        if (ret <= 0)
 385                /* No size ... try to use default type */
 386                return 0;
 387        ret = BYTES_TO_BITS(ret);
 388
 389        /* Check the bitwidth */
 390        if (ret > MAX_BASIC_TYPE_BITS) {
 391                pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
 392                        dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
 393                ret = MAX_BASIC_TYPE_BITS;
 394        }
 395        ret = snprintf(buf, 16, "%c%d", prefix, ret);
 396
 397formatted:
 398        if (ret < 0 || ret >= 16) {
 399                if (ret >= 16)
 400                        ret = -E2BIG;
 401                pr_warning("Failed to convert variable type: %s\n",
 402                           str_error_r(-ret, sbuf, sizeof(sbuf)));
 403                return ret;
 404        }
 405        tvar->type = strdup(buf);
 406        if (tvar->type == NULL)
 407                return -ENOMEM;
 408        return 0;
 409}
 410
 411static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 412                                    struct perf_probe_arg_field *field,
 413                                    struct probe_trace_arg_ref **ref_ptr,
 414                                    Dwarf_Die *die_mem)
 415{
 416        struct probe_trace_arg_ref *ref = *ref_ptr;
 417        Dwarf_Die type;
 418        Dwarf_Word offs;
 419        int ret, tag;
 420
 421        pr_debug("converting %s in %s\n", field->name, varname);
 422        if (die_get_real_type(vr_die, &type) == NULL) {
 423                pr_warning("Failed to get the type of %s.\n", varname);
 424                return -ENOENT;
 425        }
 426        pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
 427        tag = dwarf_tag(&type);
 428
 429        if (field->name[0] == '[' &&
 430            (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
 431                if (field->next)
 432                        /* Save original type for next field */
 433                        memcpy(die_mem, &type, sizeof(*die_mem));
 434                /* Get the type of this array */
 435                if (die_get_real_type(&type, &type) == NULL) {
 436                        pr_warning("Failed to get the type of %s.\n", varname);
 437                        return -ENOENT;
 438                }
 439                pr_debug2("Array real type: (%x)\n",
 440                         (unsigned)dwarf_dieoffset(&type));
 441                if (tag == DW_TAG_pointer_type) {
 442                        ref = zalloc(sizeof(struct probe_trace_arg_ref));
 443                        if (ref == NULL)
 444                                return -ENOMEM;
 445                        if (*ref_ptr)
 446                                (*ref_ptr)->next = ref;
 447                        else
 448                                *ref_ptr = ref;
 449                }
 450                ref->offset += dwarf_bytesize(&type) * field->index;
 451                if (!field->next)
 452                        /* Save vr_die for converting types */
 453                        memcpy(die_mem, vr_die, sizeof(*die_mem));
 454                goto next;
 455        } else if (tag == DW_TAG_pointer_type) {
 456                /* Check the pointer and dereference */
 457                if (!field->ref) {
 458                        pr_err("Semantic error: %s must be referred by '->'\n",
 459                               field->name);
 460                        return -EINVAL;
 461                }
 462                /* Get the type pointed by this pointer */
 463                if (die_get_real_type(&type, &type) == NULL) {
 464                        pr_warning("Failed to get the type of %s.\n", varname);
 465                        return -ENOENT;
 466                }
 467                /* Verify it is a data structure  */
 468                tag = dwarf_tag(&type);
 469                if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
 470                        pr_warning("%s is not a data structure nor a union.\n",
 471                                   varname);
 472                        return -EINVAL;
 473                }
 474
 475                ref = zalloc(sizeof(struct probe_trace_arg_ref));
 476                if (ref == NULL)
 477                        return -ENOMEM;
 478                if (*ref_ptr)
 479                        (*ref_ptr)->next = ref;
 480                else
 481                        *ref_ptr = ref;
 482        } else {
 483                /* Verify it is a data structure  */
 484                if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
 485                        pr_warning("%s is not a data structure nor a union.\n",
 486                                   varname);
 487                        return -EINVAL;
 488                }
 489                if (field->name[0] == '[') {
 490                        pr_err("Semantic error: %s is not a pointer"
 491                               " nor array.\n", varname);
 492                        return -EINVAL;
 493                }
 494                /* While prcessing unnamed field, we don't care about this */
 495                if (field->ref && dwarf_diename(vr_die)) {
 496                        pr_err("Semantic error: %s must be referred by '.'\n",
 497                               field->name);
 498                        return -EINVAL;
 499                }
 500                if (!ref) {
 501                        pr_warning("Structure on a register is not "
 502                                   "supported yet.\n");
 503                        return -ENOTSUP;
 504                }
 505        }
 506
 507        if (die_find_member(&type, field->name, die_mem) == NULL) {
 508                pr_warning("%s(type:%s) has no member %s.\n", varname,
 509                           dwarf_diename(&type), field->name);
 510                return -EINVAL;
 511        }
 512
 513        /* Get the offset of the field */
 514        if (tag == DW_TAG_union_type) {
 515                offs = 0;
 516        } else {
 517                ret = die_get_data_member_location(die_mem, &offs);
 518                if (ret < 0) {
 519                        pr_warning("Failed to get the offset of %s.\n",
 520                                   field->name);
 521                        return ret;
 522                }
 523        }
 524        ref->offset += (long)offs;
 525
 526        /* If this member is unnamed, we need to reuse this field */
 527        if (!dwarf_diename(die_mem))
 528                return convert_variable_fields(die_mem, varname, field,
 529                                                &ref, die_mem);
 530
 531next:
 532        /* Converting next field */
 533        if (field->next)
 534                return convert_variable_fields(die_mem, field->name,
 535                                        field->next, &ref, die_mem);
 536        else
 537                return 0;
 538}
 539
 540/* Show a variables in kprobe event format */
 541static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 542{
 543        Dwarf_Die die_mem;
 544        int ret;
 545
 546        pr_debug("Converting variable %s into trace event.\n",
 547                 dwarf_diename(vr_die));
 548
 549        ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
 550                                        &pf->sp_die, pf->machine, pf->tvar);
 551        if (ret == -ENOENT || ret == -EINVAL) {
 552                pr_err("Failed to find the location of the '%s' variable at this address.\n"
 553                       " Perhaps it has been optimized out.\n"
 554                       " Use -V with the --range option to show '%s' location range.\n",
 555                       pf->pvar->var, pf->pvar->var);
 556        } else if (ret == -ENOTSUP)
 557                pr_err("Sorry, we don't support this variable location yet.\n");
 558        else if (ret == 0 && pf->pvar->field) {
 559                ret = convert_variable_fields(vr_die, pf->pvar->var,
 560                                              pf->pvar->field, &pf->tvar->ref,
 561                                              &die_mem);
 562                vr_die = &die_mem;
 563        }
 564        if (ret == 0)
 565                ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
 566        /* *expr will be cached in libdw. Don't free it. */
 567        return ret;
 568}
 569
 570/* Find a variable in a scope DIE */
 571static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 572{
 573        Dwarf_Die vr_die;
 574        char *buf, *ptr;
 575        int ret = 0;
 576
 577        /* Copy raw parameters */
 578        if (!is_c_varname(pf->pvar->var))
 579                return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
 580
 581        if (pf->pvar->name)
 582                pf->tvar->name = strdup(pf->pvar->name);
 583        else {
 584                buf = synthesize_perf_probe_arg(pf->pvar);
 585                if (!buf)
 586                        return -ENOMEM;
 587                ptr = strchr(buf, ':'); /* Change type separator to _ */
 588                if (ptr)
 589                        *ptr = '_';
 590                pf->tvar->name = buf;
 591        }
 592        if (pf->tvar->name == NULL)
 593                return -ENOMEM;
 594
 595        pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
 596        /* Search child die for local variables and parameters. */
 597        if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
 598                /* Search again in global variables */
 599                if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
 600                                                0, &vr_die)) {
 601                        pr_warning("Failed to find '%s' in this function.\n",
 602                                   pf->pvar->var);
 603                        ret = -ENOENT;
 604                }
 605        }
 606        if (ret >= 0)
 607                ret = convert_variable(&vr_die, pf);
 608
 609        return ret;
 610}
 611
 612/* Convert subprogram DIE to trace point */
 613static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
 614                                  Dwarf_Addr paddr, bool retprobe,
 615                                  const char *function,
 616                                  struct probe_trace_point *tp)
 617{
 618        Dwarf_Addr eaddr, highaddr;
 619        GElf_Sym sym;
 620        const char *symbol;
 621
 622        /* Verify the address is correct */
 623        if (dwarf_entrypc(sp_die, &eaddr) != 0) {
 624                pr_warning("Failed to get entry address of %s\n",
 625                           dwarf_diename(sp_die));
 626                return -ENOENT;
 627        }
 628        if (dwarf_highpc(sp_die, &highaddr) != 0) {
 629                pr_warning("Failed to get end address of %s\n",
 630                           dwarf_diename(sp_die));
 631                return -ENOENT;
 632        }
 633        if (paddr > highaddr) {
 634                pr_warning("Offset specified is greater than size of %s\n",
 635                           dwarf_diename(sp_die));
 636                return -EINVAL;
 637        }
 638
 639        symbol = dwarf_diename(sp_die);
 640        if (!symbol) {
 641                /* Try to get the symbol name from symtab */
 642                symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
 643                if (!symbol) {
 644                        pr_warning("Failed to find symbol at 0x%lx\n",
 645                                   (unsigned long)paddr);
 646                        return -ENOENT;
 647                }
 648                eaddr = sym.st_value;
 649        }
 650        tp->offset = (unsigned long)(paddr - eaddr);
 651        tp->address = (unsigned long)paddr;
 652        tp->symbol = strdup(symbol);
 653        if (!tp->symbol)
 654                return -ENOMEM;
 655
 656        /* Return probe must be on the head of a subprogram */
 657        if (retprobe) {
 658                if (eaddr != paddr) {
 659                        pr_warning("Failed to find \"%s%%return\",\n"
 660                                   " because %s is an inlined function and"
 661                                   " has no return point.\n", function,
 662                                   function);
 663                        return -EINVAL;
 664                }
 665                tp->retprobe = true;
 666        }
 667
 668        return 0;
 669}
 670
 671/* Call probe_finder callback with scope DIE */
 672static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
 673{
 674        Dwarf_Attribute fb_attr;
 675        Dwarf_Frame *frame = NULL;
 676        size_t nops;
 677        int ret;
 678
 679        if (!sc_die) {
 680                pr_err("Caller must pass a scope DIE. Program error.\n");
 681                return -EINVAL;
 682        }
 683
 684        /* If not a real subprogram, find a real one */
 685        if (!die_is_func_def(sc_die)) {
 686                if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
 687                        if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
 688                                pr_warning("Ignoring tail call from %s\n",
 689                                                dwarf_diename(&pf->sp_die));
 690                                return 0;
 691                        } else {
 692                                pr_warning("Failed to find probe point in any "
 693                                           "functions.\n");
 694                                return -ENOENT;
 695                        }
 696                }
 697        } else
 698                memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
 699
 700        /* Get the frame base attribute/ops from subprogram */
 701        dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
 702        ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
 703        if (ret <= 0 || nops == 0) {
 704                pf->fb_ops = NULL;
 705#if _ELFUTILS_PREREQ(0, 142)
 706        } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
 707                   (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
 708                if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
 709                     (dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
 710                    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
 711                        pr_warning("Failed to get call frame on 0x%jx\n",
 712                                   (uintmax_t)pf->addr);
 713                        free(frame);
 714                        return -ENOENT;
 715                }
 716#endif
 717        }
 718
 719        /* Call finder's callback handler */
 720        ret = pf->callback(sc_die, pf);
 721
 722        /* Since *pf->fb_ops can be a part of frame. we should free it here. */
 723        free(frame);
 724        pf->fb_ops = NULL;
 725
 726        return ret;
 727}
 728
 729struct find_scope_param {
 730        const char *function;
 731        const char *file;
 732        int line;
 733        int diff;
 734        Dwarf_Die *die_mem;
 735        bool found;
 736};
 737
 738static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
 739{
 740        struct find_scope_param *fsp = data;
 741        const char *file;
 742        int lno;
 743
 744        /* Skip if declared file name does not match */
 745        if (fsp->file) {
 746                file = dwarf_decl_file(fn_die);
 747                if (!file || strcmp(fsp->file, file) != 0)
 748                        return 0;
 749        }
 750        /* If the function name is given, that's what user expects */
 751        if (fsp->function) {
 752                if (die_match_name(fn_die, fsp->function)) {
 753                        memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
 754                        fsp->found = true;
 755                        return 1;
 756                }
 757        } else {
 758                /* With the line number, find the nearest declared DIE */
 759                dwarf_decl_line(fn_die, &lno);
 760                if (lno < fsp->line && fsp->diff > fsp->line - lno) {
 761                        /* Keep a candidate and continue */
 762                        fsp->diff = fsp->line - lno;
 763                        memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
 764                        fsp->found = true;
 765                }
 766        }
 767        return 0;
 768}
 769
 770/* Find an appropriate scope fits to given conditions */
 771static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
 772{
 773        struct find_scope_param fsp = {
 774                .function = pf->pev->point.function,
 775                .file = pf->fname,
 776                .line = pf->lno,
 777                .diff = INT_MAX,
 778                .die_mem = die_mem,
 779                .found = false,
 780        };
 781
 782        cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
 783
 784        return fsp.found ? die_mem : NULL;
 785}
 786
 787static int probe_point_line_walker(const char *fname, int lineno,
 788                                   Dwarf_Addr addr, void *data)
 789{
 790        struct probe_finder *pf = data;
 791        Dwarf_Die *sc_die, die_mem;
 792        int ret;
 793
 794        if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
 795                return 0;
 796
 797        pf->addr = addr;
 798        sc_die = find_best_scope(pf, &die_mem);
 799        if (!sc_die) {
 800                pr_warning("Failed to find scope of probe point.\n");
 801                return -ENOENT;
 802        }
 803
 804        ret = call_probe_finder(sc_die, pf);
 805
 806        /* Continue if no error, because the line will be in inline function */
 807        return ret < 0 ? ret : 0;
 808}
 809
 810/* Find probe point from its line number */
 811static int find_probe_point_by_line(struct probe_finder *pf)
 812{
 813        return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
 814}
 815
 816/* Find lines which match lazy pattern */
 817static int find_lazy_match_lines(struct intlist *list,
 818                                 const char *fname, const char *pat)
 819{
 820        FILE *fp;
 821        char *line = NULL;
 822        size_t line_len;
 823        ssize_t len;
 824        int count = 0, linenum = 1;
 825        char sbuf[STRERR_BUFSIZE];
 826
 827        fp = fopen(fname, "r");
 828        if (!fp) {
 829                pr_warning("Failed to open %s: %s\n", fname,
 830                           str_error_r(errno, sbuf, sizeof(sbuf)));
 831                return -errno;
 832        }
 833
 834        while ((len = getline(&line, &line_len, fp)) > 0) {
 835
 836                if (line[len - 1] == '\n')
 837                        line[len - 1] = '\0';
 838
 839                if (strlazymatch(line, pat)) {
 840                        intlist__add(list, linenum);
 841                        count++;
 842                }
 843                linenum++;
 844        }
 845
 846        if (ferror(fp))
 847                count = -errno;
 848        free(line);
 849        fclose(fp);
 850
 851        if (count == 0)
 852                pr_debug("No matched lines found in %s.\n", fname);
 853        return count;
 854}
 855
 856static int probe_point_lazy_walker(const char *fname, int lineno,
 857                                   Dwarf_Addr addr, void *data)
 858{
 859        struct probe_finder *pf = data;
 860        Dwarf_Die *sc_die, die_mem;
 861        int ret;
 862
 863        if (!intlist__has_entry(pf->lcache, lineno) ||
 864            strtailcmp(fname, pf->fname) != 0)
 865                return 0;
 866
 867        pr_debug("Probe line found: line:%d addr:0x%llx\n",
 868                 lineno, (unsigned long long)addr);
 869        pf->addr = addr;
 870        pf->lno = lineno;
 871        sc_die = find_best_scope(pf, &die_mem);
 872        if (!sc_die) {
 873                pr_warning("Failed to find scope of probe point.\n");
 874                return -ENOENT;
 875        }
 876
 877        ret = call_probe_finder(sc_die, pf);
 878
 879        /*
 880         * Continue if no error, because the lazy pattern will match
 881         * to other lines
 882         */
 883        return ret < 0 ? ret : 0;
 884}
 885
 886/* Find probe points from lazy pattern  */
 887static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 888{
 889        int ret = 0;
 890        char *fpath;
 891
 892        if (intlist__empty(pf->lcache)) {
 893                const char *comp_dir;
 894
 895                comp_dir = cu_get_comp_dir(&pf->cu_die);
 896                ret = get_real_path(pf->fname, comp_dir, &fpath);
 897                if (ret < 0) {
 898                        pr_warning("Failed to find source file path.\n");
 899                        return ret;
 900                }
 901
 902                /* Matching lazy line pattern */
 903                ret = find_lazy_match_lines(pf->lcache, fpath,
 904                                            pf->pev->point.lazy_line);
 905                free(fpath);
 906                if (ret <= 0)
 907                        return ret;
 908        }
 909
 910        return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 911}
 912
 913static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 914{
 915        struct perf_probe_point *pp = &pf->pev->point;
 916
 917        /* Not uprobe? */
 918        if (!pf->pev->uprobes)
 919                return;
 920
 921        /* Compiled with optimization? */
 922        if (die_is_optimized_target(&pf->cu_die))
 923                return;
 924
 925        /* Don't know entrypc? */
 926        if (!pf->addr)
 927                return;
 928
 929        /* Only FUNC and FUNC@SRC are eligible. */
 930        if (!pp->function || pp->line || pp->retprobe || pp->lazy_line ||
 931            pp->offset || pp->abs_address)
 932                return;
 933
 934        /* Not interested in func parameter? */
 935        if (!perf_probe_with_var(pf->pev))
 936                return;
 937
 938        pr_info("Target program is compiled without optimization. Skipping prologue.\n"
 939                "Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
 940                pf->addr);
 941
 942        die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
 943}
 944
 945static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 946{
 947        struct probe_finder *pf = data;
 948        struct perf_probe_point *pp = &pf->pev->point;
 949        Dwarf_Addr addr;
 950        int ret;
 951
 952        if (pp->lazy_line)
 953                ret = find_probe_point_lazy(in_die, pf);
 954        else {
 955                /* Get probe address */
 956                if (dwarf_entrypc(in_die, &addr) != 0) {
 957                        pr_warning("Failed to get entry address of %s.\n",
 958                                   dwarf_diename(in_die));
 959                        return -ENOENT;
 960                }
 961                if (addr == 0) {
 962                        pr_debug("%s has no valid entry address. skipped.\n",
 963                                 dwarf_diename(in_die));
 964                        return -ENOENT;
 965                }
 966                pf->addr = addr;
 967                pf->addr += pp->offset;
 968                pr_debug("found inline addr: 0x%jx\n",
 969                         (uintmax_t)pf->addr);
 970
 971                ret = call_probe_finder(in_die, pf);
 972        }
 973
 974        return ret;
 975}
 976
 977/* Callback parameter with return value for libdw */
 978struct dwarf_callback_param {
 979        void *data;
 980        int retval;
 981};
 982
 983/* Search function from function name */
 984static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
 985{
 986        struct dwarf_callback_param *param = data;
 987        struct probe_finder *pf = param->data;
 988        struct perf_probe_point *pp = &pf->pev->point;
 989
 990        /* Check tag and diename */
 991        if (!die_is_func_def(sp_die) ||
 992            !die_match_name(sp_die, pp->function))
 993                return DWARF_CB_OK;
 994
 995        /* Check declared file */
 996        if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
 997                return DWARF_CB_OK;
 998
 999        pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
1000                 (unsigned long)dwarf_dieoffset(sp_die));
1001        pf->fname = dwarf_decl_file(sp_die);
1002        if (pp->line) { /* Function relative line */
1003                dwarf_decl_line(sp_die, &pf->lno);
1004                pf->lno += pp->line;
1005                param->retval = find_probe_point_by_line(pf);
1006        } else if (die_is_func_instance(sp_die)) {
1007                /* Instances always have the entry address */
1008                dwarf_entrypc(sp_die, &pf->addr);
1009                /* But in some case the entry address is 0 */
1010                if (pf->addr == 0) {
1011                        pr_debug("%s has no entry PC. Skipped\n",
1012                                 dwarf_diename(sp_die));
1013                        param->retval = 0;
1014                /* Real function */
1015                } else if (pp->lazy_line)
1016                        param->retval = find_probe_point_lazy(sp_die, pf);
1017                else {
1018                        skip_prologue(sp_die, pf);
1019                        pf->addr += pp->offset;
1020                        /* TODO: Check the address in this function */
1021                        param->retval = call_probe_finder(sp_die, pf);
1022                }
1023        } else if (!probe_conf.no_inlines) {
1024                /* Inlined function: search instances */
1025                param->retval = die_walk_instances(sp_die,
1026                                        probe_point_inline_cb, (void *)pf);
1027                /* This could be a non-existed inline definition */
1028                if (param->retval == -ENOENT)
1029                        param->retval = 0;
1030        }
1031
1032        /* We need to find other candidates */
1033        if (strisglob(pp->function) && param->retval >= 0) {
1034                param->retval = 0;      /* We have to clear the result */
1035                return DWARF_CB_OK;
1036        }
1037
1038        return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1039}
1040
1041static int find_probe_point_by_func(struct probe_finder *pf)
1042{
1043        struct dwarf_callback_param _param = {.data = (void *)pf,
1044                                              .retval = 0};
1045        dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1046        return _param.retval;
1047}
1048
1049struct pubname_callback_param {
1050        char *function;
1051        char *file;
1052        Dwarf_Die *cu_die;
1053        Dwarf_Die *sp_die;
1054        int found;
1055};
1056
1057static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
1058{
1059        struct pubname_callback_param *param = data;
1060
1061        if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
1062                if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
1063                        return DWARF_CB_OK;
1064
1065                if (die_match_name(param->sp_die, param->function)) {
1066                        if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
1067                                return DWARF_CB_OK;
1068
1069                        if (param->file &&
1070                            strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
1071                                return DWARF_CB_OK;
1072
1073                        param->found = 1;
1074                        return DWARF_CB_ABORT;
1075                }
1076        }
1077
1078        return DWARF_CB_OK;
1079}
1080
1081static int debuginfo__find_probe_location(struct debuginfo *dbg,
1082                                  struct probe_finder *pf)
1083{
1084        struct perf_probe_point *pp = &pf->pev->point;
1085        Dwarf_Off off, noff;
1086        size_t cuhl;
1087        Dwarf_Die *diep;
1088        int ret = 0;
1089
1090        off = 0;
1091        pf->lcache = intlist__new(NULL);
1092        if (!pf->lcache)
1093                return -ENOMEM;
1094
1095        /* Fastpath: lookup by function name from .debug_pubnames section */
1096        if (pp->function && !strisglob(pp->function)) {
1097                struct pubname_callback_param pubname_param = {
1098                        .function = pp->function,
1099                        .file     = pp->file,
1100                        .cu_die   = &pf->cu_die,
1101                        .sp_die   = &pf->sp_die,
1102                        .found    = 0,
1103                };
1104                struct dwarf_callback_param probe_param = {
1105                        .data = pf,
1106                };
1107
1108                dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1109                                  &pubname_param, 0);
1110                if (pubname_param.found) {
1111                        ret = probe_point_search_cb(&pf->sp_die, &probe_param);
1112                        if (ret)
1113                                goto found;
1114                }
1115        }
1116
1117        /* Loop on CUs (Compilation Unit) */
1118        while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1119                /* Get the DIE(Debugging Information Entry) of this CU */
1120                diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1121                if (!diep)
1122                        continue;
1123
1124                /* Check if target file is included. */
1125                if (pp->file)
1126                        pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1127                else
1128                        pf->fname = NULL;
1129
1130                if (!pp->file || pf->fname) {
1131                        if (pp->function)
1132                                ret = find_probe_point_by_func(pf);
1133                        else if (pp->lazy_line)
1134                                ret = find_probe_point_lazy(&pf->cu_die, pf);
1135                        else {
1136                                pf->lno = pp->line;
1137                                ret = find_probe_point_by_line(pf);
1138                        }
1139                        if (ret < 0)
1140                                break;
1141                }
1142                off = noff;
1143        }
1144
1145found:
1146        intlist__delete(pf->lcache);
1147        pf->lcache = NULL;
1148
1149        return ret;
1150}
1151
1152/* Find probe points from debuginfo */
1153static int debuginfo__find_probes(struct debuginfo *dbg,
1154                                  struct probe_finder *pf)
1155{
1156        int ret = 0;
1157        Elf *elf;
1158        GElf_Ehdr ehdr;
1159
1160        if (pf->cfi_eh || pf->cfi_dbg)
1161                return debuginfo__find_probe_location(dbg, pf);
1162
1163        /* Get the call frame information from this dwarf */
1164        elf = dwarf_getelf(dbg->dbg);
1165        if (elf == NULL)
1166                return -EINVAL;
1167
1168        if (gelf_getehdr(elf, &ehdr) == NULL)
1169                return -EINVAL;
1170
1171        pf->machine = ehdr.e_machine;
1172
1173#if _ELFUTILS_PREREQ(0, 142)
1174        do {
1175                GElf_Shdr shdr;
1176
1177                if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1178                    shdr.sh_type == SHT_PROGBITS)
1179                        pf->cfi_eh = dwarf_getcfi_elf(elf);
1180
1181                pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1182        } while (0);
1183#endif
1184
1185        ret = debuginfo__find_probe_location(dbg, pf);
1186        return ret;
1187}
1188
1189struct local_vars_finder {
1190        struct probe_finder *pf;
1191        struct perf_probe_arg *args;
1192        bool vars;
1193        int max_args;
1194        int nargs;
1195        int ret;
1196};
1197
1198/* Collect available variables in this scope */
1199static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1200{
1201        struct local_vars_finder *vf = data;
1202        struct probe_finder *pf = vf->pf;
1203        int tag;
1204
1205        tag = dwarf_tag(die_mem);
1206        if (tag == DW_TAG_formal_parameter ||
1207            (tag == DW_TAG_variable && vf->vars)) {
1208                if (convert_variable_location(die_mem, vf->pf->addr,
1209                                              vf->pf->fb_ops, &pf->sp_die,
1210                                              pf->machine, NULL) == 0) {
1211                        vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1212                        if (vf->args[vf->nargs].var == NULL) {
1213                                vf->ret = -ENOMEM;
1214                                return DIE_FIND_CB_END;
1215                        }
1216                        pr_debug(" %s", vf->args[vf->nargs].var);
1217                        vf->nargs++;
1218                }
1219        }
1220
1221        if (dwarf_haspc(die_mem, vf->pf->addr))
1222                return DIE_FIND_CB_CONTINUE;
1223        else
1224                return DIE_FIND_CB_SIBLING;
1225}
1226
1227static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1228                             struct perf_probe_arg *args)
1229{
1230        Dwarf_Die die_mem;
1231        int i;
1232        int n = 0;
1233        struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
1234                                .max_args = MAX_PROBE_ARGS, .ret = 0};
1235
1236        for (i = 0; i < pf->pev->nargs; i++) {
1237                /* var never be NULL */
1238                if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0)
1239                        vf.vars = true;
1240                else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) {
1241                        /* Copy normal argument */
1242                        args[n] = pf->pev->args[i];
1243                        n++;
1244                        continue;
1245                }
1246                pr_debug("Expanding %s into:", pf->pev->args[i].var);
1247                vf.nargs = n;
1248                /* Special local variables */
1249                die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1250                               &die_mem);
1251                pr_debug(" (%d)\n", vf.nargs - n);
1252                if (vf.ret < 0)
1253                        return vf.ret;
1254                n = vf.nargs;
1255        }
1256        return n;
1257}
1258
1259/* Add a found probe point into trace event list */
1260static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1261{
1262        struct trace_event_finder *tf =
1263                        container_of(pf, struct trace_event_finder, pf);
1264        struct perf_probe_point *pp = &pf->pev->point;
1265        struct probe_trace_event *tev;
1266        struct perf_probe_arg *args = NULL;
1267        int ret, i;
1268
1269        /* Check number of tevs */
1270        if (tf->ntevs == tf->max_tevs) {
1271                pr_warning("Too many( > %d) probe point found.\n",
1272                           tf->max_tevs);
1273                return -ERANGE;
1274        }
1275        tev = &tf->tevs[tf->ntevs++];
1276
1277        /* Trace point should be converted from subprogram DIE */
1278        ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1279                                     pp->retprobe, pp->function, &tev->point);
1280        if (ret < 0)
1281                goto end;
1282
1283        tev->point.realname = strdup(dwarf_diename(sc_die));
1284        if (!tev->point.realname) {
1285                ret = -ENOMEM;
1286                goto end;
1287        }
1288
1289        pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1290                 tev->point.offset);
1291
1292        /* Expand special probe argument if exist */
1293        args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1294        if (args == NULL) {
1295                ret = -ENOMEM;
1296                goto end;
1297        }
1298
1299        ret = expand_probe_args(sc_die, pf, args);
1300        if (ret < 0)
1301                goto end;
1302
1303        tev->nargs = ret;
1304        tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1305        if (tev->args == NULL) {
1306                ret = -ENOMEM;
1307                goto end;
1308        }
1309
1310        /* Find each argument */
1311        for (i = 0; i < tev->nargs; i++) {
1312                pf->pvar = &args[i];
1313                pf->tvar = &tev->args[i];
1314                /* Variable should be found from scope DIE */
1315                ret = find_variable(sc_die, pf);
1316                if (ret != 0)
1317                        break;
1318        }
1319
1320end:
1321        if (ret) {
1322                clear_probe_trace_event(tev);
1323                tf->ntevs--;
1324        }
1325        free(args);
1326        return ret;
1327}
1328
1329/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1330int debuginfo__find_trace_events(struct debuginfo *dbg,
1331                                 struct perf_probe_event *pev,
1332                                 struct probe_trace_event **tevs)
1333{
1334        struct trace_event_finder tf = {
1335                        .pf = {.pev = pev, .callback = add_probe_trace_event},
1336                        .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
1337        int ret, i;
1338
1339        /* Allocate result tevs array */
1340        *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
1341        if (*tevs == NULL)
1342                return -ENOMEM;
1343
1344        tf.tevs = *tevs;
1345        tf.ntevs = 0;
1346
1347        ret = debuginfo__find_probes(dbg, &tf.pf);
1348        if (ret < 0) {
1349                for (i = 0; i < tf.ntevs; i++)
1350                        clear_probe_trace_event(&tf.tevs[i]);
1351                zfree(tevs);
1352                return ret;
1353        }
1354
1355        return (ret < 0) ? ret : tf.ntevs;
1356}
1357
1358/* Collect available variables in this scope */
1359static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1360{
1361        struct available_var_finder *af = data;
1362        struct variable_list *vl;
1363        struct strbuf buf = STRBUF_INIT;
1364        int tag, ret;
1365
1366        vl = &af->vls[af->nvls - 1];
1367
1368        tag = dwarf_tag(die_mem);
1369        if (tag == DW_TAG_formal_parameter ||
1370            tag == DW_TAG_variable) {
1371                ret = convert_variable_location(die_mem, af->pf.addr,
1372                                                af->pf.fb_ops, &af->pf.sp_die,
1373                                                af->pf.machine, NULL);
1374                if (ret == 0 || ret == -ERANGE) {
1375                        int ret2;
1376                        bool externs = !af->child;
1377
1378                        if (strbuf_init(&buf, 64) < 0)
1379                                goto error;
1380
1381                        if (probe_conf.show_location_range) {
1382                                if (!externs)
1383                                        ret2 = strbuf_add(&buf,
1384                                                ret ? "[INV]\t" : "[VAL]\t", 6);
1385                                else
1386                                        ret2 = strbuf_add(&buf, "[EXT]\t", 6);
1387                                if (ret2)
1388                                        goto error;
1389                        }
1390
1391                        ret2 = die_get_varname(die_mem, &buf);
1392
1393                        if (!ret2 && probe_conf.show_location_range &&
1394                                !externs) {
1395                                if (strbuf_addch(&buf, '\t') < 0)
1396                                        goto error;
1397                                ret2 = die_get_var_range(&af->pf.sp_die,
1398                                                        die_mem, &buf);
1399                        }
1400
1401                        pr_debug("Add new var: %s\n", buf.buf);
1402                        if (ret2 == 0) {
1403                                strlist__add(vl->vars,
1404                                        strbuf_detach(&buf, NULL));
1405                        }
1406                        strbuf_release(&buf);
1407                }
1408        }
1409
1410        if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1411                return DIE_FIND_CB_CONTINUE;
1412        else
1413                return DIE_FIND_CB_SIBLING;
1414error:
1415        strbuf_release(&buf);
1416        pr_debug("Error in strbuf\n");
1417        return DIE_FIND_CB_END;
1418}
1419
1420/* Add a found vars into available variables list */
1421static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1422{
1423        struct available_var_finder *af =
1424                        container_of(pf, struct available_var_finder, pf);
1425        struct perf_probe_point *pp = &pf->pev->point;
1426        struct variable_list *vl;
1427        Dwarf_Die die_mem;
1428        int ret;
1429
1430        /* Check number of tevs */
1431        if (af->nvls == af->max_vls) {
1432                pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1433                return -ERANGE;
1434        }
1435        vl = &af->vls[af->nvls++];
1436
1437        /* Trace point should be converted from subprogram DIE */
1438        ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1439                                     pp->retprobe, pp->function, &vl->point);
1440        if (ret < 0)
1441                return ret;
1442
1443        pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1444                 vl->point.offset);
1445
1446        /* Find local variables */
1447        vl->vars = strlist__new(NULL, NULL);
1448        if (vl->vars == NULL)
1449                return -ENOMEM;
1450        af->child = true;
1451        die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1452
1453        /* Find external variables */
1454        if (!probe_conf.show_ext_vars)
1455                goto out;
1456        /* Don't need to search child DIE for external vars. */
1457        af->child = false;
1458        die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1459
1460out:
1461        if (strlist__empty(vl->vars)) {
1462                strlist__delete(vl->vars);
1463                vl->vars = NULL;
1464        }
1465
1466        return ret;
1467}
1468
1469/*
1470 * Find available variables at given probe point
1471 * Return the number of found probe points. Return 0 if there is no
1472 * matched probe point. Return <0 if an error occurs.
1473 */
1474int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1475                                      struct perf_probe_event *pev,
1476                                      struct variable_list **vls)
1477{
1478        struct available_var_finder af = {
1479                        .pf = {.pev = pev, .callback = add_available_vars},
1480                        .mod = dbg->mod,
1481                        .max_vls = probe_conf.max_probes};
1482        int ret;
1483
1484        /* Allocate result vls array */
1485        *vls = zalloc(sizeof(struct variable_list) * af.max_vls);
1486        if (*vls == NULL)
1487                return -ENOMEM;
1488
1489        af.vls = *vls;
1490        af.nvls = 0;
1491
1492        ret = debuginfo__find_probes(dbg, &af.pf);
1493        if (ret < 0) {
1494                /* Free vlist for error */
1495                while (af.nvls--) {
1496                        zfree(&af.vls[af.nvls].point.symbol);
1497                        strlist__delete(af.vls[af.nvls].vars);
1498                }
1499                zfree(vls);
1500                return ret;
1501        }
1502
1503        return (ret < 0) ? ret : af.nvls;
1504}
1505
1506/* For the kernel module, we need a special code to get a DIE */
1507int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
1508                                bool adjust_offset)
1509{
1510        int n, i;
1511        Elf32_Word shndx;
1512        Elf_Scn *scn;
1513        Elf *elf;
1514        GElf_Shdr mem, *shdr;
1515        const char *p;
1516
1517        elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
1518        if (!elf)
1519                return -EINVAL;
1520
1521        /* Get the number of relocations */
1522        n = dwfl_module_relocations(dbg->mod);
1523        if (n < 0)
1524                return -ENOENT;
1525        /* Search the relocation related .text section */
1526        for (i = 0; i < n; i++) {
1527                p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
1528                if (strcmp(p, ".text") == 0) {
1529                        /* OK, get the section header */
1530                        scn = elf_getscn(elf, shndx);
1531                        if (!scn)
1532                                return -ENOENT;
1533                        shdr = gelf_getshdr(scn, &mem);
1534                        if (!shdr)
1535                                return -ENOENT;
1536                        *offs = shdr->sh_addr;
1537                        if (adjust_offset)
1538                                *offs -= shdr->sh_offset;
1539                }
1540        }
1541        return 0;
1542}
1543
1544/* Reverse search */
1545int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1546                                struct perf_probe_point *ppt)
1547{
1548        Dwarf_Die cudie, spdie, indie;
1549        Dwarf_Addr _addr = 0, baseaddr = 0;
1550        const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1551        int baseline = 0, lineno = 0, ret = 0;
1552
1553        /* We always need to relocate the address for aranges */
1554        if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
1555                addr += baseaddr;
1556        /* Find cu die */
1557        if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1558                pr_warning("Failed to find debug information for address %lx\n",
1559                           addr);
1560                ret = -EINVAL;
1561                goto end;
1562        }
1563
1564        /* Find a corresponding line (filename and lineno) */
1565        cu_find_lineinfo(&cudie, addr, &fname, &lineno);
1566        /* Don't care whether it failed or not */
1567
1568        /* Find a corresponding function (name, baseline and baseaddr) */
1569        if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1570                /* Get function entry information */
1571                func = basefunc = dwarf_diename(&spdie);
1572                if (!func ||
1573                    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1574                    dwarf_decl_line(&spdie, &baseline) != 0) {
1575                        lineno = 0;
1576                        goto post;
1577                }
1578
1579                fname = dwarf_decl_file(&spdie);
1580                if (addr == (unsigned long)baseaddr) {
1581                        /* Function entry - Relative line number is 0 */
1582                        lineno = baseline;
1583                        goto post;
1584                }
1585
1586                /* Track down the inline functions step by step */
1587                while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
1588                                                &indie)) {
1589                        /* There is an inline function */
1590                        if (dwarf_entrypc(&indie, &_addr) == 0 &&
1591                            _addr == addr) {
1592                                /*
1593                                 * addr is at an inline function entry.
1594                                 * In this case, lineno should be the call-site
1595                                 * line number. (overwrite lineinfo)
1596                                 */
1597                                lineno = die_get_call_lineno(&indie);
1598                                fname = die_get_call_file(&indie);
1599                                break;
1600                        } else {
1601                                /*
1602                                 * addr is in an inline function body.
1603                                 * Since lineno points one of the lines
1604                                 * of the inline function, baseline should
1605                                 * be the entry line of the inline function.
1606                                 */
1607                                tmp = dwarf_diename(&indie);
1608                                if (!tmp ||
1609                                    dwarf_decl_line(&indie, &baseline) != 0)
1610                                        break;
1611                                func = tmp;
1612                                spdie = indie;
1613                        }
1614                }
1615                /* Verify the lineno and baseline are in a same file */
1616                tmp = dwarf_decl_file(&spdie);
1617                if (!tmp || strcmp(tmp, fname) != 0)
1618                        lineno = 0;
1619        }
1620
1621post:
1622        /* Make a relative line number or an offset */
1623        if (lineno)
1624                ppt->line = lineno - baseline;
1625        else if (basefunc) {
1626                ppt->offset = addr - (unsigned long)baseaddr;
1627                func = basefunc;
1628        }
1629
1630        /* Duplicate strings */
1631        if (func) {
1632                ppt->function = strdup(func);
1633                if (ppt->function == NULL) {
1634                        ret = -ENOMEM;
1635                        goto end;
1636                }
1637        }
1638        if (fname) {
1639                ppt->file = strdup(fname);
1640                if (ppt->file == NULL) {
1641                        zfree(&ppt->function);
1642                        ret = -ENOMEM;
1643                        goto end;
1644                }
1645        }
1646end:
1647        if (ret == 0 && (fname || func))
1648                ret = 1;        /* Found a point */
1649        return ret;
1650}
1651
1652/* Add a line and store the src path */
1653static int line_range_add_line(const char *src, unsigned int lineno,
1654                               struct line_range *lr)
1655{
1656        /* Copy source path */
1657        if (!lr->path) {
1658                lr->path = strdup(src);
1659                if (lr->path == NULL)
1660                        return -ENOMEM;
1661        }
1662        return intlist__add(lr->line_list, lineno);
1663}
1664
1665static int line_range_walk_cb(const char *fname, int lineno,
1666                              Dwarf_Addr addr __maybe_unused,
1667                              void *data)
1668{
1669        struct line_finder *lf = data;
1670        int err;
1671
1672        if ((strtailcmp(fname, lf->fname) != 0) ||
1673            (lf->lno_s > lineno || lf->lno_e < lineno))
1674                return 0;
1675
1676        err = line_range_add_line(fname, lineno, lf->lr);
1677        if (err < 0 && err != -EEXIST)
1678                return err;
1679
1680        return 0;
1681}
1682
1683/* Find line range from its line number */
1684static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1685{
1686        int ret;
1687
1688        ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1689
1690        /* Update status */
1691        if (ret >= 0)
1692                if (!intlist__empty(lf->lr->line_list))
1693                        ret = lf->found = 1;
1694                else
1695                        ret = 0;        /* Lines are not found */
1696        else {
1697                zfree(&lf->lr->path);
1698        }
1699        return ret;
1700}
1701
1702static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1703{
1704        int ret = find_line_range_by_line(in_die, data);
1705
1706        /*
1707         * We have to check all instances of inlined function, because
1708         * some execution paths can be optimized out depends on the
1709         * function argument of instances. However, if an error occurs,
1710         * it should be handled by the caller.
1711         */
1712        return ret < 0 ? ret : 0;
1713}
1714
1715/* Search function definition from function name */
1716static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1717{
1718        struct dwarf_callback_param *param = data;
1719        struct line_finder *lf = param->data;
1720        struct line_range *lr = lf->lr;
1721
1722        /* Check declared file */
1723        if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
1724                return DWARF_CB_OK;
1725
1726        if (die_is_func_def(sp_die) &&
1727            die_match_name(sp_die, lr->function)) {
1728                lf->fname = dwarf_decl_file(sp_die);
1729                dwarf_decl_line(sp_die, &lr->offset);
1730                pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1731                lf->lno_s = lr->offset + lr->start;
1732                if (lf->lno_s < 0)      /* Overflow */
1733                        lf->lno_s = INT_MAX;
1734                lf->lno_e = lr->offset + lr->end;
1735                if (lf->lno_e < 0)      /* Overflow */
1736                        lf->lno_e = INT_MAX;
1737                pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1738                lr->start = lf->lno_s;
1739                lr->end = lf->lno_e;
1740                if (!die_is_func_instance(sp_die))
1741                        param->retval = die_walk_instances(sp_die,
1742                                                line_range_inline_cb, lf);
1743                else
1744                        param->retval = find_line_range_by_line(sp_die, lf);
1745                return DWARF_CB_ABORT;
1746        }
1747        return DWARF_CB_OK;
1748}
1749
1750static int find_line_range_by_func(struct line_finder *lf)
1751{
1752        struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1753        dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1754        return param.retval;
1755}
1756
1757int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1758{
1759        struct line_finder lf = {.lr = lr, .found = 0};
1760        int ret = 0;
1761        Dwarf_Off off = 0, noff;
1762        size_t cuhl;
1763        Dwarf_Die *diep;
1764        const char *comp_dir;
1765
1766        /* Fastpath: lookup by function name from .debug_pubnames section */
1767        if (lr->function) {
1768                struct pubname_callback_param pubname_param = {
1769                        .function = lr->function, .file = lr->file,
1770                        .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
1771                struct dwarf_callback_param line_range_param = {
1772                        .data = (void *)&lf, .retval = 0};
1773
1774                dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1775                                  &pubname_param, 0);
1776                if (pubname_param.found) {
1777                        line_range_search_cb(&lf.sp_die, &line_range_param);
1778                        if (lf.found)
1779                                goto found;
1780                }
1781        }
1782
1783        /* Loop on CUs (Compilation Unit) */
1784        while (!lf.found && ret >= 0) {
1785                if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1786                                 NULL, NULL, NULL) != 0)
1787                        break;
1788
1789                /* Get the DIE(Debugging Information Entry) of this CU */
1790                diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1791                if (!diep)
1792                        continue;
1793
1794                /* Check if target file is included. */
1795                if (lr->file)
1796                        lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1797                else
1798                        lf.fname = 0;
1799
1800                if (!lr->file || lf.fname) {
1801                        if (lr->function)
1802                                ret = find_line_range_by_func(&lf);
1803                        else {
1804                                lf.lno_s = lr->start;
1805                                lf.lno_e = lr->end;
1806                                ret = find_line_range_by_line(NULL, &lf);
1807                        }
1808                }
1809                off = noff;
1810        }
1811
1812found:
1813        /* Store comp_dir */
1814        if (lf.found) {
1815                comp_dir = cu_get_comp_dir(&lf.cu_die);
1816                if (comp_dir) {
1817                        lr->comp_dir = strdup(comp_dir);
1818                        if (!lr->comp_dir)
1819                                ret = -ENOMEM;
1820                }
1821        }
1822
1823        pr_debug("path: %s\n", lr->path);
1824        return (ret < 0) ? ret : lf.found;
1825}
1826
1827/*
1828 * Find a src file from a DWARF tag path. Prepend optional source path prefix
1829 * and chop off leading directories that do not exist. Result is passed back as
1830 * a newly allocated path on success.
1831 * Return 0 if file was found and readable, -errno otherwise.
1832 */
1833int get_real_path(const char *raw_path, const char *comp_dir,
1834                         char **new_path)
1835{
1836        const char *prefix = symbol_conf.source_prefix;
1837
1838        if (!prefix) {
1839                if (raw_path[0] != '/' && comp_dir)
1840                        /* If not an absolute path, try to use comp_dir */
1841                        prefix = comp_dir;
1842                else {
1843                        if (access(raw_path, R_OK) == 0) {
1844                                *new_path = strdup(raw_path);
1845                                return *new_path ? 0 : -ENOMEM;
1846                        } else
1847                                return -errno;
1848                }
1849        }
1850
1851        *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
1852        if (!*new_path)
1853                return -ENOMEM;
1854
1855        for (;;) {
1856                sprintf(*new_path, "%s/%s", prefix, raw_path);
1857
1858                if (access(*new_path, R_OK) == 0)
1859                        return 0;
1860
1861                if (!symbol_conf.source_prefix) {
1862                        /* In case of searching comp_dir, don't retry */
1863                        zfree(new_path);
1864                        return -errno;
1865                }
1866
1867                switch (errno) {
1868                case ENAMETOOLONG:
1869                case ENOENT:
1870                case EROFS:
1871                case EFAULT:
1872                        raw_path = strchr(++raw_path, '/');
1873                        if (!raw_path) {
1874                                zfree(new_path);
1875                                return -ENOENT;
1876                        }
1877                        continue;
1878
1879                default:
1880                        zfree(new_path);
1881                        return -errno;
1882                }
1883        }
1884}
1885