From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id F05153858C3A for ; Wed, 6 Dec 2023 09:22:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F05153858C3A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=osandov.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=osandov.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F05153858C3A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701854574; cv=none; b=qAE7B5PVFaqrD71YwQ1enMkaWRGOfF71wlcE+PyQ4zqucRJ6IWA50JLjdg3p1rwkW8qpDHy2PXr3qgqTGNdM8earB1Y7+HGtq0F1MbSkFa3tzU/JEtYBOWNcD68E6YErEgIbH5TIzDGhMTX5iN+VS2PcCuSGsCj0AvuwpiKTHKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701854574; c=relaxed/simple; bh=jpSU2uy8C1etml9TaYZ4e39YjRJoqj7moLu7SfZ+qf4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=TQeS6FxAOCub0fUNtS7a1HJtTx2l8XJhsCorcTDYz+LJYKKmger0ki0/OfJSYAwFx5vOV9OkUV76m/RqmN9zZIMGqWAcPGlUXFQOHHT7Emc9G7o7HCPU52PiqWFfuLok1jgvZx+vT+w9h7Q3RJknfHc8cnIAfw5HykDXI+G5S/U= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-1d098b87eeeso28955705ad.0 for ; Wed, 06 Dec 2023 01:22:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20230601.gappssmtp.com; s=20230601; t=1701854562; x=1702459362; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=F1BASpwb/4puNMwJQRinGicw9imCfGsYkzXdp5T4F/4=; b=i3SANWvRH+UZ2PMwf/yHO6VeuWzN5MSrPw+S9H/+5wed37t6o+UBa/Az//DygfOkw1 kwKjx0gI8d4dCrLy1bybIr2L3QXs7Dhu67dMzArNfzOTIgzL0c4Rsp9DaKvdyuQhJPbN pzwxMWUnX3bW+epZspLHrtzwD58MJcbbqET+I9T1f2gMCPEyjepm4rQP8fRNKOW4Tf6j y1S5grZm4G7lOOQlJapwfgBshb5VEoQayWUCc5EST4RVWwioAeESN1h+SmojXXj6DLyu 1oZ7L4zsC/tS/nObKcEvQ70P45JZBLZsy9r00sy7jmmfEl6hfxeqQY8bsDgaObVTu4/F FDIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701854562; x=1702459362; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=F1BASpwb/4puNMwJQRinGicw9imCfGsYkzXdp5T4F/4=; b=J7tzvFCgGt2LUJQBXx8ePs7CP33/Kon4W5h1LYVNmGjo10D8CSNxpnWg0RCibAlP8b MK0g9+kMxHEvi895fRt2dDqnt1WXK2ZMIpTq7wJfil6UHphv/Ui+ehoLT2WyrnTI499P EbLN0pVmpEC4+AO+i/PsZNnoRlfYeDpXmXf2Pv8G4NJecztkSCegN/eSuwTJ79QFUOpH F1oqt8/czwrIk+UD5zVHHKTx0nogoF/mSPiR8OSKa0d5VtcQzhfJKKDOPsTs93A/Preb GVUO3C0Lx+Pnm7W7B/JOrbptKmfrHBeyWeyxDk4yRfQh5aDwDwEWOJaittWnJkqZ8Fdu O0IQ== X-Gm-Message-State: AOJu0YzUymoGl9XARgMv61ytd5R9wz+ihZTOwUd/9rVPa4IpysYiSSeP PZcNeUcuHT/WzdSB+b85DtxkRHdQCSI65WgE9Yg= X-Google-Smtp-Source: AGHT+IH7KaiV2YqjfJVv1Icmglo+ysjDQIweq7EVNKtnsJRgswRrvyFLvZB0k6ZSpmjTv0idvx/gVQ== X-Received: by 2002:a17:903:32ce:b0:1d0:c6f6:3fa3 with SMTP id i14-20020a17090332ce00b001d0c6f63fa3mr634770plr.63.1701854562006; Wed, 06 Dec 2023 01:22:42 -0800 (PST) Received: from telecaster.hsd1.wa.comcast.net ([2601:602:a300:3bc0::826d]) by smtp.gmail.com with ESMTPSA id j6-20020a170902c3c600b001cfd049528esm6364165plj.110.2023.12.06.01.22.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Dec 2023 01:22:41 -0800 (PST) From: Omar Sandoval To: elfutils-devel@sourceware.org Subject: [PATCH v2 2/4] libdw: Try .dwp file in __libdw_find_split_unit() Date: Wed, 6 Dec 2023 01:22:17 -0800 Message-ID: <0e3b1e4de076d669f4b261f0a410cbf770837f4f.1701854319.git.osandov@fb.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Omar Sandoval Try opening the file in the location suggested by the standard (the skeleton file name + ".dwp") and looking up the unit in the package index. The rest is similar to .dwo files, with slightly different cleanup since a single Dwarf handle is shared. * libdw/libdw_find_split_unit.c (try_dwp_file): New function. (__libdw_find_split_unit): Call try_dwp_file. * libdw/libdwP.h (Dwarf): Add dwp_dwarf and dwp_fd. (__libdw_dwp_findcu_id): New declaration. (__libdw_link_skel_split): Handle .debug_addr for dwp. * libdw/libdw_begin_elf.c (dwarf_begin_elf): Initialize result->dwp_fd. * libdw/dwarf_end.c (dwarf_end): Free dwarf->dwp_dwarf and close dwarf->dwp_fd. (cu_free): Don't free split dbg if it is dwp_dwarf. Signed-off-by: Omar Sandoval --- libdw/dwarf_begin_elf.c | 1 + libdw/dwarf_cu_dwp_section_info.c | 19 ++++++++ libdw/dwarf_end.c | 10 ++++- libdw/libdwP.h | 23 ++++++++-- libdw/libdw_find_split_unit.c | 75 ++++++++++++++++++++++++++++--- 5 files changed, 119 insertions(+), 9 deletions(-) diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index 323a91d0..ca2b7e2a 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -567,6 +567,7 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp) result->elf = elf; result->alt_fd = -1; + result->dwp_fd = -1; /* Initialize the memory handling. Initial blocks are allocated on first actual allocation. */ diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c index 4a4eac8c..298f36f9 100644 --- a/libdw/dwarf_cu_dwp_section_info.c +++ b/libdw/dwarf_cu_dwp_section_info.c @@ -340,6 +340,25 @@ __libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off, abbrev_offsetp, NULL); } +Dwarf_CU * +internal_function +__libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8) +{ + Dwarf_Package_Index *index = __libdw_package_index (dbg, false); + uint32_t unit_row; + Dwarf_Off offset; + Dwarf_CU *cu; + if (__libdw_dwp_unit_row (index, unit_id8, &unit_row) == 0 + && __libdw_dwp_section_info (index, unit_row, DW_SECT_INFO, &offset, + NULL) == 0 + && (cu = __libdw_findcu (dbg, offset, false)) != NULL + && cu->unit_type == DW_UT_split_compile + && cu->unit_id8 == unit_id8) + return cu; + else + return NULL; +} + int dwarf_cu_dwp_section_info (Dwarf_CU *cu, unsigned int section, Dwarf_Off *offsetp, Dwarf_Off *sizep) diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index b7f817d9..78224ddb 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -66,7 +66,9 @@ cu_free (void *arg) /* The fake_addr_cu might be shared, only release one. */ if (p->dbg->fake_addr_cu == p->split->dbg->fake_addr_cu) p->split->dbg->fake_addr_cu = NULL; - INTUSE(dwarf_end) (p->split->dbg); + /* There is only one DWP file. We free it later. */ + if (p->split->dbg != p->dbg->dwp_dwarf) + INTUSE(dwarf_end) (p->split->dbg); } } } @@ -147,6 +149,12 @@ dwarf_end (Dwarf *dwarf) close (dwarf->alt_fd); } + if (dwarf->dwp_fd != -1) + { + INTUSE(dwarf_end) (dwarf->dwp_dwarf); + close (dwarf->dwp_fd); + } + /* The cached path and dir we found the Dwarf ELF file in. */ free (dwarf->elfpath); free (dwarf->debugdir); diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 7f8d69b5..54445886 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -180,6 +180,9 @@ struct Dwarf /* dwz alternate DWARF file. */ Dwarf *alt_dwarf; + /* DWARF package file. */ + Dwarf *dwp_dwarf; + /* The section data. */ Elf_Data *sectiondata[IDX_last]; @@ -197,6 +200,9 @@ struct Dwarf close this file descriptor. */ int alt_fd; + /* File descriptor of DWARF package file. */ + int dwp_fd; + /* Information for traversing the .debug_pubnames section. This is an array and separately allocated with malloc. */ struct pubnames_s @@ -716,6 +722,10 @@ extern int __libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off, Dwarf_Off *abbrev_offsetp) __nonnull_attribute__ (1, 7, 8) internal_function; +/* Find the compilation unit in a DWARF package file with the given id. */ +extern Dwarf_CU *__libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8) + __nonnull_attribute__ (1) internal_function; + /* Get abbreviation with given code. */ extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code) @@ -1367,12 +1377,19 @@ __libdw_link_skel_split (Dwarf_CU *skel, Dwarf_CU *split) /* Get .debug_addr and addr_base greedy. We also need it for the fake addr cu. - There is only one per split debug. */ + This needs to be done for each split unit (one per .dwo file, or multiple + per .dwp file). */ Dwarf *dbg = skel->dbg; Dwarf *sdbg = split->dbg; - if (sdbg->sectiondata[IDX_debug_addr] == NULL - && dbg->sectiondata[IDX_debug_addr] != NULL) + if (dbg->sectiondata[IDX_debug_addr] != NULL + /* If this split file hasn't been linked yet... */ + && (sdbg->sectiondata[IDX_debug_addr] == NULL + /* ... or it was linked to the same skeleton file for another + unit... */ + || (sdbg->sectiondata[IDX_debug_addr] + == dbg->sectiondata[IDX_debug_addr]))) { + /* ... then link the address information for this file and unit. */ sdbg->sectiondata[IDX_debug_addr] = dbg->sectiondata[IDX_debug_addr]; split->addr_base = __libdw_cu_addr_base (skel); diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c index 533f8072..e1e78951 100644 --- a/libdw/libdw_find_split_unit.c +++ b/libdw/libdw_find_split_unit.c @@ -85,6 +85,67 @@ try_split_file (Dwarf_CU *cu, const char *dwo_path) } } +static void +try_dwp_file (Dwarf_CU *cu) +{ + if (cu->dbg->dwp_dwarf == NULL) + { + if (cu->dbg->elfpath != NULL) + { + /* The DWARF 5 standard says "the package file is typically placed in + the same directory as the application, and is given the same name + with a '.dwp' extension". */ + size_t elfpath_len = strlen (cu->dbg->elfpath); + char *dwp_path = malloc (elfpath_len + 5); + if (dwp_path == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return; + } + memcpy (dwp_path, cu->dbg->elfpath, elfpath_len); + strcpy (dwp_path + elfpath_len, ".dwp"); + int dwp_fd = open (dwp_path, O_RDONLY); + free (dwp_path); + if (dwp_fd != -1) + { + Dwarf *dwp_dwarf = dwarf_begin (dwp_fd, DWARF_C_READ); + /* There's no way to know whether we got the correct file until + we look up the unit, but it should at least be a dwp file. */ + if (dwp_dwarf != NULL + && (dwp_dwarf->sectiondata[IDX_debug_cu_index] != NULL + || dwp_dwarf->sectiondata[IDX_debug_tu_index] != NULL)) + { + cu->dbg->dwp_dwarf = dwp_dwarf; + cu->dbg->dwp_fd = dwp_fd; + } + else + close (dwp_fd); + } + } + if (cu->dbg->dwp_dwarf == NULL) + cu->dbg->dwp_dwarf = (Dwarf *) -1; + } + + if (cu->dbg->dwp_dwarf != (Dwarf *) -1) + { + Dwarf_CU *split = __libdw_dwp_findcu_id (cu->dbg->dwp_dwarf, + cu->unit_id8); + if (split != NULL) + { + if (tsearch (split->dbg, &cu->dbg->split_tree, + __libdw_finddbg_cb) == NULL) + { + /* Something went wrong. Don't link. */ + __libdw_seterrno (DWARF_E_NOMEM); + return; + } + + /* Link skeleton and split compile units. */ + __libdw_link_skel_split (cu, split); + } + } +} + Dwarf_CU * internal_function __libdw_find_split_unit (Dwarf_CU *cu) @@ -98,14 +159,18 @@ __libdw_find_split_unit (Dwarf_CU *cu) same id as the skeleton. */ if (cu->unit_type == DW_UT_skeleton) { + /* First, try the dwp file. */ + try_dwp_file (cu); + Dwarf_Die cudie = CUDIE (cu); Dwarf_Attribute dwo_name; - /* It is fine if dwo_dir doesn't exists, but then dwo_name needs - to be an absolute path. */ - if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL - || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL) + /* Try a dwo file. It is fine if dwo_dir doesn't exist, but then + dwo_name needs to be an absolute path. */ + if (cu->split == (Dwarf_CU *) -1 + && (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL + || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL)) { - /* First try the dwo file name in the same directory + /* Try the dwo file name in the same directory as we found the skeleton file. */ const char *dwo_file = dwarf_formstring (&dwo_name); const char *debugdir = cu->dbg->debugdir; -- 2.43.0