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 : 127 : 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 [ + - ]: 127 : if (dbg == NULL)
44 : : return -1;
45 : :
46 : 127 : Elf_Data *lines = dbg->sectiondata[IDX_debug_line];
47 [ - + ]: 127 : if (lines == NULL)
48 : : {
49 : 0 : __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
50 : 0 : return -1;
51 : : }
52 : :
53 [ + - ]: 127 : if (off == (Dwarf_Off) -1
54 [ + - ]: 127 : || lines->d_size < 4
55 [ + + ]: 127 : || off >= lines->d_size)
56 : : {
57 : 53 : *next_off = (Dwarf_Off) -1;
58 : 53 : 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 : 74 : const unsigned char *linep = lines->d_buf + off;
64 : 74 : const unsigned char *lineendp = lines->d_buf + lines->d_size;
65 : :
66 [ - + ]: 74 : 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 : 74 : *next_off = off + 4;
74 [ + + ]: 74 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
75 [ - + ]: 74 : 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 [ - + ]: 74 : if (unit_length > (size_t) (lineendp - linep))
84 : 0 : goto invalid_data;
85 : :
86 : 74 : *next_off += unit_length;
87 : 74 : lineendp = linep + unit_length;
88 : :
89 [ - + ]: 74 : if ((size_t) (lineendp - linep) < 2)
90 : 0 : goto invalid_data;
91 [ + + ]: 74 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
92 : :
93 : 74 : Dwarf_Die cudie;
94 [ + + ]: 74 : 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 : 68 : Dwarf_CU *given_cu = *cu;
100 : 68 : Dwarf_CU *next_cu = given_cu;
101 : 68 : bool found = false;
102 : 68 : while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
103 [ + + ]: 68 : &cudie, NULL) == 0)
104 : : {
105 [ + + ]: 61 : if (dwarf_hasattr (&cudie, DW_AT_stmt_list))
106 : : {
107 : 59 : Dwarf_Attribute attr;
108 : 59 : Dwarf_Word stmt_off;
109 [ + - ]: 59 : if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
110 : : &stmt_off) == 0
111 [ + - ]: 59 : && stmt_off == off)
112 : : {
113 : 59 : found = true;
114 : 59 : break;
115 : : }
116 : : }
117 [ + - ]: 2 : else if (off == 0
118 : 2 : && (next_cu->unit_type == DW_UT_split_compile
119 [ + - ]: 2 : || 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 [ - + ]: 68 : 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 : 0 : next_cu = NULL;
134 : 0 : while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
135 : : &cudie, NULL) == 0
136 [ # # # # ]: 0 : && next_cu != given_cu)
137 : : {
138 : 0 : Dwarf_Attribute attr;
139 : 0 : Dwarf_Word stmt_off;
140 [ # # ]: 0 : if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
141 : : &stmt_off) == 0
142 [ # # ]: 0 : && stmt_off == off)
143 : : {
144 : 0 : found = true;
145 : 0 : break;
146 : : }
147 : : }
148 : : }
149 : :
150 [ + + ]: 68 : if (found)
151 : 61 : *cu = next_cu;
152 : : else
153 : 7 : *cu = NULL;
154 : : }
155 : : else
156 : 6 : *cu = NULL;
157 : :
158 : 74 : const char *comp_dir;
159 : 74 : unsigned address_size;
160 [ + + ]: 74 : if (*cu != NULL)
161 : : {
162 : 61 : comp_dir = __libdw_getcompdir (&cudie);
163 : 61 : address_size = (*cu)->address_size;
164 : : }
165 : : else
166 : : {
167 : 13 : comp_dir = NULL;
168 : :
169 : 13 : size_t esize;
170 : 13 : char *ident = elf_getident (dbg->elf, &esize);
171 [ + - - + ]: 13 : if (ident == NULL || esize < EI_NIDENT)
172 : 0 : goto invalid_data;
173 [ + + ]: 20 : address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
174 : : }
175 : :
176 [ + - ]: 74 : if (__libdw_getsrclines (dbg, off, comp_dir, address_size,
177 : : srclines, srcfiles) != 0)
178 : : return -1;
179 : :
180 [ + + ]: 74 : if (nlines != NULL)
181 : : {
182 [ + - + - ]: 57 : if (srclines != NULL && *srclines != NULL)
183 : 57 : *nlines = (*srclines)->nlines;
184 : : else
185 : 0 : *nlines = 0;
186 : : }
187 : :
188 [ + + ]: 74 : if (nfiles != NULL)
189 : : {
190 [ + - + - ]: 17 : if (srcfiles != NULL && *srcfiles != NULL)
191 : 17 : *nfiles = (*srcfiles)->nfiles;
192 : : else
193 : 0 : *nfiles = 0;
194 : : }
195 : :
196 : : return 0;
197 : : }
|