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