cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dwarf-aux.c (36362B)


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