Branch data Line data Source code
1 : : /* Iterate through the debug line table. 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 : : 35 : : 36 : : int 37 : 310 : dwarf_next_lines (Dwarf *dbg, Dwarf_Off off, 38 : : Dwarf_Off *next_off, Dwarf_CU **cu, 39 : : Dwarf_Files **srcfiles, size_t *nfiles, 40 : : Dwarf_Lines **srclines, size_t *nlines) 41 : : { 42 : : /* Ignore existing errors. */ 43 [ + - ]: 310 : if (dbg == NULL) 44 : : return -1; 45 : : 46 : 310 : Elf_Data *lines = dbg->sectiondata[IDX_debug_line]; 47 [ - + ]: 310 : if (lines == NULL) 48 : : { 49 : 0 : __libdw_seterrno (DWARF_E_NO_DEBUG_LINE); 50 : 0 : return -1; 51 : : } 52 : : 53 [ + - ]: 310 : if (off == (Dwarf_Off) -1 54 [ + - ]: 310 : || lines->d_size < 4 55 [ + + ]: 310 : || off >= lines->d_size) 56 : : { 57 : 122 : *next_off = (Dwarf_Off) -1; 58 : 122 : return 1; 59 : : } 60 : : 61 : : /* Read enough of the header to know where the next table is and 62 : : whether we need to lookup the CU (version < 5). */ 63 : 188 : const unsigned char *linep = lines->d_buf + off; 64 : 188 : const unsigned char *lineendp = lines->d_buf + lines->d_size; 65 : : 66 [ - + ]: 188 : if ((size_t) (lineendp - linep) < 4) 67 : : { 68 : 0 : invalid_data: 69 : 0 : __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); 70 : 0 : return -1; 71 : : } 72 : : 73 : 188 : *next_off = off + 4; 74 [ + + ]: 188 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 75 [ - + ]: 188 : if (unit_length == DWARF3_LENGTH_64_BIT) 76 : : { 77 [ # # ]: 0 : if ((size_t) (lineendp - linep) < 8) 78 : 0 : goto invalid_data; 79 [ # # ]: 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep); 80 : 0 : *next_off += 8; 81 : : } 82 : : 83 [ - + ]: 188 : if (unit_length > (size_t) (lineendp - linep)) 84 : 0 : goto invalid_data; 85 : : 86 : 188 : *next_off += unit_length; 87 : 188 : lineendp = linep + unit_length; 88 : : 89 [ - + ]: 188 : if ((size_t) (lineendp - linep) < 2) 90 : 0 : goto invalid_data; 91 [ + + ]: 188 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 92 : : 93 : 188 : Dwarf_Die cudie; 94 [ + + ]: 188 : if (version < 5) 95 : : { 96 : : /* We need to find the matching CU to get the comp_dir. Use the 97 : : given CU as hint where to start searching. Normally it will 98 : : be the next CU that has a statement list. If the CUs are in a 99 : : different order from the line tables, then we do a linear 100 : : search. */ 101 : 118 : Dwarf_CU *given_cu = *cu; 102 : 118 : Dwarf_CU *next_cu = given_cu; 103 : 118 : bool restarted = false; 104 : 132 : while (1) 105 : : { 106 [ + + ]: 132 : if (restarted && next_cu == given_cu) 107 : : { 108 : : /* We checked all of the CUs and there was no match. */ 109 : 14 : *cu = NULL; 110 : 118 : break; 111 : : } 112 [ + + ]: 118 : if (INTUSE(dwarf_get_units) (dbg, next_cu, &next_cu, NULL, NULL, 113 : : &cudie, NULL) != 0) 114 : : { 115 : : /* We didn't find the matching CU after the starting point. 116 : : Check the CUs up to the starting point. */ 117 : 14 : next_cu = NULL; 118 : 14 : restarted = true; 119 : 14 : continue; 120 : : } 121 : : 122 : 104 : Dwarf_Word stmt_off = 0; 123 [ + + ]: 104 : if (dwarf_hasattr (&cudie, DW_AT_stmt_list)) 124 : : { 125 : 94 : Dwarf_Attribute attr; 126 [ - + ]: 94 : if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr), 127 : : &stmt_off) != 0) 128 : 0 : continue; 129 : : } 130 : : /* Split units have an implicit offset of 0. */ 131 : 10 : else if (next_cu->unit_type != DW_UT_split_compile 132 [ - + ]: 10 : && next_cu->unit_type != DW_UT_split_type) 133 : 0 : continue; 134 : : 135 : 104 : Dwarf_Off dwp_off; 136 [ + - ]: 104 : if (INTUSE(dwarf_cu_dwp_section_info) (next_cu, DW_SECT_LINE, 137 : : &dwp_off, NULL) == 0) 138 : 104 : stmt_off += dwp_off; 139 : : 140 [ + - ]: 104 : if (stmt_off == off) 141 : : { 142 : 104 : *cu = next_cu; 143 : 104 : break; 144 : : } 145 : : } 146 : : } 147 : : else 148 : 70 : *cu = NULL; 149 : : 150 : 188 : const char *comp_dir; 151 : 188 : unsigned address_size; 152 [ + + ]: 188 : if (*cu != NULL) 153 : : { 154 : 104 : comp_dir = __libdw_getcompdir (&cudie); 155 : 104 : address_size = (*cu)->address_size; 156 : : } 157 : : else 158 : : { 159 : 84 : comp_dir = NULL; 160 : : 161 : 84 : size_t esize; 162 : 84 : char *ident = elf_getident (dbg->elf, &esize); 163 [ + - - + ]: 84 : if (ident == NULL || esize < EI_NIDENT) 164 : 0 : goto invalid_data; 165 [ + + ]: 156 : address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 166 : : } 167 : : 168 [ + - ]: 188 : if (__libdw_getsrclines (dbg, off, comp_dir, address_size, 169 : : srclines, srcfiles) != 0) 170 : : return -1; 171 : : 172 [ + + ]: 188 : if (nlines != NULL) 173 : : { 174 [ + - + - ]: 130 : if (srclines != NULL && *srclines != NULL) 175 : 130 : *nlines = (*srclines)->nlines; 176 : : else 177 : 0 : *nlines = 0; 178 : : } 179 : : 180 [ + + ]: 188 : if (nfiles != NULL) 181 : : { 182 [ + - + - ]: 58 : if (srcfiles != NULL && *srcfiles != NULL) 183 : 58 : *nfiles = (*srcfiles)->nfiles; 184 : : else 185 : 0 : *nfiles = 0; 186 : : } 187 : : 188 : : return 0; 189 : : }