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 : 49 : 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 : : }