Branch data Line data Source code
1 : : /* Find the split (or skeleton) unit for a given unit.
2 : : Copyright (C) 2018 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include "libdwP.h"
34 : : #include "libelfP.h"
35 : :
36 : : #include <limits.h>
37 : : #include <search.h>
38 : : #include <stdlib.h>
39 : : #include <string.h>
40 : : #include <sys/types.h>
41 : : #include <sys/stat.h>
42 : : #include <fcntl.h>
43 : : #include <unistd.h>
44 : :
45 : : void
46 : 50 : try_split_file (Dwarf_CU *cu, const char *dwo_path)
47 : : {
48 : 50 : int split_fd = open (dwo_path, O_RDONLY);
49 [ + + ]: 50 : if (split_fd != -1)
50 : : {
51 : 49 : Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
52 [ + - ]: 49 : if (split_dwarf != NULL)
53 : : {
54 : 49 : Dwarf_CU *split = NULL;
55 [ + + ]: 50 : while (dwarf_get_units (split_dwarf, split, &split,
56 : : NULL, NULL, NULL, NULL) == 0)
57 : : {
58 [ + - ]: 49 : if (split->unit_type == DW_UT_split_compile
59 [ + + ]: 49 : && cu->unit_id8 == split->unit_id8)
60 : : {
61 [ - + ]: 48 : if (tsearch (split->dbg, &cu->dbg->split_tree,
62 : : __libdw_finddbg_cb) == NULL)
63 : : {
64 : : /* Something went wrong. Don't link. */
65 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
66 : 0 : break;
67 : : }
68 : :
69 : : /* Link skeleton and split compile units. */
70 : 48 : __libdw_link_skel_split (cu, split);
71 : :
72 : : /* We have everything we need from this ELF
73 : : file. And we are going to close the fd to
74 : : not run out of file descriptors. */
75 : 48 : elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
76 : 48 : break;
77 : : }
78 : : }
79 [ + + ]: 49 : if (cu->split == (Dwarf_CU *) -1)
80 : 1 : dwarf_end (split_dwarf);
81 : : }
82 : : /* Always close, because we don't want to run out of file
83 : : descriptors. See also the elf_fcntl ELF_C_FDDONE call
84 : : above. */
85 : 49 : close (split_fd);
86 : : }
87 : 50 : }
88 : :
89 : : Dwarf_CU *
90 : : internal_function
91 : 310 : __libdw_find_split_unit (Dwarf_CU *cu)
92 : : {
93 : : /* Only try once. */
94 [ + + ]: 310 : if (cu->split != (Dwarf_CU *) -1)
95 : : return cu->split;
96 : :
97 : : /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
98 : : The split unit will be the first in the dwo file and should have the
99 : : same id as the skeleton. */
100 [ + - ]: 49 : if (cu->unit_type == DW_UT_skeleton)
101 : : {
102 : 98 : Dwarf_Die cudie = CUDIE (cu);
103 : 49 : Dwarf_Attribute dwo_name;
104 : : /* It is fine if dwo_dir doesn't exists, but then dwo_name needs
105 : : to be an absolute path. */
106 [ + + ]: 49 : if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
107 [ + - ]: 26 : || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL)
108 : : {
109 : : /* First try the dwo file name in the same directory
110 : : as we found the skeleton file. */
111 : 49 : const char *dwo_file = dwarf_formstring (&dwo_name);
112 : 49 : const char *debugdir = cu->dbg->debugdir;
113 : 49 : char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
114 [ + - ]: 49 : if (dwo_path != NULL)
115 : : {
116 : 49 : try_split_file (cu, dwo_path);
117 : 49 : free (dwo_path);
118 : : }
119 : :
120 [ + + ]: 49 : if (cu->split == (Dwarf_CU *) -1)
121 : : {
122 : : /* Try compdir plus dwo_name. */
123 : 1 : Dwarf_Attribute compdir;
124 : 1 : dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
125 : 1 : const char *dwo_dir = dwarf_formstring (&compdir);
126 [ + - ]: 1 : if (dwo_dir != NULL)
127 : : {
128 : 1 : dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
129 [ + - ]: 1 : if (dwo_path != NULL)
130 : : {
131 : 1 : try_split_file (cu, dwo_path);
132 : 1 : free (dwo_path);
133 : : }
134 : : }
135 : : }
136 : : /* XXX If still not found we could try stripping dirs from the
137 : : comp_dir and adding them from the comp_dir, assuming
138 : : someone moved a whole build tree around. */
139 : : }
140 : : }
141 : :
142 : : /* If we found nothing, make sure we don't try again. */
143 [ + + ]: 49 : if (cu->split == (Dwarf_CU *) -1)
144 : 1 : cu->split = NULL;
145 : :
146 : 49 : return cu->split;
147 : : }
|