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 : : 44 : : static void 45 : 100 : try_split_file (Dwarf_CU *cu, const char *dwo_path) 46 : : { 47 : 100 : int split_fd = open (dwo_path, O_RDONLY); 48 [ + + ]: 100 : if (split_fd != -1) 49 : : { 50 : 98 : Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ); 51 [ + - ]: 98 : if (split_dwarf != NULL) 52 : : { 53 : 98 : Dwarf_CU *split = NULL; 54 : 98 : while (dwarf_get_units (split_dwarf, split, &split, 55 [ + + ]: 100 : NULL, NULL, NULL, NULL) == 0) 56 : : { 57 [ + - ]: 98 : if (split->unit_type == DW_UT_split_compile 58 [ + + ]: 98 : && cu->unit_id8 == split->unit_id8) 59 : : { 60 [ - + ]: 96 : if (tsearch (split->dbg, &cu->dbg->split_tree, 61 : : __libdw_finddbg_cb) == NULL) 62 : : { 63 : : /* Something went wrong. Don't link. */ 64 : 0 : __libdw_seterrno (DWARF_E_NOMEM); 65 : 0 : break; 66 : : } 67 : : 68 : : /* Link skeleton and split compile units. */ 69 : 96 : __libdw_link_skel_split (cu, split); 70 : : 71 : : /* We have everything we need from this ELF 72 : : file. And we are going to close the fd to 73 : : not run out of file descriptors. */ 74 : 96 : elf_cntl (split_dwarf->elf, ELF_C_FDDONE); 75 : 96 : break; 76 : : } 77 : : } 78 [ + + ]: 98 : if (cu->split == (Dwarf_CU *) -1) 79 : 2 : dwarf_end (split_dwarf); 80 : : } 81 : : /* Always close, because we don't want to run out of file 82 : : descriptors. See also the elf_fcntl ELF_C_FDDONE call 83 : : above. */ 84 : 98 : close (split_fd); 85 : : } 86 : 100 : } 87 : : 88 : : Dwarf_CU * 89 : : internal_function 90 : 642 : __libdw_find_split_unit (Dwarf_CU *cu) 91 : : { 92 : : /* Only try once. */ 93 [ + + ]: 642 : if (cu->split != (Dwarf_CU *) -1) 94 : : return cu->split; 95 : : 96 : : /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes. 97 : : The split unit will be the first in the dwo file and should have the 98 : : same id as the skeleton. */ 99 [ + - ]: 98 : if (cu->unit_type == DW_UT_skeleton) 100 : : { 101 : 98 : Dwarf_Die cudie = CUDIE (cu); 102 : 98 : Dwarf_Attribute dwo_name; 103 : : /* It is fine if dwo_dir doesn't exists, but then dwo_name needs 104 : : to be an absolute path. */ 105 [ + + ]: 98 : if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL 106 [ + - ]: 52 : || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL) 107 : : { 108 : : /* First try the dwo file name in the same directory 109 : : as we found the skeleton file. */ 110 : 98 : const char *dwo_file = dwarf_formstring (&dwo_name); 111 : 98 : const char *debugdir = cu->dbg->debugdir; 112 : 98 : char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file); 113 [ + - ]: 98 : if (dwo_path != NULL) 114 : : { 115 : 98 : try_split_file (cu, dwo_path); 116 : 98 : free (dwo_path); 117 : : } 118 : : 119 [ + + ]: 98 : if (cu->split == (Dwarf_CU *) -1) 120 : : { 121 : : /* Try compdir plus dwo_name. */ 122 : 2 : Dwarf_Attribute compdir; 123 : 2 : dwarf_attr (&cudie, DW_AT_comp_dir, &compdir); 124 : 2 : const char *dwo_dir = dwarf_formstring (&compdir); 125 [ + - ]: 2 : if (dwo_dir != NULL) 126 : : { 127 : 2 : dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file); 128 [ + - ]: 2 : if (dwo_path != NULL) 129 : : { 130 : 2 : try_split_file (cu, dwo_path); 131 : 2 : free (dwo_path); 132 : : } 133 : : } 134 : : } 135 : : /* XXX If still not found we could try stripping dirs from the 136 : : comp_dir and adding them from the comp_dir, assuming 137 : : someone moved a whole build tree around. */ 138 : : } 139 : : } 140 : : 141 : : /* If we found nothing, make sure we don't try again. */ 142 [ + + ]: 98 : if (cu->split == (Dwarf_CU *) -1) 143 : 2 : cu->split = NULL; 144 : : 145 : 98 : return cu->split; 146 : : }