From owner-svn-src-stable-12@freebsd.org Tue Mar 3 16:25:30 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id D0F11254F5A; Tue, 3 Mar 2020 16:25:30 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48X2Rs5jXXz3Fnn; Tue, 3 Mar 2020 16:25:29 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2D1A07F78; Tue, 3 Mar 2020 16:25:28 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 023GPS3f082616; Tue, 3 Mar 2020 16:25:28 GMT (envelope-from emaste@FreeBSD.org) Received: (from emaste@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 023GPSW4082615; Tue, 3 Mar 2020 16:25:28 GMT (envelope-from emaste@FreeBSD.org) Message-Id: <202003031625.023GPSW4082615@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: emaste set sender to emaste@FreeBSD.org using -f From: Ed Maste Date: Tue, 3 Mar 2020 16:25:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r358587 - stable/12/contrib/elftoolchain/addr2line X-SVN-Group: stable-12 X-SVN-Commit-Author: emaste X-SVN-Commit-Paths: stable/12/contrib/elftoolchain/addr2line X-SVN-Commit-Revision: 358587 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Mar 2020 16:25:31 -0000 Author: emaste Date: Tue Mar 3 16:25:28 2020 New Revision: 358587 URL: https://svnweb.freebsd.org/changeset/base/358587 Log: MFC r357844: addr2line: Handle DW_AT_ranges in compile units Based on original submission by Marat Radchenko in ELF Tool Chain ticket #545, rebased and updated by Tiger Gao. Also r357862, use stdbool.h header for bool PR: 217736 Submitted by: Marat Radchenko Submitted by: Tiger Gao Sponsored by: The FreeBSD Foundation Modified: stable/12/contrib/elftoolchain/addr2line/addr2line.c Directory Properties: stable/12/ (props changed) Modified: stable/12/contrib/elftoolchain/addr2line/addr2line.c ============================================================================== --- stable/12/contrib/elftoolchain/addr2line/addr2line.c Tue Mar 3 15:49:34 2020 (r358586) +++ stable/12/contrib/elftoolchain/addr2line/addr2line.c Tue Mar 3 16:25:28 2020 (r358587) @@ -65,6 +65,7 @@ struct CU { Dwarf_Signed nsrcfiles; STAILQ_HEAD(, Func) funclist; Dwarf_Die die; + Dwarf_Debug dbg; }; static struct option longopts[] = { @@ -345,7 +346,8 @@ cont_search: collect_func(dbg, ret_die, parent, cu); /* Cleanup */ - dwarf_dealloc(dbg, die, DW_DLA_DIE); + if (die != cu->die) + dwarf_dealloc(dbg, die, DW_DLA_DIE); if (abst_die != NULL) dwarf_dealloc(dbg, abst_die, DW_DLA_DIE); @@ -411,6 +413,102 @@ culookup(Dwarf_Unsigned addr) return (NULL); } +/* + * Check whether addr falls into range(s) of current CU, and save current CU + * to lookup tree if so. + */ +static int +check_range(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Unsigned addr, + struct CU **cu) +{ + Dwarf_Error de; + Dwarf_Unsigned addr_base, lopc, hipc; + Dwarf_Off ranges_off; + Dwarf_Signed ranges_cnt; + Dwarf_Ranges *ranges; + int i, ret; + bool in_range; + + addr_base = 0; + ranges = NULL; + ranges_cnt = 0; + in_range = false; + + ret = dwarf_attrval_unsigned(die, DW_AT_ranges, &ranges_off, &de); + if (ret == DW_DLV_NO_ENTRY) { + if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) == + DW_DLV_OK) { + if (lopc == curlopc) + return (DW_DLV_ERROR); + if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, + &de) == DW_DLV_OK) { + /* + * Check if the address falls into the PC + * range of this CU. + */ + if (handle_high_pc(die, lopc, &hipc) != + DW_DLV_OK) + return (DW_DLV_ERROR); + } else { + /* Assume ~0ULL if DW_AT_high_pc not present */ + hipc = ~0ULL; + } + + if (addr >= lopc && addr < hipc) { + in_range = true; + } + } + } else if (ret == DW_DLV_OK) { + ret = dwarf_get_ranges(dbg, ranges_off, &ranges, + &ranges_cnt, NULL, &de); + if (ret != DW_DLV_OK) + return (ret); + + if (!ranges || ranges_cnt <= 0) + return (DW_DLV_ERROR); + + for (i = 0; i < ranges_cnt; i++) { + if (ranges[i].dwr_type == DW_RANGES_END) + return (DW_DLV_NO_ENTRY); + + if (ranges[i].dwr_type == + DW_RANGES_ADDRESS_SELECTION) { + addr_base = ranges[i].dwr_addr2; + continue; + } + + /* DW_RANGES_ENTRY */ + lopc = ranges[i].dwr_addr1 + addr_base; + hipc = ranges[i].dwr_addr2 + addr_base; + + if (lopc == curlopc) + return (DW_DLV_ERROR); + + if (addr >= lopc && addr < hipc){ + in_range = true; + break; + } + } + } else { + return (DW_DLV_ERROR); + } + + if (in_range) { + if ((*cu = calloc(1, sizeof(struct CU))) == NULL) + err(EXIT_FAILURE, "calloc"); + (*cu)->lopc = lopc; + (*cu)->hipc = hipc; + (*cu)->die = die; + (*cu)->dbg = dbg; + STAILQ_INIT(&(*cu)->funclist); + RB_INSERT(cutree, &cuhead, *cu); + curlopc = lopc; + return (DW_DLV_OK); + } else { + return (DW_DLV_NO_ENTRY); + } +} + static void translate(Dwarf_Debug dbg, Elf *e, const char* addrstr) { @@ -418,10 +516,9 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr Dwarf_Line *lbuf; Dwarf_Error de; Dwarf_Half tag; - Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; + Dwarf_Unsigned addr, lineno, plineno; Dwarf_Signed lcount; Dwarf_Addr lineaddr, plineaddr; - Dwarf_Off off; struct CU *cu; struct Func *f; const char *funcname; @@ -439,6 +536,7 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr cu = culookup(addr); if (cu != NULL) { die = cu->die; + dbg = cu->dbg; goto status_ok; } @@ -477,44 +575,11 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr warnx("could not find DW_TAG_compile_unit die"); goto next_cu; } - if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) == - DW_DLV_OK) { - if (lopc == curlopc) - goto out; - if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, - &de) == DW_DLV_OK) { - /* - * Check if the address falls into the PC - * range of this CU. - */ - if (handle_high_pc(die, lopc, &hipc) != - DW_DLV_OK) - goto out; - } else { - /* Assume ~0ULL if DW_AT_high_pc not present */ - hipc = ~0ULL; - } - - if (dwarf_dieoffset(die, &off, &de) != DW_DLV_OK) { - warnx("dwarf_dieoffset failed: %s", - dwarf_errmsg(de)); - goto out; - } - - if (addr >= lopc && addr < hipc) { - if ((cu = calloc(1, sizeof(*cu))) == NULL) - err(EXIT_FAILURE, "calloc"); - cu->off = off; - cu->lopc = lopc; - cu->hipc = hipc; - cu->die = die; - STAILQ_INIT(&cu->funclist); - RB_INSERT(cutree, &cuhead, cu); - - curlopc = lopc; - break; - } - } + ret = check_range(dbg, die, addr, &cu); + if (ret == DW_DLV_OK) + break; + if (ret == DW_DLV_ERROR) + goto out; next_cu: if (die != NULL) { dwarf_dealloc(dbg, die, DW_DLA_DIE);