^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * dwarf-aux.c : libdw auxiliary interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "dwarf-aux.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "strbuf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "string2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * cu_find_realpath - Find the realpath of the target file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @fname: The tail filename of the target file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Find the real(long) path of @fname in @cu_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) Dwarf_Files *files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) size_t nfiles, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const char *src = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (!fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) for (i = 0; i < nfiles; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) src = dwarf_filesrc(files, i, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (strtailcmp(src, fname) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (i == nfiles)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * cu_get_comp_dir - Get the path of compilation directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @cu_die: a CU DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Get the path of compilation directory of given @cu_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Since this depends on DW_AT_comp_dir, older gcc will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * embedded it. In that case, this returns NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const char *cu_get_comp_dir(Dwarf_Die *cu_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return dwarf_formstring(&attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Unlike dwarf_getsrc_die(), cu_getsrc_die() only returns statement line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) Dwarf_Addr laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) Dwarf_Lines *lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) Dwarf_Line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) size_t nlines, l, u, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bool flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) nlines == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Lines are sorted by address, use binary search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) l = 0; u = nlines - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) while (l < u) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) n = u - (u - l) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) line = dwarf_onesrcline(lines, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (!line || dwarf_lineaddr(line, &laddr) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (addr < laddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u = n - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) l = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Going backward to find the lowest line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) line = dwarf_onesrcline(lines, --l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!line || dwarf_lineaddr(line, &laddr) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) } while (laddr == addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) l++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Going foward to find the statement line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) line = dwarf_onesrcline(lines, l++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dwarf_linebeginstatement(line, &flag) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (laddr > addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) } while (!flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * cu_find_lineinfo - Get a line number and file name for given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @cu_die: a CU DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @addr: An address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @fname: a pointer which returns the file name string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @lineno: a pointer which returns the line number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Find a line number and file name for @addr in @cu_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) const char **fname, int *lineno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) Dwarf_Line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) Dwarf_Die die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) Dwarf_Addr faddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) && die_entrypc(&die_mem, &faddr) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) faddr == addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *fname = dwarf_decl_file(&die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dwarf_decl_line(&die_mem, lineno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (line && dwarf_lineno(line, lineno) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *fname = dwarf_linesrc(line, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!*fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* line number is useless without filename */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *lineno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return *lineno ?: -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * cu_walk_functions_at - Walk on function DIEs at given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @cu_die: A CU DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @addr: An address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @callback: A callback which called with found DIEs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @data: A user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * should be subprogram or inlined-subroutines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int (*callback)(Dwarf_Die *, void *), void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) Dwarf_Die die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) Dwarf_Die *sc_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Inlined function could be recursive. Trace it until fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) sc_die != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) &die_mem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ret = callback(sc_die, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * die_get_linkage_name - Get the linkage name of the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @dw_die: A DIE of the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Get the linkage name attiribute of given @dw_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * For C++ binary, the linkage name will be the mangled symbol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const char *die_get_linkage_name(Dwarf_Die *dw_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return dwarf_formstring(&attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * die_compare_name - Compare diename and tname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @dw_die: a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @tname: a string of target name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) name = dwarf_diename(dw_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return name ? (strcmp(tname, name) == 0) : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * die_match_name - Match diename/linkage name and glob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @dw_die: a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @glob: a string of target glob pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Glob matching the name of @dw_die and @glob. Return false if matching fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * This also match linkage name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bool die_match_name(Dwarf_Die *dw_die, const char *glob)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) name = dwarf_diename(dw_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (name && strglobmatch(name, glob))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* fall back to check linkage name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) name = die_get_linkage_name(dw_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (name && strglobmatch(name, glob))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * die_get_call_lineno - Get callsite line number of inline-function instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * @in_die: a DIE of an inlined function instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * Get call-site line number of @in_die. This means from where the inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * function is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int die_get_call_lineno(Dwarf_Die *in_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) Dwarf_Word ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dwarf_formudata(&attr, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return (int)ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * die_get_type - Get type DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @vr_die: a DIE of a variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @die_mem: where to store a type DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Get a DIE of the type of given variable (@vr_die), and store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * it to die_mem. Return NULL if fails to get a type DIE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dwarf_formref_die(&attr, die_mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* Get a type die, but skip qualifiers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) vr_die = die_get_type(vr_die, die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (!vr_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) tag = dwarf_tag(vr_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } while (tag == DW_TAG_const_type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) tag == DW_TAG_restrict_type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) tag == DW_TAG_volatile_type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tag == DW_TAG_shared_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return vr_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * die_get_real_type - Get a type die, but skip qualifiers and typedef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * @vr_die: a DIE of a variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * @die_mem: where to store a type DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Get a DIE of the type of given variable (@vr_die), and store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * it to die_mem. Return NULL if fails to get a type DIE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * If the type is qualifiers (e.g. const) or typedef, this skips it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * and tries to find real type (structure or basic types, e.g. int).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) vr_die = __die_get_real_type(vr_die, die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return vr_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Get attribute and translate it as a udata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) Dwarf_Word *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dwarf_formudata(&attr, result) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* Get attribute and translate it as a sdata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) Dwarf_Sword *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dwarf_formsdata(&attr, result) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * die_is_signed_type - Check whether a type DIE is signed or not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * @tp_die: a DIE of a type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * Get the encoding of @tp_die and return true if the encoding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * is signed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) bool die_is_signed_type(Dwarf_Die *tp_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) Dwarf_Word ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ret == DW_ATE_signed_fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * die_is_func_def - Ensure that this DIE is a subprogram and definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * @dw_die: a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Ensure that this DIE is a subprogram and NOT a declaration. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * returns true if @dw_die is a function definition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) bool die_is_func_def(Dwarf_Die *dw_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) Dwarf_Addr addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (dwarf_tag(dw_die) != DW_TAG_subprogram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (dwarf_attr(dw_die, DW_AT_declaration, &attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * DW_AT_declaration can be lost from function declaration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * by gcc's bug #97060.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * So we need to check this subprogram DIE has DW_AT_inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * or an entry address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!dwarf_attr(dw_die, DW_AT_inline, &attr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) die_entrypc(dw_die, &addr) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * die_entrypc - Returns entry PC (the lowest address) of a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * @dw_die: a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * @addr: where to store entry PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * Since dwarf_entrypc() does not return entry PC if the DIE has only address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * range, we have to use this to retrieve the lowest address from the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * range attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) Dwarf_Addr base, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (dwarf_entrypc(dw_die, addr) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * Since the dwarf_ranges() will return 0 if there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * DW_AT_ranges attribute, we should check it first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!dwarf_attr(dw_die, DW_AT_ranges, &attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * @dw_die: a DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * Ensure that this DIE is an instance (which has an entry address).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * This returns true if @dw_die is a function instance. If not, the @dw_die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * must be a prototype. You can use die_walk_instances() to find actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * instances.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) bool die_is_func_instance(Dwarf_Die *dw_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) Dwarf_Addr tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) Dwarf_Attribute attr_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) int tag = dwarf_tag(dw_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (tag != DW_TAG_subprogram &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) tag != DW_TAG_inlined_subroutine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return dwarf_entrypc(dw_die, &tmp) == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * die_get_data_member_location - Get the data-member offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * @mb_die: a DIE of a member of a data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * @offs: The offset of the member in the data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Get the offset of @mb_die in the data structure including @mb_die, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * stores result offset to @offs. If any error occurs this returns errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) Dwarf_Op *expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) size_t nexpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (dwarf_formudata(&attr, offs) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* DW_AT_data_member_location should be DW_OP_plus_uconst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ret = dwarf_getlocation(&attr, &expr, &nexpr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (ret < 0 || nexpr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) expr[0].atom, nexpr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -ENOTSUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *offs = (Dwarf_Word)expr[0].number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Get the call file index number in CU DIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int die_get_call_fileno(Dwarf_Die *in_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) Dwarf_Sword idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return (int)idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* Get the declared file index number in CU DIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static int die_get_decl_fileno(Dwarf_Die *pdie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) Dwarf_Sword idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return (int)idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * die_get_call_file - Get callsite file name of inlined function instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * @in_die: a DIE of an inlined function instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * Get call-site file name of @in_die. This means from which file the inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * function is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) const char *die_get_call_file(Dwarf_Die *in_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) Dwarf_Die cu_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) Dwarf_Files *files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) idx = die_get_call_fileno(in_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return dwarf_filesrc(files, idx, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * die_find_child - Generic DIE search function in DIE tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * @rt_die: a root DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * @callback: a callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * @data: a user data passed to the callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * Trace DIE tree from @rt_die and call @callback for each child DIE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * If @callback returns DIE_FIND_CB_END, this stores the DIE into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * this continues to trace the tree. Optionally, @callback can return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * the children and trace only the siblings respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * Returns NULL if @callback can't find any appropriate DIE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int (*callback)(Dwarf_Die *, void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) void *data, Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) Dwarf_Die child_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = dwarf_child(rt_die, die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = callback(die_mem, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (ret == DIE_FIND_CB_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if ((ret & DIE_FIND_CB_CHILD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) die_find_child(die_mem, callback, data, &child_die)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } while ((ret & DIE_FIND_CB_SIBLING) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) dwarf_siblingof(die_mem, die_mem) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct __addr_die_search_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) Dwarf_Addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) Dwarf_Die *die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct __addr_die_search_param *ad = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) Dwarf_Addr addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) !dwarf_highpc(fn_die, &addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) addr == ad->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return DWARF_CB_ABORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return DWARF_CB_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * die_find_tailfunc - Search for a non-inlined function with tail call at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * @cu_die: a CU DIE which including @addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @addr: target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * Search for a non-inlined function DIE with tail call at @addr. Stores the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * DIE to @die_mem and returns it if found. Returns NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct __addr_die_search_param ad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ad.addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ad.die_mem = die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* dwarf_getscopes can't find subprogram. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* die_find callback for non-inlined function search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct __addr_die_search_param *ad = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * Since a declaration entry doesn't has given pc, this always returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * function definition entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dwarf_haspc(fn_die, ad->addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return DWARF_CB_ABORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return DWARF_CB_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * die_find_realfunc - Search a non-inlined function at given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * @cu_die: a CU DIE which including @addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * @addr: target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * Search a non-inlined function DIE which includes @addr. Stores the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * DIE to @die_mem and returns it if found. Returns NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct __addr_die_search_param ad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ad.addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ad.die_mem = die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* dwarf_getscopes can't find subprogram. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* die_find callback for inline function search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) Dwarf_Addr *addr = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dwarf_haspc(die_mem, *addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * die_find_top_inlinefunc - Search the top inlined function at given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * @sp_die: a subprogram DIE which including @addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * @addr: target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * Search an inlined function DIE which includes @addr. Stores the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * DIE to @die_mem and returns it if found. Returns NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * Even if several inlined functions are expanded recursively, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * doesn't trace it down, and returns the topmost one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * die_find_inlinefunc - Search an inlined function at given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * @sp_die: a subprogram DIE which including @addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * @addr: target address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * Search an inlined function DIE which includes @addr. Stores the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * DIE to @die_mem and returns it if found. Returns NULL if failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * If several inlined functions are expanded recursively, this trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * it down and returns deepest one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) Dwarf_Die tmp_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (!sp_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* Inlined function could be recursive. Trace it until fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (sp_die) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) &tmp_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct __instance_walk_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int (*callback)(Dwarf_Die *, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct __instance_walk_param *iwp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) Dwarf_Attribute attr_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) Dwarf_Die origin_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) Dwarf_Attribute *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) Dwarf_Die *origin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (!die_is_func_instance(inst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (attr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) origin = dwarf_formref_die(attr, &origin_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (origin == NULL || origin->addr != iwp->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* Ignore redundant instances */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) dwarf_decl_line(origin, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (die_get_call_lineno(inst) == tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) tmp = die_get_decl_fileno(origin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (die_get_call_fileno(inst) == tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) iwp->retval = iwp->callback(inst, iwp->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * die_walk_instances - Walk on instances of given DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * @or_die: an abstract original DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * @callback: a callback function which is called with instance DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * @data: user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * Walk on the instances of give @in_die. @in_die must be an inlined function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * declartion. This returns the return value of @callback if it returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * non-zero value, or -ENOENT if there is no instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) Dwarf_Die cu_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) Dwarf_Die die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct __instance_walk_param iwp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .addr = or_die->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .callback = callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .data = data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .retval = -ENOENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return iwp.retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Line walker internal parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct __line_walk_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) bool recursive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) line_walk_callback_t callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct __line_walk_param *lw = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) Dwarf_Addr addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) const char *fname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int lineno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) fname = die_get_call_file(in_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) lineno = die_get_call_lineno(in_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) lw->retval = lw->callback(fname, lineno, addr, lw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (lw->retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (!lw->recursive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return DIE_FIND_CB_SIBLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) fname = dwarf_decl_file(in_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) lw->retval = lw->callback(fname, lineno, addr, lw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (lw->retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* Continue to search nested inlined function call-sites */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* Walk on lines of blocks included in given DIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) line_walk_callback_t callback, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct __line_walk_param lw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .recursive = recursive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .callback = callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .data = data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .retval = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) Dwarf_Die die_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) Dwarf_Addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) const char *fname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) int lineno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* Handle function declaration line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) fname = dwarf_decl_file(sp_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) die_entrypc(sp_die, &addr) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) lw.retval = callback(fname, lineno, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (lw.retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return lw.retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct __line_walk_param *lw = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * Since inlined function can include another inlined function in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * the same file, we need to walk in it recursively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (lw->retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return DWARF_CB_ABORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return DWARF_CB_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * die_walk_lines - Walk on lines inside given DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * @callback: callback routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * @data: user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * Walk on all lines inside given @rt_die and call @callback on each line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * If the @rt_die is a function, walk only on the lines inside the function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * otherwise @rt_die must be a CU DIE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * Note that this walks not only dwarf line list, but also function entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * and inline call-site.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) Dwarf_Lines *lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) Dwarf_Line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) Dwarf_Addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) const char *fname, *decf = NULL, *inf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int lineno, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int decl = 0, inl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) Dwarf_Die die_mem, *cu_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) size_t nlines, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) bool flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* Get the CU die */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) dwarf_decl_line(rt_die, &decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) decf = dwarf_decl_file(rt_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) cu_die = rt_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (!cu_die) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) pr_debug2("Failed to get CU from given DIE.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) /* Get lines list in the CU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) pr_debug2("Failed to get source lines on this CU.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) pr_debug2("Get %zd lines from this CU\n", nlines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* Walk on the lines on lines list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) for (i = 0; i < nlines; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) line = dwarf_onesrcline(lines, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (line == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dwarf_lineno(line, &lineno) != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dwarf_lineaddr(line, &addr) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) pr_debug2("Failed to get line info. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) "Possible error in debuginfo.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Skip end-of-sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (dwarf_lineendsequence(line, &flag) != 0 || flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* Skip Non statement line-info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* Filter lines based on address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (rt_die != cu_die) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * Address filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * The line is included in given function, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * no inline block includes it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!dwarf_haspc(rt_die, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* Call-site check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) inf = die_get_call_file(&die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if ((inf && !strcmp(inf, decf)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) die_get_call_lineno(&die_mem) == lineno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dwarf_decl_line(&die_mem, &inl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (inl != decl ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) decf != dwarf_decl_file(&die_mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* Get source line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) fname = dwarf_linesrc(line, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ret = callback(fname, lineno, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * Dwarf lines doesn't include function declarations and inlined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * subroutines. We have to check functions list or given function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (rt_die != cu_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * Don't need walk inlined functions recursively, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * inner inlined functions don't have the lines of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * specified function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ret = __die_walk_funclines(rt_die, false, callback, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) struct __line_walk_param param = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .callback = callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) .data = data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .retval = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) ret = param.retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct __find_variable_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) Dwarf_Addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct __find_variable_param *fvp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) int tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) tag = dwarf_tag(die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if ((tag == DW_TAG_formal_parameter ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) tag == DW_TAG_variable) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) die_compare_name(die_mem, fvp->name) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * Does the DIE have location information or const value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * or external instance?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) (dwarf_attr(die_mem, DW_AT_external, &attr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) dwarf_attr(die_mem, DW_AT_location, &attr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dwarf_attr(die_mem, DW_AT_const_value, &attr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (dwarf_haspc(die_mem, fvp->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return DIE_FIND_CB_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return DIE_FIND_CB_SIBLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * die_find_variable_at - Find a given name variable at given address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * @sp_die: a function DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * @name: variable name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * @addr: address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * Find a variable DIE called @name at @addr in @sp_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) Dwarf_Addr addr, Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct __find_variable_param fvp = { .name = name, .addr = addr};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) const char *name = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (dwarf_tag(die_mem) == DW_TAG_member) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (die_compare_name(die_mem, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) Dwarf_Die type_die, tmp_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (die_get_type(die_mem, &type_die) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) die_find_member(&type_die, name, &tmp_die))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return DIE_FIND_CB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return DIE_FIND_CB_SIBLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) * die_find_member - Find a given name member in a data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * @st_die: a data structure type DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * @name: member name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * @die_mem: a buffer for result DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * Find a member DIE called @name in @st_die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) Dwarf_Die *die_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return die_find_child(st_die, __die_find_member_cb, (void *)name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) die_mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) * die_get_typename - Get the name of given variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * @vr_die: a variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * @buf: a strbuf for result type name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * and Return -ENOENT if failed to find type name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * Note that the result will stores typedef name if possible, and stores
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * "*(function_type)" if the type is a function pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) Dwarf_Die type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int tag, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) const char *tmp = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if (__die_get_real_type(vr_die, &type) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) tag = dwarf_tag(&type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) tmp = "*";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) else if (tag == DW_TAG_subroutine_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* Function pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return strbuf_add(buf, "(function_type)", 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (!dwarf_diename(&type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (tag == DW_TAG_union_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) tmp = "union ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) else if (tag == DW_TAG_structure_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) tmp = "struct ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) else if (tag == DW_TAG_enumeration_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) tmp = "enum ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /* Write a base name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret = die_get_typename(&type, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return ret ? ret : strbuf_addstr(buf, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * die_get_varname - Get the name and type of given variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * @vr_die: a variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * @buf: a strbuf for type and variable name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * Get the name and type of @vr_die and stores it in @buf as "type\tname".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) ret = die_get_typename(vr_die, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) pr_debug("Failed to get type, make it unknown.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) ret = strbuf_add(buf, " (unknown_type)", 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * @sp_die: a subprogram DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * @vr_die: a variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * @buf: a strbuf for variable byte offset range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * Get the innermost scope range of @vr_die and stores it in @buf as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * "@<function_name+[NN-NN,NN-NN]>".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct strbuf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) Dwarf_Die *scopes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) size_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) Dwarf_Addr base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) Dwarf_Addr start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) Dwarf_Addr entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) ret = die_entrypc(sp_die, &entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) name = dwarf_diename(sp_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) count = dwarf_getscopes_die(vr_die, &scopes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) /* (*SCOPES)[1] is the DIE for the scope containing that scope */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (count <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) while ((offset = dwarf_ranges(&scopes[1], offset, &base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) &start, &end)) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) start -= entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) end -= entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) name, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ret = strbuf_add(buf, "]>", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) free(scopes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * die_get_var_range - Get byte offset range of given variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * @sp_die: a subprogram DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * @vr_die: a variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * @buf: a strbuf for type and variable name and byte offset range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * Get the byte offset range of @vr_die and stores it in @buf as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) * "@<function_name+[NN-NN,NN-NN]>".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) Dwarf_Addr base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) Dwarf_Addr start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) Dwarf_Addr entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) Dwarf_Op *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) size_t nops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) size_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) Dwarf_Attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) ret = die_entrypc(sp_die, &entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) name = dwarf_diename(sp_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) while ((offset = dwarf_getlocations(&attr, offset, &base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) &start, &end, &op, &nops)) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (start == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /* Single Location Descriptions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) /* Location Lists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) start -= entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) end -= entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) name, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ret = strbuf_add(buf, "]>", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) Dwarf_Die *vr_die __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) struct strbuf *buf __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return -ENOTSUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * @vr_die: a variable DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static bool die_has_loclist(Dwarf_Die *vr_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) Dwarf_Attribute loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) int tag = dwarf_tag(vr_die);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (tag != DW_TAG_formal_parameter &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) tag != DW_TAG_variable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) dwarf_whatform(&loc) == DW_FORM_sec_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * die_is_optimized_target - Check if target program is compiled with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * optimization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * @cu_die: a CU DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * For any object in given CU whose DW_AT_location is a location list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * target program is compiled with optimization. This is applicable to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * clang as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) bool die_is_optimized_target(Dwarf_Die *cu_die)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) Dwarf_Die tmp_die;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (die_has_loclist(cu_die))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (!dwarf_child(cu_die, &tmp_die) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) die_is_optimized_target(&tmp_die))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (!dwarf_siblingof(cu_die, &tmp_die) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) die_is_optimized_target(&tmp_die))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * die_search_idx - Search index of given line address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * @lines: Line records of single CU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * @nr_lines: Number of @lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * @addr: address we are looking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * @idx: index to be set by this function (return value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * Search for @addr by looping over every lines of CU. If address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * matches, set index of that line in @idx. Note that single source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) * line can have multiple line records. i.e. single source line can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) * have multiple index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) Dwarf_Addr addr, unsigned long *idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) Dwarf_Addr tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) for (i = 0; i < nr_lines; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (tmp == addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) *idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * die_get_postprologue_addr - Search next address after function prologue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * @entrypc_idx: entrypc index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * @lines: Line records of single CU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) * @nr_lines: Number of @lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) * @hignpc: high PC address of function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * @postprologue_addr: Next address after function prologue (return value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) * Look for prologue-end marker. If there is no explicit marker, return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * address of next line record or next source line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) static bool die_get_postprologue_addr(unsigned long entrypc_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) Dwarf_Lines *lines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) unsigned long nr_lines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) Dwarf_Addr highpc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) Dwarf_Addr *postprologue_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) int entrypc_lno, lno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) Dwarf_Line *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) Dwarf_Addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) bool p_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /* entrypc_lno is actual source line number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) line = dwarf_onesrcline(lines, entrypc_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (dwarf_lineno(line, &entrypc_lno))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) for (i = entrypc_idx; i < nr_lines; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) line = dwarf_onesrcline(lines, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (dwarf_lineaddr(line, &addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) dwarf_lineno(line, &lno) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) dwarf_lineprologueend(line, &p_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) /* highpc is exclusive. [entrypc,highpc) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (addr >= highpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) /* clang supports prologue-end marker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (p_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) /* Actual next line in source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (lno != entrypc_lno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * Single source line can have multiple line records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * For Example,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * void foo() { printf("hello\n"); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * contains two line records. One points to declaration and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * other points to printf() line. Variable 'lno' won't get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) * incremented in this case but 'i' will.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (i != entrypc_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) dwarf_lineaddr(line, postprologue_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (*postprologue_addr >= highpc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) postprologue_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * die_skip_prologue - Use next address after prologue as probe location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * @sp_die: a subprogram DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * @cu_die: a CU DIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * @entrypc: entrypc of the function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * Function prologue prepares stack and registers before executing function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * logic. When target program is compiled without optimization, function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * parameter information is only valid after prologue. When we probe entrypc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * of the function, and try to record function parameter, it contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * garbage value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) Dwarf_Addr *entrypc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) size_t nr_lines = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) unsigned long entrypc_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) Dwarf_Lines *lines = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) Dwarf_Addr postprologue_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) Dwarf_Addr highpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (dwarf_highpc(sp_die, &highpc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) highpc, &postprologue_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) *entrypc = postprologue_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }