1*7304104dSAndroid Build Coastguard Worker /* Iterate through the debug line table.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include <libdwP.h>
34*7304104dSAndroid Build Coastguard Worker
35*7304104dSAndroid Build Coastguard Worker
36*7304104dSAndroid Build Coastguard Worker int
dwarf_next_lines(Dwarf * dbg,Dwarf_Off off,Dwarf_Off * next_off,Dwarf_CU ** cu,Dwarf_Files ** srcfiles,size_t * nfiles,Dwarf_Lines ** srclines,size_t * nlines)37*7304104dSAndroid Build Coastguard Worker dwarf_next_lines (Dwarf *dbg, Dwarf_Off off,
38*7304104dSAndroid Build Coastguard Worker Dwarf_Off *next_off, Dwarf_CU **cu,
39*7304104dSAndroid Build Coastguard Worker Dwarf_Files **srcfiles, size_t *nfiles,
40*7304104dSAndroid Build Coastguard Worker Dwarf_Lines **srclines, size_t *nlines)
41*7304104dSAndroid Build Coastguard Worker {
42*7304104dSAndroid Build Coastguard Worker /* Ignore existing errors. */
43*7304104dSAndroid Build Coastguard Worker if (dbg == NULL)
44*7304104dSAndroid Build Coastguard Worker return -1;
45*7304104dSAndroid Build Coastguard Worker
46*7304104dSAndroid Build Coastguard Worker Elf_Data *lines = dbg->sectiondata[IDX_debug_line];
47*7304104dSAndroid Build Coastguard Worker if (lines == NULL)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
50*7304104dSAndroid Build Coastguard Worker return -1;
51*7304104dSAndroid Build Coastguard Worker }
52*7304104dSAndroid Build Coastguard Worker
53*7304104dSAndroid Build Coastguard Worker if (off == (Dwarf_Off) -1
54*7304104dSAndroid Build Coastguard Worker || lines->d_size < 4
55*7304104dSAndroid Build Coastguard Worker || off >= lines->d_size)
56*7304104dSAndroid Build Coastguard Worker {
57*7304104dSAndroid Build Coastguard Worker *next_off = (Dwarf_Off) -1;
58*7304104dSAndroid Build Coastguard Worker return 1;
59*7304104dSAndroid Build Coastguard Worker }
60*7304104dSAndroid Build Coastguard Worker
61*7304104dSAndroid Build Coastguard Worker /* Read enough of the header to know where the next table is and
62*7304104dSAndroid Build Coastguard Worker whether we need to lookup the CU (version < 5). */
63*7304104dSAndroid Build Coastguard Worker const unsigned char *linep = lines->d_buf + off;
64*7304104dSAndroid Build Coastguard Worker const unsigned char *lineendp = lines->d_buf + lines->d_size;
65*7304104dSAndroid Build Coastguard Worker
66*7304104dSAndroid Build Coastguard Worker if ((size_t) (lineendp - linep) < 4)
67*7304104dSAndroid Build Coastguard Worker {
68*7304104dSAndroid Build Coastguard Worker invalid_data:
69*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
70*7304104dSAndroid Build Coastguard Worker return -1;
71*7304104dSAndroid Build Coastguard Worker }
72*7304104dSAndroid Build Coastguard Worker
73*7304104dSAndroid Build Coastguard Worker *next_off = off + 4;
74*7304104dSAndroid Build Coastguard Worker Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
75*7304104dSAndroid Build Coastguard Worker if (unit_length == DWARF3_LENGTH_64_BIT)
76*7304104dSAndroid Build Coastguard Worker {
77*7304104dSAndroid Build Coastguard Worker if ((size_t) (lineendp - linep) < 8)
78*7304104dSAndroid Build Coastguard Worker goto invalid_data;
79*7304104dSAndroid Build Coastguard Worker unit_length = read_8ubyte_unaligned_inc (dbg, linep);
80*7304104dSAndroid Build Coastguard Worker *next_off += 8;
81*7304104dSAndroid Build Coastguard Worker }
82*7304104dSAndroid Build Coastguard Worker
83*7304104dSAndroid Build Coastguard Worker if (unit_length > (size_t) (lineendp - linep))
84*7304104dSAndroid Build Coastguard Worker goto invalid_data;
85*7304104dSAndroid Build Coastguard Worker
86*7304104dSAndroid Build Coastguard Worker *next_off += unit_length;
87*7304104dSAndroid Build Coastguard Worker lineendp = linep + unit_length;
88*7304104dSAndroid Build Coastguard Worker
89*7304104dSAndroid Build Coastguard Worker if ((size_t) (lineendp - linep) < 2)
90*7304104dSAndroid Build Coastguard Worker goto invalid_data;
91*7304104dSAndroid Build Coastguard Worker uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
92*7304104dSAndroid Build Coastguard Worker
93*7304104dSAndroid Build Coastguard Worker Dwarf_Die cudie;
94*7304104dSAndroid Build Coastguard Worker if (version < 5)
95*7304104dSAndroid Build Coastguard Worker {
96*7304104dSAndroid Build Coastguard Worker /* We need to find the matching CU to get the comp_dir. Use the
97*7304104dSAndroid Build Coastguard Worker given CU as hint where to start searching. Normally it will
98*7304104dSAndroid Build Coastguard Worker be the next CU that has a statement list. If the CUs are in a
99*7304104dSAndroid Build Coastguard Worker different order from the line tables, then we do a linear
100*7304104dSAndroid Build Coastguard Worker search. */
101*7304104dSAndroid Build Coastguard Worker Dwarf_CU *given_cu = *cu;
102*7304104dSAndroid Build Coastguard Worker Dwarf_CU *next_cu = given_cu;
103*7304104dSAndroid Build Coastguard Worker bool restarted = false;
104*7304104dSAndroid Build Coastguard Worker while (1)
105*7304104dSAndroid Build Coastguard Worker {
106*7304104dSAndroid Build Coastguard Worker if (restarted && next_cu == given_cu)
107*7304104dSAndroid Build Coastguard Worker {
108*7304104dSAndroid Build Coastguard Worker /* We checked all of the CUs and there was no match. */
109*7304104dSAndroid Build Coastguard Worker *cu = NULL;
110*7304104dSAndroid Build Coastguard Worker break;
111*7304104dSAndroid Build Coastguard Worker }
112*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_get_units) (dbg, next_cu, &next_cu, NULL, NULL,
113*7304104dSAndroid Build Coastguard Worker &cudie, NULL) != 0)
114*7304104dSAndroid Build Coastguard Worker {
115*7304104dSAndroid Build Coastguard Worker /* We didn't find the matching CU after the starting point.
116*7304104dSAndroid Build Coastguard Worker Check the CUs up to the starting point. */
117*7304104dSAndroid Build Coastguard Worker next_cu = NULL;
118*7304104dSAndroid Build Coastguard Worker restarted = true;
119*7304104dSAndroid Build Coastguard Worker continue;
120*7304104dSAndroid Build Coastguard Worker }
121*7304104dSAndroid Build Coastguard Worker
122*7304104dSAndroid Build Coastguard Worker Dwarf_Word stmt_off = 0;
123*7304104dSAndroid Build Coastguard Worker if (dwarf_hasattr (&cudie, DW_AT_stmt_list))
124*7304104dSAndroid Build Coastguard Worker {
125*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
126*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
127*7304104dSAndroid Build Coastguard Worker &stmt_off) != 0)
128*7304104dSAndroid Build Coastguard Worker continue;
129*7304104dSAndroid Build Coastguard Worker }
130*7304104dSAndroid Build Coastguard Worker /* Split units have an implicit offset of 0. */
131*7304104dSAndroid Build Coastguard Worker else if (next_cu->unit_type != DW_UT_split_compile
132*7304104dSAndroid Build Coastguard Worker && next_cu->unit_type != DW_UT_split_type)
133*7304104dSAndroid Build Coastguard Worker continue;
134*7304104dSAndroid Build Coastguard Worker
135*7304104dSAndroid Build Coastguard Worker Dwarf_Off dwp_off;
136*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_cu_dwp_section_info) (next_cu, DW_SECT_LINE,
137*7304104dSAndroid Build Coastguard Worker &dwp_off, NULL) == 0)
138*7304104dSAndroid Build Coastguard Worker stmt_off += dwp_off;
139*7304104dSAndroid Build Coastguard Worker
140*7304104dSAndroid Build Coastguard Worker if (stmt_off == off)
141*7304104dSAndroid Build Coastguard Worker {
142*7304104dSAndroid Build Coastguard Worker *cu = next_cu;
143*7304104dSAndroid Build Coastguard Worker break;
144*7304104dSAndroid Build Coastguard Worker }
145*7304104dSAndroid Build Coastguard Worker }
146*7304104dSAndroid Build Coastguard Worker }
147*7304104dSAndroid Build Coastguard Worker else
148*7304104dSAndroid Build Coastguard Worker *cu = NULL;
149*7304104dSAndroid Build Coastguard Worker
150*7304104dSAndroid Build Coastguard Worker const char *comp_dir;
151*7304104dSAndroid Build Coastguard Worker unsigned address_size;
152*7304104dSAndroid Build Coastguard Worker if (*cu != NULL)
153*7304104dSAndroid Build Coastguard Worker {
154*7304104dSAndroid Build Coastguard Worker comp_dir = __libdw_getcompdir (&cudie);
155*7304104dSAndroid Build Coastguard Worker address_size = (*cu)->address_size;
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker else
158*7304104dSAndroid Build Coastguard Worker {
159*7304104dSAndroid Build Coastguard Worker comp_dir = NULL;
160*7304104dSAndroid Build Coastguard Worker
161*7304104dSAndroid Build Coastguard Worker size_t esize;
162*7304104dSAndroid Build Coastguard Worker char *ident = elf_getident (dbg->elf, &esize);
163*7304104dSAndroid Build Coastguard Worker if (ident == NULL || esize < EI_NIDENT)
164*7304104dSAndroid Build Coastguard Worker goto invalid_data;
165*7304104dSAndroid Build Coastguard Worker address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
166*7304104dSAndroid Build Coastguard Worker }
167*7304104dSAndroid Build Coastguard Worker
168*7304104dSAndroid Build Coastguard Worker if (__libdw_getsrclines (dbg, off, comp_dir, address_size,
169*7304104dSAndroid Build Coastguard Worker srclines, srcfiles) != 0)
170*7304104dSAndroid Build Coastguard Worker return -1;
171*7304104dSAndroid Build Coastguard Worker
172*7304104dSAndroid Build Coastguard Worker if (nlines != NULL)
173*7304104dSAndroid Build Coastguard Worker {
174*7304104dSAndroid Build Coastguard Worker if (srclines != NULL && *srclines != NULL)
175*7304104dSAndroid Build Coastguard Worker *nlines = (*srclines)->nlines;
176*7304104dSAndroid Build Coastguard Worker else
177*7304104dSAndroid Build Coastguard Worker *nlines = 0;
178*7304104dSAndroid Build Coastguard Worker }
179*7304104dSAndroid Build Coastguard Worker
180*7304104dSAndroid Build Coastguard Worker if (nfiles != NULL)
181*7304104dSAndroid Build Coastguard Worker {
182*7304104dSAndroid Build Coastguard Worker if (srcfiles != NULL && *srcfiles != NULL)
183*7304104dSAndroid Build Coastguard Worker *nfiles = (*srcfiles)->nfiles;
184*7304104dSAndroid Build Coastguard Worker else
185*7304104dSAndroid Build Coastguard Worker *nfiles = 0;
186*7304104dSAndroid Build Coastguard Worker }
187*7304104dSAndroid Build Coastguard Worker
188*7304104dSAndroid Build Coastguard Worker return 0;
189*7304104dSAndroid Build Coastguard Worker }
190