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 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 if (dbg == NULL) 44 return -1; 45 46 Elf_Data *lines = dbg->sectiondata[IDX_debug_line]; 47 if (lines == NULL) 48 { 49 __libdw_seterrno (DWARF_E_NO_DEBUG_LINE); 50 return -1; 51 } 52 53 if (off == (Dwarf_Off) -1 54 || lines->d_size < 4 55 || off >= lines->d_size) 56 { 57 *next_off = (Dwarf_Off) -1; 58 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 const unsigned char *linep = lines->d_buf + off; 64 const unsigned char *lineendp = lines->d_buf + lines->d_size; 65 66 if ((size_t) (lineendp - linep) < 4) 67 { 68 invalid_data: 69 __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); 70 return -1; 71 } 72 73 *next_off = off + 4; 74 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 75 if (unit_length == DWARF3_LENGTH_64_BIT) 76 { 77 if ((size_t) (lineendp - linep) < 8) 78 goto invalid_data; 79 unit_length = read_8ubyte_unaligned_inc (dbg, linep); 80 *next_off += 8; 81 } 82 83 if (unit_length > (size_t) (lineendp - linep)) 84 goto invalid_data; 85 86 *next_off += unit_length; 87 lineendp = linep + unit_length; 88 89 if ((size_t) (lineendp - linep) < 2) 90 goto invalid_data; 91 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 92 93 Dwarf_Die cudie; 94 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. */ 99 Dwarf_CU *given_cu = *cu; 100 Dwarf_CU *next_cu = given_cu; 101 bool found = false; 102 while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL, 103 &cudie, NULL) == 0) 104 { 105 if (dwarf_hasattr (&cudie, DW_AT_stmt_list)) 106 { 107 Dwarf_Attribute attr; 108 Dwarf_Word stmt_off; 109 if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr), 110 &stmt_off) == 0 111 && stmt_off == off) 112 { 113 found = true; 114 break; 115 } 116 } 117 else if (off == 0 118 && (next_cu->unit_type == DW_UT_split_compile 119 || next_cu->unit_type == DW_UT_split_type)) 120 { 121 /* For split units (in .dwo files) there is only one table 122 at offset zero (containing just the files, no lines). */ 123 found = true; 124 break; 125 } 126 } 127 128 if (!found && given_cu != NULL) 129 { 130 /* The CUs might be in a different order from the line 131 tables. Need to do a linear search (but stop at the given 132 CU, since we already searched those. */ 133 next_cu = NULL; 134 while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL, 135 &cudie, NULL) == 0 136 && next_cu != given_cu) 137 { 138 Dwarf_Attribute attr; 139 Dwarf_Word stmt_off; 140 if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr), 141 &stmt_off) == 0 142 && stmt_off == off) 143 { 144 found = true; 145 break; 146 } 147 } 148 } 149 150 if (found) 151 *cu = next_cu; 152 else 153 *cu = NULL; 154 } 155 else 156 *cu = NULL; 157 158 const char *comp_dir; 159 unsigned address_size; 160 if (*cu != NULL) 161 { 162 comp_dir = __libdw_getcompdir (&cudie); 163 address_size = (*cu)->address_size; 164 } 165 else 166 { 167 comp_dir = NULL; 168 169 size_t esize; 170 char *ident = elf_getident (dbg->elf, &esize); 171 if (ident == NULL || esize < EI_NIDENT) 172 goto invalid_data; 173 address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 174 } 175 176 if (__libdw_getsrclines (dbg, off, comp_dir, address_size, 177 srclines, srcfiles) != 0) 178 return -1; 179 180 if (nlines != NULL) 181 { 182 if (srclines != NULL && *srclines != NULL) 183 *nlines = (*srclines)->nlines; 184 else 185 *nlines = 0; 186 } 187 188 if (nfiles != NULL) 189 { 190 if (srcfiles != NULL && *srcfiles != NULL) 191 *nfiles = (*srcfiles)->nfiles; 192 else 193 *nfiles = 0; 194 } 195 196 return 0; 197 } 198