return dwarf_formstring(&attr);
 }
 
+/* Unlike dwarf_getsrc_die(), cu_getsrc_die() only returns statement line */
+static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
+{
+       Dwarf_Addr laddr;
+       Dwarf_Lines *lines;
+       Dwarf_Line *line;
+       size_t nlines, l, u, n;
+       bool flag;
+
+       if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 ||
+           nlines == 0)
+               return NULL;
+
+       /* Lines are sorted by address, use binary search */
+       l = 0; u = nlines - 1;
+       while (l < u) {
+               n = u - (u - l) / 2;
+               line = dwarf_onesrcline(lines, n);
+               if (!line || dwarf_lineaddr(line, &laddr) != 0)
+                       return NULL;
+               if (addr < laddr)
+                       u = n - 1;
+               else
+                       l = n;
+       }
+       /* Going backward to find the lowest line */
+       do {
+               line = dwarf_onesrcline(lines, --l);
+               if (!line || dwarf_lineaddr(line, &laddr) != 0)
+                       return NULL;
+       } while (laddr == addr);
+       l++;
+       /* Going foward to find the statement line */
+       do {
+               line = dwarf_onesrcline(lines, l++);
+               if (!line || dwarf_lineaddr(line, &laddr) != 0 ||
+                   dwarf_linebeginstatement(line, &flag) != 0)
+                       return NULL;
+               if (laddr > addr)
+                       return NULL;
+       } while (!flag);
+
+       return line;
+}
+
 /**
  * cu_find_lineinfo - Get a line number and file name for given address
  * @cu_die: a CU DIE
                    const char **fname, int *lineno)
 {
        Dwarf_Line *line;
-       Dwarf_Addr laddr;
+       Dwarf_Die die_mem;
+       Dwarf_Addr faddr;
 
-       line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
-       if (line && dwarf_lineaddr(line, &laddr) == 0 &&
-           addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
+       if (die_find_realfunc(cu_die, (Dwarf_Addr)addr, &die_mem)
+           && die_entrypc(&die_mem, &faddr) == 0 &&
+           faddr == addr) {
+               *fname = dwarf_decl_file(&die_mem);
+               dwarf_decl_line(&die_mem, lineno);
+               goto out;
+       }
+
+       line = cu_getsrc_die(cu_die, (Dwarf_Addr)addr);
+       if (line && dwarf_lineno(line, lineno) == 0) {
                *fname = dwarf_linesrc(line, NULL, NULL);
                if (!*fname)
                        /* line number is useless without filename */
                        *lineno = 0;
        }
 
+out:
        return *lineno ?: -ENOENT;
 }