1*7304104dSAndroid Build Coastguard Worker /* Find the split (or skeleton) unit for a given unit.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
34*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
35*7304104dSAndroid Build Coastguard Worker
36*7304104dSAndroid Build Coastguard Worker #include <limits.h>
37*7304104dSAndroid Build Coastguard Worker #include <search.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
39*7304104dSAndroid Build Coastguard Worker #include <string.h>
40*7304104dSAndroid Build Coastguard Worker #include <sys/types.h>
41*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
42*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker static void
try_split_file(Dwarf_CU * cu,const char * dwo_path)45*7304104dSAndroid Build Coastguard Worker try_split_file (Dwarf_CU *cu, const char *dwo_path)
46*7304104dSAndroid Build Coastguard Worker {
47*7304104dSAndroid Build Coastguard Worker int split_fd = open (dwo_path, O_RDONLY);
48*7304104dSAndroid Build Coastguard Worker if (split_fd != -1)
49*7304104dSAndroid Build Coastguard Worker {
50*7304104dSAndroid Build Coastguard Worker Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
51*7304104dSAndroid Build Coastguard Worker if (split_dwarf != NULL)
52*7304104dSAndroid Build Coastguard Worker {
53*7304104dSAndroid Build Coastguard Worker Dwarf_CU *split = NULL;
54*7304104dSAndroid Build Coastguard Worker while (INTUSE(dwarf_get_units) (split_dwarf, split, &split,
55*7304104dSAndroid Build Coastguard Worker NULL, NULL, NULL, NULL) == 0)
56*7304104dSAndroid Build Coastguard Worker {
57*7304104dSAndroid Build Coastguard Worker if (split->unit_type == DW_UT_split_compile
58*7304104dSAndroid Build Coastguard Worker && cu->unit_id8 == split->unit_id8)
59*7304104dSAndroid Build Coastguard Worker {
60*7304104dSAndroid Build Coastguard Worker if (tsearch (split->dbg, &cu->dbg->split_tree,
61*7304104dSAndroid Build Coastguard Worker __libdw_finddbg_cb) == NULL)
62*7304104dSAndroid Build Coastguard Worker {
63*7304104dSAndroid Build Coastguard Worker /* Something went wrong. Don't link. */
64*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
65*7304104dSAndroid Build Coastguard Worker break;
66*7304104dSAndroid Build Coastguard Worker }
67*7304104dSAndroid Build Coastguard Worker
68*7304104dSAndroid Build Coastguard Worker /* Link skeleton and split compile units. */
69*7304104dSAndroid Build Coastguard Worker __libdw_link_skel_split (cu, split);
70*7304104dSAndroid Build Coastguard Worker
71*7304104dSAndroid Build Coastguard Worker /* We have everything we need from this ELF
72*7304104dSAndroid Build Coastguard Worker file. And we are going to close the fd to
73*7304104dSAndroid Build Coastguard Worker not run out of file descriptors. */
74*7304104dSAndroid Build Coastguard Worker elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
75*7304104dSAndroid Build Coastguard Worker break;
76*7304104dSAndroid Build Coastguard Worker }
77*7304104dSAndroid Build Coastguard Worker }
78*7304104dSAndroid Build Coastguard Worker if (cu->split == (Dwarf_CU *) -1)
79*7304104dSAndroid Build Coastguard Worker dwarf_end (split_dwarf);
80*7304104dSAndroid Build Coastguard Worker }
81*7304104dSAndroid Build Coastguard Worker /* Always close, because we don't want to run out of file
82*7304104dSAndroid Build Coastguard Worker descriptors. See also the elf_fcntl ELF_C_FDDONE call
83*7304104dSAndroid Build Coastguard Worker above. */
84*7304104dSAndroid Build Coastguard Worker close (split_fd);
85*7304104dSAndroid Build Coastguard Worker }
86*7304104dSAndroid Build Coastguard Worker }
87*7304104dSAndroid Build Coastguard Worker
88*7304104dSAndroid Build Coastguard Worker static void
try_dwp_file(Dwarf_CU * cu)89*7304104dSAndroid Build Coastguard Worker try_dwp_file (Dwarf_CU *cu)
90*7304104dSAndroid Build Coastguard Worker {
91*7304104dSAndroid Build Coastguard Worker if (cu->dbg->dwp_dwarf == NULL)
92*7304104dSAndroid Build Coastguard Worker {
93*7304104dSAndroid Build Coastguard Worker if (cu->dbg->elfpath != NULL)
94*7304104dSAndroid Build Coastguard Worker {
95*7304104dSAndroid Build Coastguard Worker /* The DWARF 5 standard says "the package file is typically placed in
96*7304104dSAndroid Build Coastguard Worker the same directory as the application, and is given the same name
97*7304104dSAndroid Build Coastguard Worker with a '.dwp' extension". */
98*7304104dSAndroid Build Coastguard Worker size_t elfpath_len = strlen (cu->dbg->elfpath);
99*7304104dSAndroid Build Coastguard Worker char *dwp_path = malloc (elfpath_len + 5);
100*7304104dSAndroid Build Coastguard Worker if (dwp_path == NULL)
101*7304104dSAndroid Build Coastguard Worker {
102*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
103*7304104dSAndroid Build Coastguard Worker return;
104*7304104dSAndroid Build Coastguard Worker }
105*7304104dSAndroid Build Coastguard Worker memcpy (dwp_path, cu->dbg->elfpath, elfpath_len);
106*7304104dSAndroid Build Coastguard Worker strcpy (dwp_path + elfpath_len, ".dwp");
107*7304104dSAndroid Build Coastguard Worker int dwp_fd = open (dwp_path, O_RDONLY);
108*7304104dSAndroid Build Coastguard Worker free (dwp_path);
109*7304104dSAndroid Build Coastguard Worker if (dwp_fd != -1)
110*7304104dSAndroid Build Coastguard Worker {
111*7304104dSAndroid Build Coastguard Worker Dwarf *dwp_dwarf = dwarf_begin (dwp_fd, DWARF_C_READ);
112*7304104dSAndroid Build Coastguard Worker /* There's no way to know whether we got the correct file until
113*7304104dSAndroid Build Coastguard Worker we look up the unit, but it should at least be a dwp file. */
114*7304104dSAndroid Build Coastguard Worker if (dwp_dwarf != NULL
115*7304104dSAndroid Build Coastguard Worker && (dwp_dwarf->sectiondata[IDX_debug_cu_index] != NULL
116*7304104dSAndroid Build Coastguard Worker || dwp_dwarf->sectiondata[IDX_debug_tu_index] != NULL))
117*7304104dSAndroid Build Coastguard Worker {
118*7304104dSAndroid Build Coastguard Worker cu->dbg->dwp_dwarf = dwp_dwarf;
119*7304104dSAndroid Build Coastguard Worker cu->dbg->dwp_fd = dwp_fd;
120*7304104dSAndroid Build Coastguard Worker }
121*7304104dSAndroid Build Coastguard Worker else
122*7304104dSAndroid Build Coastguard Worker close (dwp_fd);
123*7304104dSAndroid Build Coastguard Worker }
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker if (cu->dbg->dwp_dwarf == NULL)
126*7304104dSAndroid Build Coastguard Worker cu->dbg->dwp_dwarf = (Dwarf *) -1;
127*7304104dSAndroid Build Coastguard Worker }
128*7304104dSAndroid Build Coastguard Worker
129*7304104dSAndroid Build Coastguard Worker if (cu->dbg->dwp_dwarf != (Dwarf *) -1)
130*7304104dSAndroid Build Coastguard Worker {
131*7304104dSAndroid Build Coastguard Worker Dwarf_CU *split = __libdw_dwp_findcu_id (cu->dbg->dwp_dwarf,
132*7304104dSAndroid Build Coastguard Worker cu->unit_id8);
133*7304104dSAndroid Build Coastguard Worker if (split != NULL)
134*7304104dSAndroid Build Coastguard Worker {
135*7304104dSAndroid Build Coastguard Worker if (tsearch (split->dbg, &cu->dbg->split_tree,
136*7304104dSAndroid Build Coastguard Worker __libdw_finddbg_cb) == NULL)
137*7304104dSAndroid Build Coastguard Worker {
138*7304104dSAndroid Build Coastguard Worker /* Something went wrong. Don't link. */
139*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
140*7304104dSAndroid Build Coastguard Worker return;
141*7304104dSAndroid Build Coastguard Worker }
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker /* Link skeleton and split compile units. */
144*7304104dSAndroid Build Coastguard Worker __libdw_link_skel_split (cu, split);
145*7304104dSAndroid Build Coastguard Worker }
146*7304104dSAndroid Build Coastguard Worker }
147*7304104dSAndroid Build Coastguard Worker }
148*7304104dSAndroid Build Coastguard Worker
149*7304104dSAndroid Build Coastguard Worker Dwarf_CU *
150*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_find_split_unit(Dwarf_CU * cu)151*7304104dSAndroid Build Coastguard Worker __libdw_find_split_unit (Dwarf_CU *cu)
152*7304104dSAndroid Build Coastguard Worker {
153*7304104dSAndroid Build Coastguard Worker /* Only try once. */
154*7304104dSAndroid Build Coastguard Worker if (cu->split != (Dwarf_CU *) -1)
155*7304104dSAndroid Build Coastguard Worker return cu->split;
156*7304104dSAndroid Build Coastguard Worker
157*7304104dSAndroid Build Coastguard Worker /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
158*7304104dSAndroid Build Coastguard Worker The split unit will be the first in the dwo file and should have the
159*7304104dSAndroid Build Coastguard Worker same id as the skeleton. */
160*7304104dSAndroid Build Coastguard Worker if (cu->unit_type == DW_UT_skeleton)
161*7304104dSAndroid Build Coastguard Worker {
162*7304104dSAndroid Build Coastguard Worker /* First, try the dwp file. */
163*7304104dSAndroid Build Coastguard Worker try_dwp_file (cu);
164*7304104dSAndroid Build Coastguard Worker
165*7304104dSAndroid Build Coastguard Worker Dwarf_Die cudie = CUDIE (cu);
166*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute dwo_name;
167*7304104dSAndroid Build Coastguard Worker /* Try a dwo file. It is fine if dwo_dir doesn't exist, but then
168*7304104dSAndroid Build Coastguard Worker dwo_name needs to be an absolute path. */
169*7304104dSAndroid Build Coastguard Worker if (cu->split == (Dwarf_CU *) -1
170*7304104dSAndroid Build Coastguard Worker && (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
171*7304104dSAndroid Build Coastguard Worker || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL))
172*7304104dSAndroid Build Coastguard Worker {
173*7304104dSAndroid Build Coastguard Worker /* Try the dwo file name in the same directory
174*7304104dSAndroid Build Coastguard Worker as we found the skeleton file. */
175*7304104dSAndroid Build Coastguard Worker const char *dwo_file = dwarf_formstring (&dwo_name);
176*7304104dSAndroid Build Coastguard Worker const char *debugdir = cu->dbg->debugdir;
177*7304104dSAndroid Build Coastguard Worker char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
178*7304104dSAndroid Build Coastguard Worker if (dwo_path != NULL)
179*7304104dSAndroid Build Coastguard Worker {
180*7304104dSAndroid Build Coastguard Worker try_split_file (cu, dwo_path);
181*7304104dSAndroid Build Coastguard Worker free (dwo_path);
182*7304104dSAndroid Build Coastguard Worker }
183*7304104dSAndroid Build Coastguard Worker
184*7304104dSAndroid Build Coastguard Worker if (cu->split == (Dwarf_CU *) -1)
185*7304104dSAndroid Build Coastguard Worker {
186*7304104dSAndroid Build Coastguard Worker /* Try compdir plus dwo_name. */
187*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute compdir;
188*7304104dSAndroid Build Coastguard Worker dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
189*7304104dSAndroid Build Coastguard Worker const char *dwo_dir = dwarf_formstring (&compdir);
190*7304104dSAndroid Build Coastguard Worker if (dwo_dir != NULL)
191*7304104dSAndroid Build Coastguard Worker {
192*7304104dSAndroid Build Coastguard Worker dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
193*7304104dSAndroid Build Coastguard Worker if (dwo_path != NULL)
194*7304104dSAndroid Build Coastguard Worker {
195*7304104dSAndroid Build Coastguard Worker try_split_file (cu, dwo_path);
196*7304104dSAndroid Build Coastguard Worker free (dwo_path);
197*7304104dSAndroid Build Coastguard Worker }
198*7304104dSAndroid Build Coastguard Worker }
199*7304104dSAndroid Build Coastguard Worker }
200*7304104dSAndroid Build Coastguard Worker /* XXX If still not found we could try stripping dirs from the
201*7304104dSAndroid Build Coastguard Worker comp_dir and adding them from the comp_dir, assuming
202*7304104dSAndroid Build Coastguard Worker someone moved a whole build tree around. */
203*7304104dSAndroid Build Coastguard Worker }
204*7304104dSAndroid Build Coastguard Worker }
205*7304104dSAndroid Build Coastguard Worker
206*7304104dSAndroid Build Coastguard Worker /* If we found nothing, make sure we don't try again. */
207*7304104dSAndroid Build Coastguard Worker if (cu->split == (Dwarf_CU *) -1)
208*7304104dSAndroid Build Coastguard Worker cu->split = NULL;
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker return cu->split;
211*7304104dSAndroid Build Coastguard Worker }
212