xref: /aosp_15_r20/external/elfutils/libdw/dwarf_next_lines.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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